Fad*_*EID 0 c embedded microcontroller arm stm32
我正在尝试编写一个简单的程序,该程序利用外部中断来控制 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++)
{}
}
}
Run Code Online (Sandbox Code Playgroud)
EXTI 功能需要在 RCC 中启用 SYSCFG/AFIO。否则您的 EXTI 配置将被忽略。对于STM32F1xx来说是AFIO,其他系列使用SYSCFG。
RCC->APB2ENR |= (1<<0); // Enable AFIO CLOCK
Run Code Online (Sandbox Code Playgroud)
初始化:
GPIOB->ODR |= (1<<5); // pullup
Run Code Online (Sandbox Code Playgroud)
写入错误的寄存器。你的意图是:
GPIOB->PUPDR |= (1<<5); // pullup
Run Code Online (Sandbox Code Playgroud)
如果评论有意义的话。
延迟循环有严重缺陷 - 至少你应该有:
volatile int i ;
Run Code Online (Sandbox Code Playgroud)
除此之外,请考虑使用 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 ) ;
}
Run Code Online (Sandbox Code Playgroud)
线程上下文之间共享的任何变量也必须声明volatile:
volatile int signal = 0; // this will change upon each interrupt
Run Code Online (Sandbox Code Playgroud)
并且signal无需测试两次,else if(signal==1)即可简单else。这会更好,因为signal两个测试之间可能会发生变化,并且最终不会执行任何一个块。切勿在同一迭代中重新测试共享变量。如果您需要这样做,请一次性获取一份副本并测试该副本。