STM32F103 | libopencm3 | GPIO toggle using interrupt issue

1.2k Views Asked by At

So, I am trying to toggle a LED based on an interrupt from a button.

Ideally the when the button is pressed the LED should toggle i.e. switch on if its off and vice versa. But when I execute this code it toggles and returns to its original state.

Expected Result: LED OFF » Button pressed » LED ON

Practical Result: LED OFF » Button pressed » LED ON » LED OFF

I have added a delay for debouncing so bouncing is out of the picture. Also the GPIO's ODR is set in the ISR when the button is pressed so how is it getting cleared while exiting the ISR?

I would really appreciate your help! Thank you.

#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();
}
2

There are 2 best solutions below

0
On BEST ANSWER
  1. Not open drain but push-pull
  2. Butttons should not use EXTI as it makes debouncing more complicated, often floods the uC with interrupts, Use timer interrupt instead to read the key and debounce.
0
On

As @dev_eng rightly pointed out the issue was the interrupt being configured as both RISING/FALLING edge.

Configuring it with single EDGE that is either RISING or FALLING solved my problem.