Сен 162020
 

Arduino STM32 — внешние прерывания

Arduino

df7438.jpg

Эта статья является продолжением описания платы Blue Pill (Arduino STM32). Начало здесь.

Описание сделано предельно упрощённо, и рассчитано на программирование в IDE Arduino.

Прерывание — это сигнал, при возникновении которого, работа основного цикла (void loop) программы мгновенно прерывается, и выполняется функция, которую называют обработчиком прерывания (см. ниже пример кода). После того как эта функция завершится, работа основного цикла возобновится с места остановки.

Выполнение функции обработки прерывания называют вектором прерывания, то есть, если можно так выразиться, отклонением от основного цикла.

Во время обработки прерывания не работают функции delay() и millis().

Прерывания от таймеров здесь не рассматриваются, про это в следующей части.

Внешние прерывания вызываются при поступлении сигналов от какого-либо устройства, например, изменение состояния на «ножке» МК…

Предположим у Вас есть программа, которая в числе прочего, должна считывать импульсы с какого-то источника. Чтобы не пропускать эти импульсы, нужно пин, к которому подключён источник, запрограммировать на прерывание и написать обработчик (допустим увеличение переменной на единицу, мы же импульсы считаем). Таким образом, при появлении импульса, программа будет прерываться и выполнять действие описанное в обработчике.

В обработчике прерывания должно быть минимум кода, всё что возможно выносите в основной цикл.

Любой пин может использоваться для прерываний, но не более 16-ти одновременно. Это определяется количеством EXTI Line — линий внешних прерываний (External Interrupts Lines), к которым подключены пины.

К линии EXTI0 подключены нулевые пины — PB0 и PA0, к линии EXTI1 первые — PA1 и PB1 и т.д. Обращайте внимание на то, что выведено на пины, например РА11 и РА12 это USB, поэтому вряд ли стоит заводить на них внешние сигналы.

Не получится одновременно использовать несколько пинов находящихся на одной линии, можно только какой-то один (это замечание относится к программированию в IDE Arduino). Соответственно если Вам нужно «слушать» прерывания от двух источников, нельзя использовать PB0 и PA0, нужно выбрать пины из разных линий.

381e31.png
Arduino STM32

Еще есть линии внешних прерываний не выведенные непосредственно на «ножки»…

EXTI16 – подключена к PVD (программируемый детектор напряжения).
EXTI17 – RTC Alert event.
EXTI18 – USB Wakeup event.
EXTI19 – Ethernet Wakeup event.
схема из datasheetcf9b13.png

Запуск прерывания — attachInterrupt(pin, function, mode);
Отключение — detachInterrupt(pin);

pin — номер пина
function — функция, которая будет вызываться при срабатывании прерывания.
mode — тип сигнала (RISING, FALLING, CHANGE).

RISING — с LOW на HIGH.
FALLING — с HIGH на LOW.
CHANGE — с LOW на HIGH и с HIGH на LOW.

То есть то же самое, что и у Arduino, только нет режима LOW.

Переменные внутри функции прерывания должны иметь модификатор volatile.

Пример прослушивания трёх внешних прерываний:

#define signal1 PA0 // пин на линии EXTI0 #define signal2 PA1 // пин на линии EXTI1 #define signal3 PA2 // пин на линии EXTI2 #define LED1 PB0 #define LED2 PB1 volatile int state1 = LOW; volatile int state2 = LOW; volatile int state3 = LOW; void setup() { Serial.begin(115200); pinMode(signal1, INPUT_PULLDOWN); pinMode(signal2, INPUT_PULLDOWN); pinMode(signal3, INPUT_PULLDOWN); pinMode(LED1, OUTPUT); pinMode(LED2, OUTPUT); pinMode(LED_BUILTIN, OUTPUT); // PC13 attachInterrupt(signal1, func_interrup_1, RISING); // инициализация первого прерывания attachInterrupt(signal2, func_interrup_2, FALLING); // инициализация второго прерывания attachInterrupt(signal3, func_interrup_3, CHANGE); // инициализация третьего прерывания } void loop() { Serial.println("Hello"); delay(2000); } void func_interrup_1() // обработчик первого прерывания { if(state1 == HIGH) state1 = LOW; else state1 = HIGH; digitalWrite(LED1, state1); } void func_interrup_2() // обработчик второго прерывания { if(state2 == HIGH) state2 = LOW; else state2 = HIGH; digitalWrite(LED2, state2); } void func_interrup_3() // обработчик третьего прерывания { if(state3 == HIGH) state3 = LOW; else state3 = HIGH; digitalWrite(LED_BUILTIN, state3); }

Теперь, если подать на пины PA0, PA1, PA2 сигналы (например с ардуины — чередующиеся digitalWrite(5, HIGH); delay(50); и digitalWrite(5, LOW); delay(50);), то светики на пинах PB0, PB1, PC13 будут дружно моргать. PC13 будет мигать в два раза чаще. При этом задержка в цикле void loop() не будет ни на что влиять.

Warning! Пины PA0, PA1, PA2 трехвольтовые, сигнал подавайте через делитель напряжения, либо укажите другие ноги.картинка

У микроконтроллера stm32 (в отличии от Arduino) у прерываний есть приоритет, высший у линии EXTI0, низший у линии EXTI19. Соответственно если одновременно произойдут два или более прерывания, то приоритет будет у линии с меньшим номером. Прерывания на линии с большим номером будут поставлены в очередь.

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

На этом всё.

Форум (рус.)

Руководство (рус.) по stm32

Телеграм-чат STM32

Следите за обновлениями ядра.

Ссылки:
External Interrupts

attachInterrupt

detachInterrupt

Понравилось? Поделитесь:

:

Sorry, the comment form is closed at this time.