How to detect button press on stm32f4discover?

David Gölzhäuser picture David Gölzhäuser · Sep 19, 2013 · Viewed 9.5k times · Source

I like to detect a button press to switch through the 4 LEDs on the board, like

Click-1 --> LED 1 on
Click-2 --> LED 2 on
Click-3 --> LED 3 on
Click-4 --> LED 4 on
Click-5 --> LED 1 off
Click-6 --> LED 2 off
Click-7 --> LED 3 off
Click-8 --> LED 4 off
Click-9 --> LED 1 on
…

as far I have this, but the button click detection isn't working as expected:

/*
 * This file is part of the libopencm3 project.
 *
 * Copyright (C) 2009 Uwe Hermann <[email protected]>,
 * Copyright (C) 2010 Piotr Esden-Tempski <[email protected]>
 * Copyright (C) 2011 Stephen Caudle <[email protected]>
 *
 * This library is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with this library.  If not, see <http://www.gnu.org/licenses/>.
 */

#include <libopencm3/stm32/f4/rcc.h>
#include <libopencm3/stm32/f4/gpio.h>

uint16_t exti_line_state;

/* Set STM32 to 168 MHz. */
static void clock_setup(void)
{
    rcc_clock_setup_hse_3v3(&hse_8mhz_3v3[CLOCK_3V3_168MHZ]);
}

static void gpio_setup(void)
{
    /* Enable GPIOD clock. */
    rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPDEN);

    /* Set GPIO12 (in GPIO port D) to 'output push-pull'. */
    gpio_mode_setup(GPIOD, GPIO_MODE_OUTPUT,
            GPIO_PUPD_NONE, GPIO12 | GPIO13 | GPIO14 | GPIO15);
}

static void button_setup(void)
{
    /* Enable GPIOA clock. */
    rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPAEN);

    /* Set GPIO0 (in GPIO port A) to 'input open-drain'. */
    gpio_mode_setup(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO0);
}

int main(void)
{

    int i;
    i = 1;
    clock_setup();
    button_setup();
    gpio_setup();

    while (1) {

        exti_line_state = GPIOA_IDR;
        if ((exti_line_state & (1 << 0)) != 0) {

            if(i == 1){
                i = 2;
                gpio_toggle(GPIOD, GPIO12);
            }
            if(i == 2){
                i = 3;
                gpio_toggle(GPIOD, GPIO13);
            }
            if(i == 3){
                i = 4;
                gpio_toggle(GPIOD, GPIO14);
            }
            if(i == 4){
                i = 5;
                gpio_toggle(GPIOD, GPIO15);
            }
            if(i == 5){
                i = 1;
                //Shut off all LEDs
            }

        } 
    }

    return 0;
}

Answer

David G&#246;lzh&#228;user picture David Gölzhäuser · Sep 20, 2013

OK, the answer is very simple:

#include <libopencm3/stm32/f4/rcc.h>
#include <libopencm3/stm32/f4/gpio.h>
#include <libopencm3/stm32/f4/adc.h>
#include <stddef.h>
#include <stdlib.h>

int count = 1;
/* Set STM32 to 168 MHz. */
static void clock_setup(void)
{
    rcc_clock_setup_hse_3v3(&hse_8mhz_3v3[CLOCK_3V3_168MHZ]);
}

static void gpio_setup(void)
{
    /* Enable GPIOD clock. */
    rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPDEN);

    /* Set GPIO12 (in GPIO port D) to 'output push-pull'. */
    gpio_mode_setup(GPIOD, GPIO_MODE_OUTPUT,
            GPIO_PUPD_NONE, GPIO12 | GPIO13 | GPIO14 | GPIO15);
}

static void button_setup(void)
{
    /* Enable GPIOA clock. */
    rcc_peripheral_enable_clock(&RCC_AHB1ENR, RCC_AHB1ENR_IOPAEN);

    /* Set GPIO0 (in GPIO port A) to 'input open-drain'. */
    gpio_mode_setup(GPIOA, GPIO_MODE_INPUT, GPIO_PUPD_NONE, GPIO0);
}

static void changeLEDs(void)
{

    if(count == 1){
        count = 2;
        gpio_set(GPIOD, GPIO12);
        return;
    }
    if(count == 2){
        count = 3;
        gpio_set(GPIOD, GPIO13);
        return;
    }
    if(count == 3){
        count = 4;
        gpio_set(GPIOD, GPIO14);
        return;
    }
    if(count == 4){
        count = 5;
        gpio_set(GPIOD, GPIO15);
        return;
    }
    if(count == 5){
        count = 6;
        gpio_clear(GPIOD, GPIO12);
        return;
    }
    if(count == 6){
        count = 7;
        gpio_clear(GPIOD, GPIO13);
        return;
    }
    if(count == 7){
        count = 8;
        gpio_clear(GPIOD, GPIO14);
        return;
    }
    if(count == 8){
        count = 1;
        gpio_clear(GPIOD, GPIO15);
        return;
    }
}

int main(void)
{

    gpio_setup();
    clock_setup();
    button_setup(); 
    int i;

    while (1) {

        if(GPIOA_IDR & 0x0001){

             for (i = 0; i < 6000000; i++)  /* Wait a bit. */
                        __asm__("nop");
            changeLEDs();
        }
    }

    return 0;
}