我正在尝试制作一个简单的程序,该程序利用外部中断来控制 2 个 LED 中的哪一个会闪烁。在没有中断例程的情况下,两个 LED 都可以闪烁,因此 LED 引脚(PB 和 PC13)的配置是正确的。 该程序是每当我尝试使用 ISR 时。 我正在为 STM32F103C8 MCU 使用只有 CMSIS 内核的 Keil uVision 5。
在下面的代码中,两个 LED 都没有闪烁。 我正在尝试将引脚 PB5 设置为输入上拉,并在将 PB5 与 GND 连接时将下降沿检测为中断。
#include "stm32f10x.h" // Device header
void delay(int rep);
void EXTI9_5_IRQHandler();
// global variable
int signal = 0; // this will change upon each interrupt
int main(void)
{
// set RCC for PortC to enable the clock BUS
RCC->APB2ENR |= (1<<4);
// set RCC for portB to enable the clock bus
RCC->APB2ENR |= (1<<3);
// set the mode and function of PC13 to output
GPIOC->CRH &= 0xFF0FFFFF; // reset to all zeros
GPIOC->CRH |= 0x00200000; // make output push-pull
// set the mode and function of PB3 as output
GPIOB->CRH &= 0xFFFFFFF0; // reset to all zeros
GPIOB->CRH |= 0x00000002; // make output push-pull
// set PB5 as input to later make it an external interrupt
GPIOB->CRL &= 0xFF0FFFFF; // reset to all zeros
GPIOB->CRL |= 0x00800000; // make input pullup/pulldown
GPIOB->ODR |= (1<<5); // pullup
// configure PB5 as external interrupt
__disable_irq(); // disable interrupt requests (for safety)
AFIO->EXTICR[1] = 0x00000010;
EXTI->IMR |= (1<<5);
EXTI->FTSR |= (1<<5); // set to falling edge
NVIC_EnableIRQ(EXTI9_5_IRQn);
__enable_irq(); // enable the interrupt requests again
// toggle PC13 indefinitely (waiting for interrupts)
while(1)
{
if(signal==0)
{
GPIOC->ODR |= (1<<13);
delay(10);
GPIOC->ODR &= ~(1<<13);
delay(5);
}
else if(signal==1)
{
GPIOB->ODR |= (1<<8);
delay(10);
GPIOB->ODR &= ~(1<<8);
delay(5);
}
}
}
// ISR Function to service PB5 external interrupts
void EXTI9_5_IRQHandler()
{
EXTI->PR |=(1<<5);
if(signal ==1) signal = 0;
else signal = 1;
}
/// Random time delay Function
void delay(int rep)
{
for(;rep>0;rep--)
{
int i;
for(i=0; i< 100000;i++)
{}
}
}
EXTI 功能需要在 RCC 中启用 SYSCFG/AFIO。否则将忽略您的 EXTI 配置。对于STM32F1xx是AFIO,其他系列使用SYSCFG。
RCC->APB2ENR |= (1<<0); // Enable AFIO CLOCK
初始化:
GPIOB->ODR |= (1<<5); // pullup
写入错误的寄存器。你打算:
GPIOB->PUPDR |= (1<<5); // pullup
如果评论有意义。
延迟循环存在严重缺陷——至少你应该:
volatile int i ;
除此之外,考虑使用 Cortex-M SYSCLK 和
SystemCoreClock
来实现更合理和确定性的延迟。例如:
volatile uint32_t tick = 0 ;
void SysTick_Handler(void)
{
tick++ ;
}
void delayms( uint32_t millisec )
{
static bool init = false ;
if( !init )
{
SysTick_Config( SystemCoreClock / 1000 ) ;
init = true ;
}
uint32_t start = tick ;
while( tick - start < millisec ) ;
}
线程上下文之间共享的任何变量也必须声明
volatile
:
volatile int signal = 0; // this will change upon each interrupt
而
signal
不需要测试两次,else if(signal==1)
可以简单的else
。这会更好,因为 signal
可能会在两个测试之间发生变化,并最终不会执行任何一个块。永远不要在同一次迭代中重新测试共享变量。如果您需要这样做,请一次性复印一份并测试该副本。