Ads

Get STM32 tutorial using HAL at $10 for a limited time!

Saturday, January 2, 2016

ARM Cortex-M3 (STM32F103) Tutorial - GPIO - Read Push Button/Switch

In this tutorial, I will explain how to use STM32F103 GPIO peripheral for read input from push button. GPIO (General Purpose Input Output) on STM32F103 can be configure to 4 different modes (input mode, output mode, analog input mode, alternate function mode). For read input from push button, we need to configure GPIO in digital input mode.


STM32F013 has 3 input mode (digital input): input with internal pull-up, input with internal pull-down, and input floating. The logic voltage of STM32 microcontroller is 3.3V, so the logic voltage for GPIO input pins is also 3.3V, but there are several pins that have 5V tolerant. So, we can input 5V logic level to this 5V tolerant input pins. This table below shows I/O voltage level on STM32F103 input pins.


This is the characteristic of I/O port bit when configured as input mode:

  • The output buffer is disabled.
  • The schmitt trigger input is activated.
  • The weak pull-up and pull-down resistors are activated or not depending on input
    configuration (pull-up, pull-down or floating).
  • The data present on the I/O pin is sampled into the input data register every APB2
    clock cycle.
  • A read access to the input data register obtains the I/O state.

This is the push button circuit for this tutorial. I also add a LED in this circuit just for show the state of button (is pressed or not).


For the GPIO, I choose input mode with internal pull-up. Therefore the button configuration is active low (when the button is pressed, the logic in data buffer is "0"). The output configuration for LED is open-drain mode and also active low.

This is the progam code. The purpose of this code is to turn on the LED when the button is pressed and turn off when it is not pressed.
#include "stm32f10x.h"
#include "stm32f10x_rcc.h"
#include "stm32f10x_gpio.h"

GPIO_InitTypeDef GPIO_InitStruct;

int main(void)
{
    // Enable clock for GPIOA
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);

    // Cofigure PA0 as open-drain output
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_0;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_Out_OD;
    GPIO_Init(GPIOA, &GPIO_InitStruct);
 
    // Cofigure PA1 as input with internal pull-up resistor
    GPIO_InitStruct.GPIO_Pin = GPIO_Pin_1;
    GPIO_InitStruct.GPIO_Speed = GPIO_Speed_2MHz;
    GPIO_InitStruct.GPIO_Mode = GPIO_Mode_IPU;
    GPIO_Init(GPIOA, &GPIO_InitStruct);

    while (1)
    {
        // If button on PA1 is pressed (button circuit is active low)
        if (!(GPIO_ReadInputData(GPIOA) & GPIO_Pin_1))
        {
            // Turn on LED on PA0 (LED circuit is active low)
            GPIO_ResetBits(GPIOA, GPIO_Pin_0);
        }
        else
        {
            // Turn off LED on PA0
            GPIO_SetBits(GPIOA, GPIO_Pin_0);
        }
    }
}
You can use other input mode such as input with internal pull-down resistor or input floating. For input floating, you must add external pull-up or pull- down resistor. This is the example circuit for input with internal pull-down and input floating with external pull-up.


When using pull-down resistor, the logic is active high (when the button is pressed, the logic in data buffer is "1"). For more example code, you can visit here.

For STM32 tutorial with HAL library, you can click here.

17 comments :

  1. Where do you download every files needed in the project? I mean, the headers and the source code required for the GPIOs, RCC, etc.

    Thank you!

    ReplyDelete
    Replies
    1. MDK5 Software Packs: https://www.keil.com/dd2/pack/
      Choose STM32F1 device series.

      Delete
  2. Great work!
    Could you elaborate as to how to read the Datasheet/reference manual in general?
    Example, how did you come to know that you'll need to configure the APB2 register.
    Do i need read the whole refernce manual for the same thing?
    Regards,
    Kartik

    ReplyDelete
    Replies
    1. Thank You.

      In general, when I read the datasheet/reference manual, I always follow this steps:

      1. You need to know where the peripheral that you want to use is connected (bus AHB, APB1, or APB2). You can get this information on chapter 3 of the reference manual (on figure 1).

      2. On the chapter 7 or 8 of the reference manual (RCC), you can get information about the bus clocks and prescaler settings. Every peripheral needs a clock, so you must enable the clock that corresponding to the peripheral in the peripheral clock enable register.

      3. You can read the chapter of the peripheral that you want to use. You can read the part that you are interested. Sometimes it is useful to read the register description of the peripheral.

      4. If you want to know whether the pin which corresponds to the peripheral that you want to use is available or not on the MCU package, you can see on the datasheet. In the datasheet you can also find the information about default pin mapping, pin remap, and 5V tolerant pins.

      5. You can also learn how to configure the peripheral from the ST library files. You can open the files and see what registers or another peripherals need to be configured.

      Delete
    2. Hi Yohanes, what did you use to dump the code? Can it be done via USB when doing it for the first time? Or do i need to use some external USB bootloader?

      Delete
    3. I use the ST-Link/V2 (clone version) to burn and debug the code.
      For the first time the microcontroller cannot be programmed via the USB port, unless your board arrives with an existing USB bootloader.
      Yes, you need a USB bootloader in order to burn the code via USB.

      Delete
  3. Can't the code be dumped via a USB to TTL converter in stm32?

    ReplyDelete
    Replies
    1. Yes it can, according to the reference manual (Ch 3, boot configuration), each stm32 device has an embedded bootloader inside (programmed by ST during production) which support USART, so we can use USB to TTL USART to program the code.

      Delete
  4. Greetings from Brazil, my dear Yohanes. I am a beginner in ARM, I chose to start with M3, I loved its explanation, I would like later to leave the download link of the source codes. Thank you. Marcos.

    ReplyDelete
    Replies
    1. Hello Marcos. Thank you for visiting my blog. I have added the download link for the source code, so you or other people can download many example code for M3.

      Delete
  5. I am a beginner in ARM Cortex processor based microcontroller.
    I have one question. I am also using stm32f103vet microcontroller. when I use open drain mode output it provides always 0 output. Maybe It happens because of using no internal pull-up resistor. I did search into the datasheet but didn't find any register to enable pull-up resistor for open drain output. So my question is. Is there any option for stm32f103 microcontroller to enable internal pull-up? or I should use external pull-up resistor. I need your help. I think you can help me. Thank you.

    ReplyDelete
    Replies
    1. In STM32F103, there is no internal pull-up for output driver. The available internal pull-up is only for input driver. You can see this on the block diagram of GPIO. The internal pull-up/down only exists inside the input driver (only input driver can use it). So for open-drain output, you must use external pull-up.

      Delete
  6. Hi Yohanes. I have a serial data which have been sent by a sensor. What should I configure which type of output to read that data.

    ReplyDelete
  7. Hello
    How to set one port eg GPIOA: PA0 - PA4 as outputs, PA5 - PA7 as inputs?

    ReplyDelete