STM32F4xx GPIO`s (as Input)

Keywords: Embedded systems, ARM, STM32F4, GPIOs, Multiplexed Pins

Code Link: Source Code Github Keil- Bare-Metal

Code Link: Source Code Github Keil- HAL Libraries

GPIOs (General Purpose Input Output) enable a processor to interact with outside world. GPIOs are the most common way of interacting processor with off-chip digital and analog devices. In this tutorial we will explain how to use STM32F4xx GPIOs to read a digital input. The board used is STM32F4-Discovery[1]. The board contains a user button connected to PA.0 (blue one) – Figure-1. In this tutorial we will read the on-board user button and if button is pressed, the on-board Blue LED connected to PD.15, will glow.

Figure-1: STM32F407-Discovery User button

Note: This tutorial mainly focuses on configuring PA.0 (GPIOA, Pin#0) as input. The configuration required to Blink an LED is covered in previous tutorial. If you haven’t read that tutorial, go back and read from the link given bellow. The step of configuring a GPIOx as input is almost similar to configuring GPIOx as an output.

Following are the steps to configure a GPIOx as an Input on STM32F4xx devices.

1. Enable GPIOx Module:

As mentioned earlier, User Button is connected to GPIOA – Pin#0, so the first step is to enable clock to GPIOA. As can be seen from STM32F407VG datasheet[2] – Figure-2, GPIOA is connected to AHB1 bus (Advance High Speed Bus).

Figure-2: GPIOA AHB1 bus Connection.

To reduce power consumption, by default various SoC modules (GPIO, USART, UART etc.) and associated registers are disabled. In order to use them, clock must be enabled to them. On STM32F4xx clock to GPIOs is enabled/disabled via AHB1ENR Register Figure-3.

Figure-3: AHB1ENR Register.

As can be seen from Figure-3, the clock to GPIOA is enabled/disabled via bit-0 (GPIOA-EN). Let’s enable GPIOA module by setting bit-0 to 1.

// enable clock to GPIOA
__setbit(RCC->AHB1ENR, 0);

2. GPIOx as Digital Input:

The next step is to decide for which purpose the GPIO needs to be used. On STM32F4 GPIOs can be configured as:
    1. As Digital Input – Code : 00
    2. As Digital Output – Code : 01
    3. As Analog Input/Output – Code : 10
    4. As Alternate function Pin. – Code : 11

The respective GPIO can be configured with above associated code in GPIOx-MODER register – Figure-4.

Figure-4: GPIOx_MODER Register.

For configuring PA.0 as input pin, MODER0 (bits – 1,0) should be set to 00 as per above codes.

/*
    configure PA.0 as digital input
*/
__clearbit(GPIOA->MODER, 0);
__clearbit(GPIOA->MODER, 1);

3. GPIOx Input Type:

On STM32F4, GPIOs can be configured as Push-Pull or open-drain.
Push-Pull: In this state, GPIO Pin can be set to Logic-0 and Logic-1 by Software (if configured as output) or External Logic (if configured as input).
Open-drain: In this state, the GPIO Pins state (logic-0, logic-1) can’t be set by means of Software. Unless an external resister connecting pin to Vcc / Ground. In open-drain state, GPIO Pin remains in High-Impedance floating state.

The output type can be set via GPIOx_OTYPER register – Figure-5.

Figure-5: GPIOx_OTYPER Register.

For this example, we will configure PA.0 in Push-Pull state so that both button state (0,1) can be read depending on button connection to Ground or Vcc respectively.

/*
    GPIOs output type: Push-Pull
    so that it can be pulled high (logic-1) and pulled down (logic-0)
*/
__clearbit(GPIOA->OTYPER, 0);

4. GPIOx Speed:

In order to reduce power, GPIOs speed can be set to in accordance to application requirements. Higher the speed, the more will be the power consumption. On STM32F4, GPIO speed can be set via GPIOx_OSPEEDR-Figure-6:
    Low Speed (00): Speed goes up to 2Mhz.
    Medium Speed (01): Speed goes up to 25Mhz.
    Fast Speed (10): Speed goes up to 50Mhz.
    High Speed (11): Speed goes up to 100Mhz.

Figure-6: GPIOx_OSEEDR Register.

For this example, let’s keep the speed to Medium.

/*
    Lets keep GPIO speed: Medium
*/
__setbit(GPIOA->OSPEEDR, 0);
__clearbit(GPIOA->OSPEEDR, 1);

5. GPIOx Pull-up/Pull-down:

This is one of the most important step in configuring GPIO as input. The GPIO default Hardware based state can be set to Pull-up or Pull-down via Resister. These states indicate what will be the state of GPIO pin if no state is set via software.
As can be seen from Figure-1, when the button is pressed, Vcc (Logic-1) appears at PA.0. What this means is the default state of PA.0 should be 0 (Pull-down) so that 1 (Vcc) can be detected on this Pin. If we don’t pull the line (PA.0) down, the button will always be read as Logic-1.

On STM32F4, Pull-up/Pull-down state can be set via GPIOx_PUPDR register – Figure-7.

Figure-7: GPIOx_PUPDR Register.

For this example, Pull-down the PA.0 line.

/*
  Initial Level: Pull Down --> Logic-0
*/
__clearbit(GPIOA->PUPDR, 0);
__setbit(GPIOA->PUPDR, 1);

6. Read GPIOx:

Now that all required steps to configure a GPIOx Pin as input have been made, the final step is to read pin state. This can done via GPIOx_IDR – Figure-8. Setting pin voltage to Vcc/Ground on physical connection will set the corresponding in bit in GPIOx_IDR to 1/0 respectively.

Figure-8: GPIOx_IDR (Input Data) Register.

Let’s finally read user button on PA.0 and if it is pressed (PA.0 is connected to Vcc), TRUN-ON Blue LED PD.15 and if not pressed, Turn the LED OFF.

while (1) {
	
    /* Read User Button on PA.0 */
    if (__getbit(GPIOA->IDR, 0)) {
        /* Turn-ON the LED */
        __setbit(GPIOD->ODR, 15); 
    }else {
        __clearbit(GPIOD->ODR, 15); 
    }
}


For complete source code refer to the Github links given at the start of this tutorial.

Video Demonstration:

[1] – Reference manual-RM0090



281 thoughts on “STM32F4xx GPIO`s (as Input)”

Leave a Reply

Your email address will not be published. Required fields are marked *