为什么中断在 STM32 上没有按预期工作?

问题描述 投票:0回答:1

我正在尝试制作一个简单的程序,该程序利用外部中断来控制 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++)
    {}
    }
}

c arm embedded stm32 microcontroller
1个回答
5
投票

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
可能会在两个测试之间发生变化,并最终不会执行任何一个块。永远不要在同一次迭代中重新测试共享变量。如果您需要这样做,请一次性复印一份并测试该副本。

© www.soinside.com 2019 - 2024. All rights reserved.