Search code examples
interruptkeilstm32f4discoverydebouncing

Twice handled (by rising/falling edge) interruption of the button


I have written some code that must turn on leds one by another (in a round) by each click of the button, but sometimes with one click of the button lights not the next led but one random from four leds. It's something like one or more leds skips its turn. I think the problem is caused by wrong setup of clock rate or wrong setup of Rising/Falling EXTI trigers. Board: STM32DISCOVERY

periph.h

#ifndef PERIPH_H
#define PERIPH_H

#include "stm32f4xx_gpio.h"
#include "stm32f4xx_rcc.h"
#include "misc.h"
#include "stm32f4xx_exti.h"
#include "stm32f4xx_syscfg.h"

void Initialize_GPIO_LEDS(void);
void Initialize_GPIO_Button(void);
void Initialize_EXTI0_PA(void);
void Initialize_NVIC(void);

typedef enum
{ 
  GPIO_LED_Green         = GPIO_Pin_12,
  GPIO_LED_Yellow        = GPIO_Pin_13,
  GPIO_LED_Red           = GPIO_Pin_14,
  GPIO_LED_Blue          = GPIO_Pin_15
}GPIO_LED_TypeDef;

void GPIO_LED_On(GPIO_LED_TypeDef GPIO_LED_x);
void GPIO_LED_Off(GPIO_LED_TypeDef GPIO_LED_x);
void GPIO_LED_All_On(void);
void GPIO_LED_All_Off(void);

#endif /* PERIPH_H */

periph.c

#include "periph.h"

GPIO_InitTypeDef GPIO_LEDS;
GPIO_InitTypeDef GPIO_Button;
EXTI_InitTypeDef EXTI0_PA;
NVIC_InitTypeDef NVIC_Struct;

void Initialize_GPIO_LEDS(void)
{
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOD, ENABLE);

    GPIO_LEDS.GPIO_Pin = GPIO_Pin_15 | GPIO_Pin_14 | GPIO_Pin_13 | GPIO_Pin_12;
    GPIO_LEDS.GPIO_Mode = GPIO_Mode_OUT;
    GPIO_LEDS.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_LEDS.GPIO_OType = GPIO_OType_PP;
    GPIO_LEDS.GPIO_PuPd = GPIO_PuPd_NOPULL;

    GPIO_Init(GPIOD, &GPIO_LEDS);
}

void Initialize_GPIO_Button(void)
{
    RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE);

    GPIO_Button.GPIO_Pin = GPIO_Pin_0;
    GPIO_Button.GPIO_Mode = GPIO_Mode_IN;
    GPIO_Button.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_Button.GPIO_OType = GPIO_OType_PP;
    GPIO_Button.GPIO_PuPd = GPIO_PuPd_DOWN;

    GPIO_Init(GPIOA, &GPIO_Button);
}

void Initialize_EXTI0_PA(void)
{
    EXTI0_PA.EXTI_Line = EXTI_Line0;
    EXTI0_PA.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI0_PA.EXTI_Trigger = EXTI_Trigger_Rising;
    EXTI0_PA.EXTI_LineCmd = ENABLE;

    EXTI_Init(&EXTI0_PA);
}

void Initialize_NVIC(void)
{
    NVIC_Struct.NVIC_IRQChannel  = EXTI0_IRQn;
    NVIC_Struct.NVIC_IRQChannelCmd = ENABLE;

    NVIC_Init(&NVIC_Struct);
}

void GPIO_LED_On(GPIO_LED_TypeDef GPIO_LED_x)
{
    GPIO_SetBits(GPIOD, GPIO_LED_x);
}

void GPIO_LED_Off(GPIO_LED_TypeDef GPIO_LED_x)
{
    GPIO_ResetBits(GPIOD, GPIO_LED_x);
}

void GPIO_LED_All_On(void)
{
    GPIO_SetBits(GPIOD, GPIO_LED_Green | GPIO_LED_Yellow | GPIO_LED_Red | GPIO_LED_Blue);
}

void GPIO_LED_All_Off(void)
{
    GPIO_ResetBits(GPIOD, GPIO_LED_Green | GPIO_LED_Yellow | GPIO_LED_Red | GPIO_LED_Blue);
}

main.c

#include "cmsis_os.h"
#include "periph.h"

uint8_t led_num = 0;

void EXTI0_IRQHandler(void)
{
    if (EXTI_GetITStatus(EXTI_Line0) != RESET)
    {
        if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0))
        {
            led_num++;
            if (led_num == 4) led_num = 0;
        }
        EXTI_ClearITPendingBit(EXTI_Line0);
    }
}

int main (void)
{
    Initialize_GPIO_LEDS();
    Initialize_GPIO_Button();
    SYSCFG_EXTILineConfig(EXTI_PortSourceGPIOA, EXTI_PinSource0);
    Initialize_EXTI0_PA();
    Initialize_NVIC();

    while(1)
    {
        switch(led_num)
        {
            case 0 : GPIO_LED_On(GPIO_LED_Green);  break;
            case 1 : GPIO_LED_On(GPIO_LED_Yellow); break;
            case 2 : GPIO_LED_On(GPIO_LED_Red);    break;
            case 3 : GPIO_LED_On(GPIO_LED_Blue);     break;
        }

        GPIO_LED_All_Off();
    }
}

Solution

  • It's probably due to debouncing (or the lack thereof).

    See http://www.labbookpages.co.uk/electronics/debounce.html for a short primer on how to solve this.

    See also http://www.emcu.it/STM32/STM32Discovery-Debounce/STM32Discovery-InputWithDebounce_Output_UART_SPI_SysTick.html for something specifically about the STM32Discovery.

    All this was found via google.