Внешние прерывания STM32.

Внешние прерывания STM32.

Плюсом внешних прерываний является то, что они фиксируют переход от одного логического уровня к другому, а не сам уровень.

Предположим нам надо зафиксировать когда изменится напряжение на какой-то ножке и экстренно выполнить определённый набор инструкций. Самый простой алгоритм выглядит следующим образом, через определённые интервалы времени опрашиваем вывод и анализируем изменилось ли его состояние. Если время между опросами будет большим, то мы можем пропустить переход, а если мало, то большая часть процессорного времени будет тратиться на опрос вывода и ожидание события. Понятно, что рассмотренный алгоритм нам не подходит. Что же делать? Решение этой задачи уже давно придумано за нас инженерами, разрабатывающими микроконтроллеры, название его — внешнее прерывание.

Как это работает? При изменении логического уровня на ножке микроконтроллера, он бросает все свои дела и бежит выполнять инструкции, расположенные по заданному адресу, наше дело разместить по этому адресу нужный код.

Теперь от общей теории перейдём к частным вариантам реализации. У AVR под внешние прерывания отведены конкретные выводы, у Atmega16 их 4. У STM32 дело с внешними прерываниями обстоит интереснее, управляет внешними прерываниями контроллер EXTI. Любой из выводов порта может быть настроен на работу с внешними прерываниями, но количество выводов GPIO одновременно настроенных на работу с внешними прерываниями не может превышать шестнадцать. Эти выводы соединяются с EXTI c помощью мультиплексоров.
Внешние прерывания STM32.

Если посмотреть на картинку с мультиплексорами видно, что номер мультиплексора совпадает с номером вывода и мы не можем настроить на прерывание два вывода с одинаковыми номерами, то есть нельзя одновременно настроить на внешние прерывания PB0 и PA0.

Есть ещё 4 линии, которые подключаются не к GPIO, а к периферии:
  • EXTI 17 – выход PVD
  • EXTI 18 – событие от RTC_Alarm
  • EXTI 19 – событие от USB_Wakeup
  • EXTI 20 – событие от Ethernet_Wakeup


Кроме привычных прерываний, контроллер EXTI может генерировать события и программные прерывания.

Событие — выставляется флаг, без перехода в обработчик прерывания.

Программное прерывание — то же прерывание, но вызывается вручную, записью '1' в соответствующий регистр.

Существует всего семь обработчиков внешних прерываний: EXTI0, EXTI1, EXTI2, EXTI3, EXTI4, EXTI9_5, EXTI15_10. Видно, что не каждое внешнее прерывание от GPIO имеет отдельный обработчик, некоторые из них совмещены.

Давайте рассмотрим регистры необходимые для настройки внешних прерываний.
Первым делом надо включить тактирование порта и альтернативных функций так, как прерывание — это альтернативная функция порта.

	RCC->APB2ENR |= RCC_APB2ENR_AFIOEN | RCC_APB2ENR_IOPEEN;

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

Для настройки мультиплексоров выделены 4 регистра AFIO_EXTICRx разделённые на 4 секции, по 4 бита в каждой, мы рассмотрим один из них.
Внешние прерывания STM32.

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

         //выбор порта и пина для внешнего прерывания
	 AFIO->EXTICR [0] |= AFIO_EXTICR1_EXTI0_PE;
        //если хотим выбрать первый пин порта B
        AFIO->EXTICR [0] |= AFIO_EXTICR1_EXTI1_PB;


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

EXTI_EMR – регистр маскировки событий, запись '1' в соответствующий бит разрешает событие, по умолчанию там нули.

EXTI_FTSR и EXTI_RTSR – определяют по какому фронту будет возникать прерывание. При записи '1' в соответствующий бит EXTI_FTSR по спадающему фронту, в EXTI_RTSR – по возрастающему.

EXTI_SWIER – программный вызов события/прерывания, запись '1' в соответствующий бит вызывает генерацию события/прерывания.

EXTI_PR – флаг возникновения события/прерывания, сбрасывается вручную при записи '1'.

Теперь давайте рассмотрим простой пример, в котором по нажатию кнопки, которая подключена к нулевому выводу порта E, будет генерироваться прерывание.


#include "stm32f10x.h"

void EXTI0_IRQHandler(void)
{
        
        //сбрасываем флаг прерывания
	EXTI->PR |= EXTI_PR_PR0; 
}	
int main(void)
{
        //включаем тактирование порта и альтернативных функций
        RCC->APB2ENR |= RCC_APB2ENR_AFIOEN | RCC_APB2ENR_IOPEEN;
        //настраиваем вывод на вход с подтяжкой
	GPIOE->CRL &= ~GPIO_CRL_CNF0_0;
	GPIOE->CRL |= GPIO_CRL_CNF0_1;
	GPIOE->CRL	&= ~GPIO_CRL_MODE0 ;
        //подтягиваем к питанию
	GPIOE->BSRR |= GPIO_BSRR_BR0;
	
         //выбор порта и пина для внешнего прерывания
	 AFIO->EXTICR [0] |= AFIO_EXTICR1_EXTI0_PE;
         //по спадающему фронту
	 EXTI->FTSR |= EXTI_FTSR_TR0;
         //устанавливаем маску
         EXTI->IMR |= EXTI_IMR_MR0;
         //разрешаем прерывания  EXTI0
	 NVIC->ISER[0] = NVIC_ISER_SETENA_6;
         //разрешаем прерывания глобально
        __enable_irq ();
       while(1)
       {

       }
}

комментарии
5