Я работаю над проектом, включающим микроконтроллер STM32 (точнее, на плате STM32303C-EVAL), который должен реагировать на внешнее прерывание. Я хочу, чтобы реакция на внешнее прерывание была максимально быстрой. Я изменил пример стандартной периферийной библиотеки с веб-страницы ST, и текущая программа просто включает светодиод на каждом последующем фронте на PE6:
#include "stm32f30x.h"
#include "stm32303c_eval.h"
EXTI_InitTypeDef EXTI_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
static void EXTI9_5_Config(void);
int main(void)
{
/* Initialize LEDs mounted on STM32303C-EVAL board */
STM_EVAL_LEDInit(LED1);
/* Configure PE6 in interrupt mode */
EXTI9_5_Config();
/* Infinite loop */
while (1)
{
}
}
// Configure PE6 and PD5 in interrupt mode
static void EXTI9_5_Config(void)
{
/* Enable clocks */
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_GPIOD | RCC_AHBPeriph_GPIOE, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_SYSCFG, ENABLE);
/* Configure input */
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN;
GPIO_InitStructure.GPIO_PuPd = GPIO_PuPd_DOWN;
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/* Connect EXTI6 Line to PE6 pin */
SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOE, EXTI_PinSource6);
/* Configure Button EXTI line */
EXTI_InitStructure.EXTI_Line = EXTI_Line6;
EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
EXTI_InitStructure.EXTI_LineCmd = ENABLE;
EXTI_Init(&EXTI_InitStructure);
/* Enable and set interrupt to the highest priority */
NVIC_InitStructure.NVIC_IRQChannel = EXTI9_5_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
Обработчик прерываний выглядит так:
void EXTI9_5_IRQHandler(void)
{
if((EXTI_GetITStatus(EXTI_Line6) != RESET))
{
/* Toggle LD1 */
STM_EVAL_LEDToggle(LED1);
/* Clear the EXTI line 6 pending bit */
EXTI_ClearITPendingBit(EXTI_Line6);
}
}
В этом конкретном случае прерывания создаются внешним программируемым генератором функций, работающим с частотой 100 Гц. Изучив ответ MCU на осциллографе, я был довольно удивлен, что MCU требуется почти 1,32 мегапикселя для начала обработки прерывания:
Когда MCU работает на частоте 72 МГц (я предварительно проверил вывод SYSCLK на выводе MCO), это составляет почти 89 тактов. Разве ответ MCU на прерывание не должен быть намного быстрее?
PS Код был скомпилирован с помощью IAR Embedded Workbench и оптимизирован для максимальной скорости.
if{}
оператор необходим, потому что подпрограмма прерывания не знает, каков источник прерывания.