|
|||||||
ARM. Учебный курс. Внешние прерывания
Время создания: 02.03.2022 22:52
Раздел: Компьютер - Аппаратное обеспечение - Микроконтроллеры ARM
Запись: xintrea/mytetra_syncro/master/base/1646250737a3sl4vrie1/text.html на raw.github.com
|
|||||||
|
|||||||
Внешние прерывания активизируются по изменению логического уровня на ноге контроллера. Удобно для обработки срочных событий от внешней периферии, иногда на них делают обработку кнопок. Т.к. они могут будить контроллер из глубокой спячки. У STM32 за внешние прерывания отвечает EXTI контроллер. Его основные возможности: До 20 линий прерываний (в реальности несколько меньше, зависит от контроллера) Независимая работа со всеми линиями. Каждой линии присвоен собственный статусный бит в спец регистре Улавливает импульсы длительность которых ниже меньше периода частоты APB2
EXTI Может генерировать:
Сама структура связи EXTI следующая:
Т.е. у нас есть 16 EXTI линий к которым мы можем подключать выводы порта. Причем группируются они по номерам пинов. Т.е. мы не можем на разные прерывания навесить, например, PA0 и PB0 либо одно, либо другое. Придется выбирать. Мультиплексоры управляются из группы регистров AFIO_EXTICR*.
Кстати, интересный факт. Даташит утверждает следующее:
8.4 Note: To read/write the AFIO_EVCR, AFIO_MAPR and AFIO_EXTICRx registers, the AFIO clock should first be enabled. Refer to Section 6.3.7: APB2 peripheral clock enable register (RCC_APB2ENR).
Т.е. для записи в регистры AFIO_EXTICRx должно быть включено тактирование AFIO. Проверил без него — все работает, значения записываются, прерывания работают. Может я где то ошибся? Прогнал под JTAG в Keil — нет, AFIO CLOCK Disabled, а все работает. Странно.
Но после выяснилось, что без включения AFIO мультиплексоры не работают. Т.е. сигнал будет передаваться ТОЛЬКО от порта А, т.к. это дефолтное значение мультиплексоров. Причем вне зависимости от того, что вы там себе настроили в программе. Прикиньте какие грабли! Забыл включить AFIO и привет! Ладно бы прерывания тупо не работали, а они будут работать, но совсем не от того вывода который вы выставили. А если там что-то дрыгается, то прерывание у вас срабатывать будет, но совсем не тогда, когда вы ждете. Попробуйте выловить такую фигню! Так что AFIO надо включать до выбора канала мультиплексора! У меня же все работало потому, что выбранные линии порта совпали с портом А, стоящим по умолчанию. ВСЕГДА затактирывайте AFIO если используете альтернативные функции портов, избежите кучи глюков.
Есть еще четыре EXTI линии которые подключены не к GPIO, а к разной периферии. ● EXTI 16 — PVD выход ● EXTI 17 — событие от RTC Alarm ● EXTI 18 — событие от USB Wakeup ● EXTI 19 — событие от Ethernet Wakeup (там где есть эзернет на борту)
Конфигурация и регистры AFIO_EXTICR* — выбор вывода. Сначало надо выбрать в AFIO какой канал у нас к чему подключен. За это отвечает группа регистров AFIO_EXTICR* их там 4 штуки. Вот структура первого: Т.е. у нас тут типичный мультиплексор. В первом регистре первые 4 канала EXTI, во втором регистре (AFIO_EXTICR2) следующая четверка и так до 16го. Мы просто выбираем на какой канал какой порт будет подцеплен. Т.е. чтобы, например, повесить прерывание на PD2 надо в EXTI2 (биты с 8 по 11) записать 0011. Ногу выбрали, дальше приступаем к настройке непосредственно прерываний.
EXTI_IMR — Регистр масок прерываний. Единичка в этом регистре в соответствующем бите разрешает прерывание на соответствующий канал EXTI. После сброса там нули. Т.е. все прерывания внешние локально запрещены.
EXTI_EMR — Регистр масок событий. Единичка тут разрешает событие на канал. События отличается от прерывания тем, что контроллер только сигнализирует о нем, но никуда, ни по какому вектору, не бежит выполнять код. Еще события умеют чуять некоторые периферийные устройства. EXTI_RTSR и EXTI_FTSR — Регистры определяющие когда срабатывать. По какому фронту? Единичка в EXTI_RTSR даст событие по восходящему фронту, а единичка в EXTI_FTSR по спадающему. Можно поставить оба бита и ловить прерывание на подъеме и спаде.
EXTI_SWIER — Регистр софтверного запуска прерывания. Т.е. если нам надо вручную, принудительно, его запустить, то надо сюда записать в конкретный бит. Записываем в EXTI_SWIER 1 и у нас вскакивает бит в EXTI_PR, а контроллер генерирует событие и, если разрешено, уходит на прерывание.
EXTI_PR — Ну и бит собственно флажка события, по которому происходит вызов прерывания. Обратите внимание на обозначение обращения с ним — rc_w1. Это следует читать как read/clear = write 1. Т.е. мы этот бит можем читать, а чтобы его сбросить надо в него записать единичку. Как на AVR прям :) При переходе в прерывание его надо сбрасывать вручную! Иначе на выходе с прерывания будет «и снова здравствуйте!».
Теперь покажу пример кода работы с прерыванием. Отдельный пример создавать мне лень, возьму кусок кода из прошлого примера про NVIC там как раз были внешние прерывания:
Вот, собственно, и все. Ничего сложного. |
|||||||
Так же в этом разделе:
|
|||||||
|
|||||||
|