1

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();
}
mattyyy
  • 13
  • 7
  • As per my understanding, you have configured External interrupt for both edges. So when you press buttion then it gets one edge and when you release button it gets another edge (I don't know how your switch is used PULL UP or PULL DOWN). Try with single EDGE that is either RISING or FALLING. – dev_eng May 08 '20 at 04:38
  • @dev_eng Thank you so much! Configuring it with a RISING edge solved my problem. – mattyyy May 08 '20 at 10:07

2 Answers2

2
  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___________
  • 60,014
  • 4
  • 34
  • 74
0

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.

mattyyy
  • 13
  • 7