Developer от Бога

DV

четверг, 6 июля 2017 г.

STM32. Прерывание на кнопке

В этой статье обсудим пример применения прерывания по нажатию кнопки, на плате Discovery с микроконтроллером STM32f407VG.
Как упоминалось в статье ранее, прерывание это остановка работы основной программы и выполнение некой функции в случае появления нужного нам события. В плате Discovery с микроконтроллером STM32f407VG кнопка расположена на первой ножке порта - A. На ст. 379 документации RM0090 Reference manual указано, что ножки 1-4 (0-3 в битовом эквиваленте) находятся на нулевой линии EXTI ( EXTI0 ), и в файле StartUp который создается по умолчанию вместе с проектом в редакторе Keil, находится название соответствующей функции-обработчика для этой линии ( EXTI0_IRQHandler ) в нее мы и запишем программу, которая будет выполнятся по нажатию кнопки. В инициализации МК начинаем с подачи тактирования портов на которых светодиоды, кнопка, а также контроллера SYSCFG, в котором укажем ножки, которые мы будем "слушать". Для кнопки на нулевой ножке порта - А регистр MODER оставим по умолчанию ( ножка работает на вход) , а для портов D на которых светодиоды - конфигурация на выход.
По схеме, ножка на которой "висит" кнопка PA0, прижата к земле через сопротивление. При включении чипа, на ножке будет логический ноль, а при нажатии на кнопку - к ножке пойдет ток, но сопротивление R39 не даст создать замыкание, хоть в этот момент ножка будет и дальше прижата к нулю. Это схема подтягивания, её нужно понять , она используется всегда в электронике.



Дальше пойдут настройки Контроллера EXTI. В регистре EXTI_IMR снимем маскирование прерывания, а в регистре EXTI_RTSR установим условие прерывания - при переходе состояния ножки с нуля к единице. В SYSCFG_EXTICR1 установим пин порта которые хотим подключить к нужной линии EXTI.


  1. void EXTI0_IRQHandler (void) //название функции прерывания из файла stm32f4xx.h
  2. { uint32_t i;
  3. GPIOD_ODR=0xF000;
  4. for(i=0;i<=200000;i++);
  5. GPIOD_ODR=0;
  6. for(i=0;i<=200000;i++);
  7. if((GPIOA_IDR&0x1)==0x1)// Если кнопка будет отпущена
  8. EXTI_PR=0x1;//Произойдет выход из прерывания, функция завершит свою работу.
  9. }
  10. void func_two (void)
  11. { uint32_t i;
  12. GPIOD_ODR=0xF000;
  13. for(i=0;i<=1000000;i++);
  14. GPIOD_ODR=0;
  15. for(i=0;i<=1000000;i++);
  16. }
  17. void SystemInit(void)
  18. {
  19. }
  20. int main(void)
  21. {
  22. RCC_GPIO=0x9; //тактирование портов
  23. RCC_SYSCFG=0x4000; //тактирование SYSCFG , для выбора источника прерывания
  24. GPIOA_MODER=0xA8000000;
  25. GPIOA_PUPDR|=0x64000000;
  26. GPIOD_MODER=0x55000000;
  27. GPIOD_PUPDR=0x55000000;
  28. EXTI_IMR=0x1; //Для размаскирования соответствующих линий прерываний
  29. EXTI_RTSR=0x1; //генерация события прерывания по переходу из состояния «0» в состояние «1»
  30. SYSCFG_EXTICR1=0; //пин с какого порта подключается к определенной линии EXTI
  31. NVIC_ISER0=0x40;//из таблицы узнали номера векторов, необходимых нам прерываний. Теперь нужно записать «1» в 6 бит
  32. GPIOD_ODR=0xF000;
  33. while(1)
  34. {
  35. func_two ();
  36. }
  37. }


В данном примере, когда кнопка не нажата, будет выполнятся func_two() с относительно медленным миганием светодиодов. В момент нажатия кнопки, сработает прерывание, и основная программа остановит свое выполнение, пока не завершит работу функция EXTI0_IRQHandler ();

Комментариев нет:

Отправить комментарий