STM32. Прерывания
В этой статье мы поделимся базовыми знаниями о практической реализации механизма прерываний от различных источников в этих микроконтроллерах. В частности будут рассмотрены прерывания от кнопки и по таймеру, а также создание внешних переменных. Напомню, что наш курс сквозной и мы рассчитываем при написании этой статьи, что читатель ознакомился с предыдущими статьями.
Внешние прерывания
Ранее мы рассматривали подключение кнопки к выводу контроллера и опрос ее состояния в основном цикле. Такая реализация часто встречается на практике, но в некоторых случаях удобнее использовать прерывания.
Для начала создадим проект в CubeMX. Необходимо запустить его и выбрать используемую вами отладочную плату. В нашем случае это Nucleo64 на контроллере STM32F030R8T6. Подготовка проекта была описана в предыдущих статьях.
Если посмотреть в параметрах преднастроенного проекта, то можно увидеть, что голубая кнопка, подключенная к выводу PC13, уже настроена в режиме прерываний.
Чтобы это прерывание начало срабатывать, необходимо включить его. Для этого перейдите во вкладку "Configuration" и в меню "NVIC" установите галочку "EXTI line 4 to 15 interrupts". Обратите внимание, что это прерывание генерируется одно на несколько каналов. Это означает, что если надо подключить несколько кнопок, то и в обработчике прерывания потом придется опрашивать эти кнопки, чтобы выяснить какая из них конкретно была нажата.
Также обратите внимание, что в пункте меню "GPIO" можно установить режим работы прерывания. По умолчанию установлено "External Interrupt Mode with Falling edge trigger detection", то есть прерывание генерируется по спаду.
На этом предварительная настройка окончена. Можно сгенерировать проект и приступить к написанию кода.
После запуска Keil uVision в папке "Application/User" необходимо найти файл "stm32f0xx_it.c". Это файл в котором уже сгенерированы обработчики различных прерываний. Нас интересует обработчик EXTI4_15_IRQHandler.
В обработчике этого прерывания мы вызовем функцию HAL_GPIO_TogglePin(). Она изменяет состояние вывода на противоположное. На плате Nucleo есть светодиод, подключенный к выводу PA5. Если мы скомпилируем и загрузим этот проект, то кнопка начнет переключать состояние светодиода на противоположное.
В результате проделанной работы мы получили то, что микроконтроллер в основном цикле не делает ничего, но при нажатие кнопки запускается подпрограмма, которая выполняет определенные действия.
Прерывания от таймера
Ранее мы рассматривали как организовать мигание светодиоды в основном цикле. Мы делали это самым простым способом, основная проблема которого в том, что программа почти все время остановлена вызовом функции HAL_Delay().
С другой стороны в микроконтроллерах есть таймеры, которые могут самостоятельно генерировать прерывания и выполнять какие-то действия. При этом основная программа будет останавливаться только на время, необходимое для выполнения команд обработчика прерываний. Мы рассмотрим самый простой пример работы таймера, когда он генерирует прерывания через равные интервалы времени.
В первую очередь требуется включить таймер. Для этого в CubeMX во вкладке "Pinout" включите таймер. Для примера мы включили 14ый таймер.
Во вкладке "Clock Configuration" можно изменить или просто проверить тактовую частоту таймера. У нас установлена тактовая частота 48МГц.
Затем переходим на вкладку "Configuration" и в меню "TIM14" настраиваем таймер. Делитель "Prescaler (PSC — 16 bits value)" мы установили на 47999. То есть тактовая частота таймера 48МГц будет делиться в 48000 раз (так как счет идет от нуля) и прибавление внутреннего счетчика таймера будет происходить раз в одну миллисекунду. В пункте "Counter Period" устанавливается значение счетчика, при котором генерируется прерывание и счет начинается заново. Мы хотим, чтобы светодиод изменял свое состояние раз в секунду, поэтому установили значение 999. Таймер будет с периодичностью в 1мс считать от 0 до 999, то есть прерывание будет вызываться каждую тысячу миллисекунд.
Также на вкладке таймера "NVIC Settings" надо установить галочку, разрешающую глобальные прерывания от таймера.
Обратите внимание, что в сводной таблице таймеров "NVIC" также появилась новая строка с таймером и прерывания от него включены.
Генерируем проект заново и открываем файл main.c. В нем нам потребуется в ручную запустить таймер в нужном нам режиме. Делается это командой HAL_TIM_Base_Start_IT(&htim14);. IT подразумевает запуск таймера в режиме прерываний. Указатель &htim14 передает функции структуру данных, в которой описаны настройки таймеров. Она генерируется автоматически CubeMX’ом.
Обратите внимание, что функция HAL_TIM_Base_Start_IT(&htim14); вызывается до вхождения в бесконечный цикл.
Далее снова переходим в файл "stm32f0xx_it.c" и в обработчике прерывания TIM14_IRQHandler добавляем код, изменяющий состояние вывода.
После компиляции и загрузки светодиод начнет мигать раз в секунду. И снова, благодаря использованию прерываний, у нас полностью разгружен основной цикл и светодиод мигает в фоновом процессе.
Внешние переменные
На практике очень часто в прерывании возникает необходимость изменять переменные, которые используются в основном цикле. То есть обращаться к переменным, описанным в другом файле.
Для примера запустим мигание светодиодом в основном цикле с переменной частотой, а частоту будем изменять в прерывании от кнопки.
Начнем с создания переменной в файле main.c.
Далее закомментируем функцию запуска таймера в 96ой строке и добавим код, мигающий светодиодом:
Если мы сейчас скомпилируем и загрузим эту программу, то светодиод начнет мигать с периодичностью 200мс. Но мы хотим изменять эту периодичность при помощи кнопки.
Поэтому переходим в файл stm32f0xx_it.c и создаем в нем внешнюю переменную extern uint16_t pause;. Служебное слово extern расширяет область видимости переменной. Важно то, что переменная инициализируется, но не определяется. То есть ей не присваивается никакое значение.
Осталось только добавить изменение этой переменной в прерывании. В строках 103, 104 мы просто прибавляем 100, если переменная меньше тысячи и присваиваем значение, если она равна тысяче.
Скомпилированная программа при старте будет мигать светодиодом быстро, а при нажатии кнопки будет изменять частоту мигания светодиодом.
Мы разобрали самые простые варианты прерываний, но даже они очень эффективные и будут использоваться нами в будущих статьях. Ссылки на остальные статьи цикла можно найти здесь.
Мы будем очень рады, если вы поддержите наш ресурс и посетите магазин наших товаров shop.customelectronics.ru.
Метки: extern, interrupt, STM32, курс, прерывания, программирование, таймер Просмотров: 14731