Заголовок сообщения: Как определить какой вход сгенерировал прерывание?
Добавлено: Ср июл 20, 2022 00:28:20
Первый раз сказал Мяу!
Зарегистрирован: Сб мар 20, 2021 23:31:54 Сообщений: 35
Рейтинг сообщения:0
STM32CubeMX создал такой код:
Код:
void EXTI15_10_IRQHandler(void) { /* USER CODE BEGIN EXTI15_10_IRQn 0 */
/* USER CODE END EXTI15_10_IRQn 0 */ HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_13); HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_14); HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_15); /* USER CODE BEGIN EXTI15_10_IRQn 1 */
/* USER CODE END EXTI15_10_IRQn 1 */ }
Как определить какой из входов сгенерировал прерывание?
Юрий48, а вот не нужно калом пользоваться. Достаточно документацию почитать. Если у вас F103, то есть регистры EXTI_EMR и EXTI_IMR, дающие возможность маскировать прерывания и события. Есть регистры EXTI_RTSR и EXTI_FTRS, позволяющие задать, на какой фронт реагировать: восходящий или нисходящий. А в EXTI_PR будут установлены в 1 те биты, которые события сработали. Кроме того, прерывания на каждый бит этих регистров мультиплексируются от разных групп ног (скажем, PA0, PB0 и т.п. управляются младшим битом). Чтобы узнать, от какого порта GPIO сработало прерывание, можно воспользоваться регистром AFIO_EXTICRx (тоже, между прочим, в документации все есть). За биты 10..15 отвечают регистры с x=3 и 4. Регистр GPIO обозначается группой из четырех бит. Т.е. если сработало EXTI_15_10, смотрим, что там у нас в EXTI_PR: ага, установлен бит 12 → прерывание сработало от 12-го пина какого-то регистра GPIO. Смотрим, что там в младшем квартете AFIO_EXTICR4, ага, там 0x2 → сработало прерывание от PC12. Вуаля!
Ну, точней несколько наоборот: чтобы задать, что вы в обработчике прерывания ждете события от PC12, вы должны в младший октет AFIO_EXTICR4 занести двойку. К сожалению, нет возможности настроить прерывания, скажем, сразу на PA12, PB12, PC12… Надо выбрать что-то одно. Правда, у STM32 достаточно богатая периферия, так что EXTI по сути бывают нужны крайне редко (лично я уж забыл, пользовался ли ими когда-либо вообще!).
_________________ Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда. Я на гитхабе, в ЖЖ
Заголовок сообщения: Re: Как определить какой вход сгенерировал прерывание?
Добавлено: Ср июл 20, 2022 22:04:24
Первый раз сказал Мяу!
Зарегистрирован: Сб мар 20, 2021 23:31:54 Сообщений: 35
Рейтинг сообщения:0
Eddy_Em, спасибо за разъяснения. В отладчике кейла пробую посмотреть, что делается в EXTI_PR при нажатии кнопок и ничего не увидел там меняющегося, хотя в регистре GPIOB_IDR реакция на нажатие кнопок адекватная. Решил поиграться с этим регистром в программе. Но не могу к нему обратиться, просто не знаю, как правильно сделать запись (не смешно). Сразу хочу спросить: а можно ли где посмотреть этот синтаксис, какая логика составление этих записей. Вообще то надо определять время нажатия кнопок, поэтому прерывание настроено на срабатывание по обоим фронтам. То есть надо не только определить какая кнопка сработала, но и что было - нажатие или отпускание - фронт. Понятно, что надо опрашивать регистр в цикле. Учитывая мой уровень знаний, лучшим вариантом было бы привести конкретный код, например, определения срабатывания конкретной кнопки.
_________________ Linux rules! Windows must die. Здравомыслящий человек добровольно будет пользоваться мастдаем лишь в двух случаях: под дулом автомата или под влиянием анального зонда. Я на гитхабе, в ЖЖ
Юрий48, из какой то сетевой шпаргалки (кажется, для F103), но EXTI вроде везде +/- одинаков.... Спойлер
Код:
/******************* * EXTI *******************/ /* AFIO->EXTICR[0..3] ---------- В контроллере EXTI есть 19 линий внешних прерываний. Первые 16 мультиплексируются на биты физических портов МК, два оставшихся - на прерывания от PVD (программируемый датчик напряжения питания), RTC Alarm event и USB Wakeup event. На линию EXTI0 мультиплексируется бит 0 портов A,B,C,D,E,F,G На линию EXTI1 мультиплексируется бит 1 портов A,B,C,D,E,F,G ....... На линию EXTI15 мультиплексируется бит 15 портов A,B,C,D,E,F,G За мультиплексирование отвечают регистры EXTICR1, EXTICR2, EXTICR3, EXTICR4 домена AFIO. В CMSIS они сгруппированы в массив EXTICR[0..3], но битовые константы оперируют литералами EXTICR1..EXTICR4 AFIO->EXTICR[0..3] Регистор EXTICR[0] отвечает за биты 0, 1, 2, 3 Регистор EXTICR[1] отвечает за биты 4, 5, 6, 7 Регистор EXTICR[2] отвечает за биты 8, 9, 10, 11 Регистор EXTICR[3] отвечает за биты 12, 13, 14, 15 Соответствено, что бы настроить мультиплексирование соответствующего бита порта в контроллер EXTI, необходимо включить тактирование альтернативных функций AFIOEN: RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; EXTIx[3:0]: EXTI x configuration, где x=0..3 для регистра AFIO_EXTICR1; x=4..7 для регистра AFIO_EXTICR2; x=8..11 для регистра AFIO_EXTICR3; x=12..15 для регистра AFIO_EXTICR4. Биты (битовые поля) модифицируются программно и используются для выбора источника сигнала для линии внешнего прерывания EXTIx, x=0..15. В зависимости от значения битового поля, используется вход одного из портов ввода/вывода микроконтроллера (GPIO): 0000: PA[x] вывод микроконтроллера; 0001: PB[x] вывод микроконтроллера; 0010: PC[x] вывод микроконтроллера; 0011: PD[x] вывод микроконтроллера; 0100: PE[x] вывод микроконтроллера; 0101: PF[x] вывод микроконтроллера; 0110: PG[x] вывод микроконтроллера.
В CMSIS уже есть готовые константы для битовых полей: AFIO_EXTICRx_EXTInn - маска битов для прерывания nn в регистре EXTICRx AFIO_EXTICRx_EXTInn_PA - v AFIO_EXTICRx_EXTInn_PB - v AFIO_EXTICRx_EXTInn_PC - v AFIO_EXTICRx_EXTInn_PD - v AFIO_EXTICRx_EXTInn_PE - v AFIO_EXTICRx_EXTInn_PF - v AFIO_EXTICRx_EXTInn_PG - готовые битовые маски для портов A..G (помним nn=0..3->x=1, nn=4..7->x=2, nn=8..11->x=3,nn=12..15->x=4)
Регистры контроллера внешних прерываний EXTI
EXTI->IMR Interrupt mask register - Регистр маски прерываний --------- MR18 MR17 MR16 MR15 MR14 MR13 MR12 MR11 MR10 MR9 MR8 MR7 MR6 MR5 MR4 MR3 MR2 MR1 MR0 ---------- Разрешение или запрет контроллеру EXTI генерацию прерываний (для каждой линии имеется отдельный бит разрешения). MRx: Interrupt Mask on line x, x=0..17 - Бит, разрешающей генерацию прерываний от соответствующей линии EXTI: 0: не формируются запросы на прерывание от соответствующей линии EXTIx; 1: разрешается формировать запросы на прерывание от соответствующей линии EXTIx.
EXTI->EMR Event mask register - Регистр маски событий пробуждения --------- MR18 ..... MR0 ---------- Разрешение или запрет контроллеру EXTI генерацию событий (для каждой линии имеется отдельный бит разрешения). MRx: Event mask on line x, x=0..18 - Бит, разрешающей генерацию событий от соответствующей линии EXTI: 0: не формируются сигналы события от соответствующей линии EXTIx; 1: разрешается формировать сигналы события от соответствующей линии EXTIx
EXTI->RTSR Rising trigger selection register - Регистр выбора линий EXTI, запускаемых нарастающим входным сигналом. EXTI->FTSR Falling trigger selection register - Регистр выбора линий EXTI, запускаемых спадающим входным сигналом. ---------- TR18 ..... TR0 ---------- TRx: Rising trigger event configuration bit of line x=0..18 - Бит определяет, что на входной линии x контроллера EXTI требуется обнаруживать нарастающий фронт сигнала: 0: отключён запуск нарастающим фронтом (как для прерываний, так и для событий) для данной линии; 1: включён запуск нарастающим фронтом (как для прерываний, так и для событий) для данной линии. TRx: Falling trigger event configuration bit of line x, x=0..18 - Бит определяет, что на входной линии x контроллера EXTI требуется обнаруживать спадающий фронт сигнала: 0: отключён запуск спадающим фронтом (как для прерываний, так и для событий) для данной линии; 1: включён запуск спадающим фронтом (как для прерываний, так и для событий) для данной линии.
EXTI->SWIER Software interrupt event register - Регистр для программной генерации прерываний и событий EXTI. ---------- SWIER18 ..... SWIER0 ---------- SWIERx: Software interrupt on line x, x=0..17 Запись 1 в этот бит, когда он содержит 0, приводит к установке соответствующего отложенного бита в регистре EXTI_PR (если разрешено регистром маски EXTI_IMR). Если прерывания для данной линии разрешены, генерируется запрос на прерывание. Бит сбрасывается при сбросе соответствующего бита в регистре EXTI_PR, который, в свою очередь, сбрасывается записью 1 в этот бит.
EXTI->PR Pending register - Регистр отложенных прерываний -------- PR18 ..... PR0 ---------- PRx: Pending bit - Бит отложенного прерывания: 0: не генерировалось запросов на прерывание; 1: произошла генерация запроса на прерывание. Этот бит устанавливается при обнаружении отслеживаемого фронта входного сигнала на внешней линии. Бит сбрасывается путём записи 1 в этот бит.
Вектора прерываний (описаны в startup_stm32f103xb.s): EXTI0_IRQHandler Прерывание от линии 0 EXTI EXTI1_IRQHandler Прерывание от линии 1 EXTI EXTI2_IRQHandler Прерывание от линии 2 EXTI EXTI3_IRQHandler Прерывание от линии 3 EXTI EXTI4_IRQHandler Прерывание от линии 4 EXTI EXTI9_5_IRQHandler Прерывание от линий [9:5] EXTI EXTI15_10_IRQHandler Прерывание от линий [15:10] EXTI Внутри обработчика прерывания необходимо проверить, какая линия была виновником вызова прерывания. Это делается проверкой битов в регистре EXTI_PR. Так же необходимо сбросить бит прерывания, записав в этот бит 1.
Кроме разрешения прерывания в регистрах контроллера EXTI еше необходимо разрешить соответствующие прерывания в контроллере NVIC: NVIC_EnableIRQ(nnn); Тут nnn - имя вектора прерываний (определены в stm32f103xb.h) PVD_IRQn - PVD through EXTI Line detection Interrupt EXTI0_IRQn - EXTI Line0 Interrupt EXTI1_IRQn - EXTI Line1 Interrupt EXTI2_IRQn - EXTI Line2 Interrupt EXTI3_IRQn - EXTI Line3 Interrupt EXTI4_IRQn - EXTI Line4 Interrupt EXTI9_5_IRQn - External Line[9:5] Interrupts EXTI15_10_IRQn - External Line[15:10] Interrupts */
// обработчик прерывания void EXTI15_10_IRQHandler(void) { if (EXTI->PR & EXTI_PR_PIF12) { EXTI->PR |= EXTI_PR_PIF12; // нужное нам действие } }
// настройка прерывания //GPIO_B12 - key RCC->APB2ENR |= RCC_APB2ENR_IOPBEN; GPIOB->CRH &= ~(GPIO_CRH_MODE12_Msk | GPIO_CRH_CNF_Msk); // input GPIOB->CRH |= GPIO_CRH_CNF12_1; // with pull resistor GPIOB->ODR |= GPIO_ODR_ODR12; // pull to UP // EXTI RCC->APB2ENR |= RCC_APB2ENR_AFIOEN; AFIO->EXTICR[3] &= ~AFIO_EXTICR4_EXTI12; // мапим EXTI12 AFIO->EXTICR[3] |= AFIO_EXTICR4_EXTI12_PB; // на порт B (GPIO_B_12) EXTI->IMR |= EXTI_IMR_IM12; // прерывание от IO_B12 EXTI->RTSR |= EXTI_RTSR_RT12; // по нарастающему фронту (Rising) EXTI->FTSR |= EXTI_FTSR_FT12; // по спадающему фронту (Falling) NVIC_EnableIRQ(EXTI15_10_IRQn);
Отвечу на первоначальный вопрос, если конечно еще актуально.
В ваш код необходимо вставить функцию, которую будет вызывать HAL при срабатывании прерывании по GPIO:
Код:
void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) { if (GPIO_Pin == GPIO_PIN_13) { // Сработало прерывание на 13 пине. // Aналогичные проверки можно сделать и для остальных пинов. } }
где, GPIO_Pin - пин на котором сработало прерывание.
Пользующиеся кубами как правило не знают что такое "Reference manual"
А при чём здесь собственно "куб"? IDE появились только в этом веке. В прошлом веке для МК вообще всё на ассемблерах писалось. Но RM тогда существовали. Просто их кто-то изучал, а кто-то нет, а кто-то и вовсе не знал о их существовании.
Сейчас этот форум просматривают: нет зарегистрированных пользователей и гости: 16
Вы не можете начинать темы Вы не можете отвечать на сообщения Вы не можете редактировать свои сообщения Вы не можете удалять свои сообщения Вы не можете добавлять вложения