使用中断问题的STM32F103 | libopencm3 | GPIO切换

使用中断问题的STM32F103 | libopencm3 | GPIO切换,stm32,interrupt,interrupt-handling,isr,libopencm3,Stm32,Interrupt,Interrupt Handling,Isr,Libopencm3,因此,我试图根据按钮的中断切换LED 理想情况下,当按下按钮时,LED应切换,即如果关闭则打开,反之亦然。但当我执行这段代码时,它会切换并返回其原始状态 预期结果: LED熄灭»按钮按下»LED点亮 实际效果: LED关闭»按钮按下»LED打开»LED关闭 我增加了一个去抖动的延迟,所以不考虑反弹。此外,按下按钮时,在ISR中设置GPIO的ODR,那么在退出ISR时如何清除 我非常感谢你的帮助!多谢各位 #include <libopencm3/stm32/rcc.h> #inclu

因此,我试图根据按钮的中断切换LED

理想情况下,当按下按钮时,LED应切换,即如果关闭则打开,反之亦然。但当我执行这段代码时,它会切换并返回其原始状态

预期结果: LED熄灭»按钮按下»LED点亮

实际效果: LED关闭»按钮按下»LED打开»LED关闭

我增加了一个去抖动的延迟,所以不考虑反弹。此外,按下按钮时,在ISR中设置GPIO的ODR,那么在退出ISR时如何清除

我非常感谢你的帮助!多谢各位

#include <libopencm3/stm32/rcc.h>
#include <libopencm3/stm32/gpio.h>
#include <libopencm3/stm32/exti.h>
#include <libopencm3/cm3/nvic.h>

#define LEDPIN (GPIO13)

static void exti_setup(void)
{
    /* Enable GPIOA and AFIO clock. */
    rcc_periph_clock_enable(RCC_GPIOB);
    rcc_periph_clock_enable(RCC_AFIO);

    /* Enable EXTI0 interrupt. */
    nvic_enable_irq(NVIC_EXTI15_10_IRQ);

    /* Set GPIO12 (in GPIO port B) to input  */
    gpio_set_mode(GPIOB, GPIO_MODE_INPUT,GPIO_CNF_INPUT_FLOAT, GPIO12);

    /* Configure the EXTI subsystem. */
    exti_select_source(EXTI12,GPIOB);
    exti_set_trigger(EXTI12, EXTI_TRIGGER_BOTH);
    exti_enable_request(EXTI12);
}


static void gpio_setup(void)
{
    /* Enable clock for GPIO port C */
    rcc_periph_clock_enable(RCC_GPIOC);

    /* Set LEDPIN (in GPIO port C) as opendrain output  */
    gpio_set_mode(GPIOC, GPIO_MODE_OUTPUT_2_MHZ, GPIO_CNF_OUTPUT_OPENDRAIN, LEDPIN);
}

void delay(){
    int i;
    for (i = 0; i < 1000000; i++) 
    {
        __asm__("nop");
    } 
}

void handler(){
    delay();
    gpio_toggle(GPIOC, GPIO13);
}

int main(void)
{
    gpio_setup();
    exti_setup();

    while (1) {
    __asm__("nop");
    }
    return 0;
}

void exti15_10_isr()
{
    exti_reset_request(EXTI12);
    handler();
}
#包括
#包括
#包括
#包括
#定义LED引脚(GPIO13)
静态void exti_设置(void)
{
/*启用GPIOA和AFIO时钟*/
rcc外围时钟启用(rcc GPIOB);
rcc外围时钟启用(rcc AFIO);
/*启用EXTI0中断*/
nvic_启用_irq(nvic_EXTI15_10_irq);
/*将GPIO12(在GPIO端口B中)设置为输入*/
gpio_设置_模式(GPIOB,gpio_模式_输入,gpio_CNF_输入_浮点,GPIO12);
/*配置EXTI子系统*/
exti_选择_源(EXTI12,GPIOB);
exti_设置_触发器(EXTI12,exti_触发器两个);
exti_启用_请求(EXTI12);
}
静态无效gpio_设置(无效)
{
/*为GPIO端口C启用时钟*/
rcc外围时钟启用(rcc GPIOC);
/*将LEDPIN(GPIO端口C中)设置为opendrain输出*/
gpio_设置_模式(GPIOC、gpio_模式_输出_2_MHZ、gpio_CNF_输出_OPENDRAIN、LEDPIN);
}
无效延迟(){
int i;
对于(i=0;i<1000000;i++)
{
__asm_uuuuuuuuuuuuuuuuu(“nop”);
} 
}
void处理程序(){
延迟();
gpio_切换(GPIOC、GPIO13);
}
内部主(空)
{
gpio_设置();
exti_setup();
而(1){
__asm_uuuuuuuuuuuuuuuuu(“nop”);
}
返回0;
}
无效exti15_10_isr()
{
exti_重置_请求(EXTI12);
handler();
}
  • 不是开式排水管,而是推拉式排水管
  • Buttons不应使用EXTI,因为它会使解Bouncing更加复杂,经常会使uC充满中断,使用定时器中断来读取键并解Bouncing

  • 正如@dev_eng正确指出的,问题在于中断被配置为上升/下降沿


    将其配置为上升或下降的单边解决了我的问题

    据我所知,您已经为两个边缘配置了外部中断。所以,当你们按下按钮时,它会有一个边缘,当你们松开按钮时,它会有另一个边缘(我不知道你们的开关是如何使用的,向上拉还是向下拉)。尝试使用上升或下降的单边。@dev_eng非常感谢您!将其配置为上升沿解决了我的问题。