STM32F030 GPIO прерывание
Попытка получить прерывание на A3, чтобы разбудить процессор из спящего режима на rx char, но это не стрельба.
Что определяет, какое прерывание будет активировать вывод GPIO? Я не могу найти его в справочном руководстве
static void EXTI0_1_IRQHandler_Config(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
/* Enable GPIOA clock */
__HAL_RCC_GPIOA_CLK_ENABLE();
GPIO_InitStructure.Mode = GPIO_MODE_IT_RISING;
GPIO_InitStructure.Pull = GPIO_NOPULL;
GPIO_InitStructure.Pin = GPIO_PIN_3;
HAL_GPIO_Init(GPIOA, &GPIO_InitStructure);
/* Enable and set EXTI line 0 Interrupt to the lowest priority */
HAL_NVIC_SetPriority(EXTI0_1_IRQn, 2, 0);
HAL_NVIC_EnableIRQ(EXTI0_1_IRQn);
}
1 ответ
Функции прерываний (кратко) описаны в главе 11 "Прерывания и события", раздел 11.1.3 "Векторы прерываний и исключений".
Итак, номер прерывания EXTI2_3_IRQn
и вы должны определить EXTI2_3_IRQHandler()
звонить HAL_GPIO_EXTI_IRQHandler()
,
Некоторый фон
Есть несколько шагов, связанных с получением функции обратного вызова, вызываемой при возникновении запроса на прерывание.
Каждому запросу на прерывание присваивается номер прерывания, см. Запись позиции в таблице выше. Номер определяется оборудованием, символическое имя присваивается где-то в заголовках машины.
typedef enum {
[...]
EXTI0_1_IRQn = 5, /*!< EXTI Line 0 and 1 Interrupt */
EXTI2_3_IRQn = 6, /*!< EXTI Line 2 and 3 Interrupt */
[...]
} IRQn_Type;
В таблице векторов есть соответствующий указатель на функцию, который должен содержать адрес функции-обработчика. Эта векторная таблица заполняется в модуле запуска, который называется startup_stm32f030x8.s
или что-то подобное, и файл конфигурации компоновщика гарантирует, что таблица заканчивается по правильному физическому адресу при программировании флэш-памяти.
g_pfnVectors:
.word _estack
.word Reset_Handler
.word NMI_Handler
.word HardFault_Handler
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word 0
.word SVC_Handler
.word 0
.word 0
.word PendSV_Handler
.word SysTick_Handler
.word WWDG_IRQHandler /* Window WatchDog */
.word 0 /* Reserved */
.word RTC_IRQHandler /* RTC through the EXTI line */
.word FLASH_IRQHandler /* FLASH */
.word RCC_IRQHandler /* RCC */
.word EXTI0_1_IRQHandler /* EXTI Line 0 and 1 */
.word EXTI2_3_IRQHandler /* EXTI Line 2 and 3 */
...
Записи в фиксированном порядке, так как оборудование заботится только о числовом адресе. Всякий раз, когда EXTI2
или же EXTI3
событие происходит, и IRQ6
включен, он переходит на адрес в 0x00000058
, Таблица выше гарантирует, что адрес EXTI2_3_IRQHandler()
входит в таблицу векторов в 0x00000058
,
Копаясь дальше в модуле запуска, мы находим это
.weak EXTI0_1_IRQHandler
.thumb_set EXTI0_1_IRQHandler,Default_Handler
.weak EXTI2_3_IRQHandler
.thumb_set EXTI2_3_IRQHandler,Default_Handler
и это
Default_Handler:
Infinite_Loop:
b Infinite_Loop
Это означает, что если нет определения для EXTI0_1_IRQHandler()
или же EXTI2_3_IRQHandler()
затем они вызывают бесконечный цикл, хороший для отладки, но не более того. Чтобы реально использовать его, вы должны переопределить этот символ в вашей программе. Если вы посмотрите на GPIO_EXTI
Например, у него есть этот обработчик
void EXTI0_1_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(USER_BUTTON_PIN);
}
определяется в stm32f0xx_it.c
звонить HAL_GPIO_EXTI_IRQHandler()
когда EXTI0
прерывание происходит. Если вы хотите действовать на EXTI3
то у вас должна быть похожая функция
void EXTI2_3_IRQHandler(void)
{
HAL_GPIO_EXTI_IRQHandler(3);
}
звонить HAL_GPIO_EXTI_IRQHandler()
,