Ich arbeite an einem Projekt, das eine STM32-MCU (genauer gesagt auf der STM32303C-EVAL-Karte) umfasst, die auf einen externen Interrupt reagieren muss. Ich möchte, dass die Reaktion auf den externen Interrupt so schnell wie möglich erfolgt. Ich habe ein Beispiel für eine Standard-Peripheriebibliothek auf der ST-Webseite geändert und das aktuelle Programm schaltet einfach eine LED bei jeder aufeinanderfolgenden ansteigenden Flanke auf PE6 um:
#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);
}
Der Interrupt-Handler sieht folgendermaßen aus:
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);
}
}
In diesem speziellen Fall werden die Interrupts von einem externen programmierbaren Funktionsgenerator erzeugt, der mit 100 Hz läuft. Nachdem ich die MCU-Antwort auf einem Oszilloskop untersucht hatte, war ich ziemlich überrascht, dass die MCU fast 1,32 Minuten benötigt, um mit der Verarbeitung des Interrupts zu beginnen:
Bei einer MCU mit 72 MHz (ich habe zuvor den SYSCLK-Ausgang am MCO-Pin überprüft) entspricht dies fast 89 Taktzyklen. Sollte die MCU-Reaktion auf den Interrupt nicht viel schneller sein?
PS Der Code wurde mit IAR Embedded Workbench kompiliert und für höchste Geschwindigkeit optimiert.
if{}
Anweisung wird benötigt, da die Interruptroutine die Quelle des Interrupts nicht kennt.