About STM32

Прерывания

Сегодня речь пойдет о прерываниях в stm32 и по традиции небольшой ликбез по поводу прерываний в общем.

В любом микроконтроллере прерывание нарушает его нормальный режим работы и заставляет микроконроллер реагировать на какое-то событие, например, кто-то прислал байтик по UART. Прерывания по своей природе происходят в произвольное время, т.е. заранее не известно когда произойдет какое прерывание. После того, как контроллер обработал прерывание, то он возвращается к своей привычной работе.

Теперь по сути: Помню, как в свое время я радовался огромному количеству прерываний в AVR! Например, в Atmega88 их аж 26! Но прерывания в stm32 поразили меня до глубины души! Этот камушек поддерживает до 60 пользовательских прерываний (прерывания от таймера или АЦП, например) и 10 системных прерываний (например, сброс МК или прерывание для отладки). Стоит стразу отметить, что в AVR прерыание отвечает за какое либо событие, например, таймер 0 может генерировать 3 различных прерывания, а в stm32 прерывания сгруппированы по устройствам, т.е. для любого события, скажем, таймера 7 вызывается одно и то же прерывание. Представляете себе, какая мощь тут кроется? Прерывания в stm32 действительно реагируют не только на «ой, а у нас тут что-то случилось..», но и вообще на любой «чих». О различии событий и прерываний в stm32 далее в статье!

Таблица с именами прерываний нарисована в руководстве по программированию на стр. 129, а разрешить прерывание можно следующей командой:

NVIC_EnableIRQ(имя_прерывания_IRQn);

Например:

NVIC_EnableIRQ(USART1_IRQn); //разрешить прерывание от модуля USART1
NVIC_EnableIRQ(TIM7_IRQn); //резрешить прерывание от базового таймера 7

Но это еще не все! Чтобы прерывание срабатывало его необходимо включить в соответствующем регистре переферийного устройства, например:

USART1->CR1 |= USART_CR1_RXNEIE; //разрешить генерацию прерывания при получении данных в модуль USART1

Т.е. командой NVIC_EnableIRQ(имя_прерывания_IRQn); мы разрешаем обрабатывать прерывания от указанного переферийного устройства, а в настройках самого устройства указываем какие прерывания необходимо генерировать.

Обработчик прерывания не представляет из себя ничего интересного, поскольку это обычная функция. Единственное условие – имя функции должно быть вида: имя_прерывания_IRQHandler. Например,обработчик для прерывания от USART1 выглядит так:

void USART1_IRQHandler(void)
{
… // тело прерывания
}

Еще один момент: в stm32 прерывания сгруппированы по переферийным устройствам, т.е. не важно что стряслось у какого-то устройства, мы всегда попадаем в его прерывание. Вернемся к примеру с UART: этот модуль может генерировать прерывание по девяти причинам, и чтобы разобраться, что же все таки произошло, в stm32 существуют события (event stm32).

События в stm32 – это самые обыкновенные флаги! Например, отправили байт по UART – взвелся флаг TC (transmition complete). События для USART1 в stm32 можно найти на 606 странице руководства по программированию. Подобные события (events) существуют для любого переферийного устройства микроконтроллера и тут стоит заметить одну важную деталь!

Флаги устанавливаются в любом случае, в отличии от прерываний, которые генерируются только если разрешены.

Флаги удобны, если не требуется молниеносная реакция на событие. Мы просто время от времени считываем интерисующие флаги и, например, переполнился таймер, но мы можем подождать 1 мкс и обработать это событие без каких либо последствий от задержки(например, отключить какое либо инерционное устройство). Но представим, если мы решим таким неспешным образом обрабатывать события от SPI. В этом случае нас засыпет данными так, что потом разгрестить будет весьма и весьма проблематично и вероятнее всего будет потеря данных. Для предотвращения таких грустных событий уместней использовать прерывание.

 
Хостинг от uCoz