Library 02- STM32F429 Discovery GPIO tutorial with onboard leds and button
Your first blinky project works, but you don’t know how?
I will explain GPIO (General Purpose Input/Output) CMSIS Library. This library is used to work with physical pins on microcontroller. You can set pins to input or output, put them low (0 volts) or HIGH (3,3 volts), select pull resistors, choose output type and select clock speed.
To be able to work with pin, you have to enable pin clock. This is set inside RCC (Reset and Clock Control). All GPIO‘s are on AHB1 bus. We will use GPIOG port, because our onboard leds are connected to pins PG13 and PG14. We can enable clock with code below:
1 |
RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE); |
Next, you need a GPIO_InitTypeDef struct to set options for pin. If you have included GPIO library into project, you can do this with following:
1 |
GPIO_InitTypeDef GPIO_InitDef; //Where GPIO_InitDef is variable to work with struct |
GPIO_InitTypeDef has 5 options:
- GPIO_Pin: Choose pins you will use for set settings
- GPIO_Mode: Choose mode of operation. Look down for options
- GPIO_OType: Choose output type
- GPIO_PuPd: Choose pull resistor
- GPIO_Speed: Choose pin speed
Every of this settings has it’s own options.
- GPIO_Pin: With this you select pins.
1234567//Apply settings just to GPIO_Pin_13:GPIO_InitDef.GPIO_Pin = GPIO_Pin_13;//If you would like to use more pins with same settings, you can use this://This will apply same settings to pins 13 and 14GPIO_InitDef.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14;//This will apply same setings to all pins for one GPIOGPIO_InitDef.GPIO_Pin = GPIO_Pin_All;
- GPIO_Mode: Mode of pins operation
- GPIO_Mode_IN: Set pin to input
- GPIO_Mode_OUT: Set pin to be an output
- GPIO_Mode_AF: Set pin to alternating function (to use with peripheral ex. SPI, USART, etc)
- GPIO_Mode_AN: Set pin to be an analog (ADC or DAC)
- GPIO_OType: Mode for pin’s output type
- GPIO_OType_PP: Output type is push-pull
- GPIO_OType_OD: Output type is open drain
- GPIO_PuPd: Select pull resistors or disable it
- GPIO_PuPd_UP: Enable pull up resistor
- GPIO_PuPd_DOWN: Enable pull down resistor
- GPIO_PuPd_NOPULL: Disable pull resistor
- GPIO_Speed: Select GPIO speed
- GPIO_Speed_100MHz
- GPIO_Speed_50MHz
- GPIO_Speed_25MHz
- GPIO_Speed_2MHz
We never told the script which port we will use because we have more pins 13 and 14 on board. Here comes the first GPIO function called GPIO_Init(). It is located in stm32f4xx_gpio.h
1 2 3 4 5 6 7 8 |
/** * @brief Initializes the GPIOx peripheral according to the specified parameters in the GPIO_InitStruct. * @param GPIOx: where x can be (A..I) to select the GPIO peripheral. * @param GPIO_InitStruct: pointer to a GPIO_InitTypeDef structure that contains * the configuration information for the specified GPIO peripheral. * @retval None */ void GPIO_Init(GPIO_TypeDef* GPIOx, GPIO_InitTypeDef* GPIO_InitStruct); |
We want to initialize pins PG13 and PG14 (there are red and green leds on board) to be an output, push-pull output type, without pull resistor and speed 50MHz. We do this like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
//Enable clock for GPOIG RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE); //Initialize struct GPIO_InitTypeDef GPIO_InitDef; //Pins 13 and 14 GPIO_InitDef.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14; //Mode output GPIO_InitDef.GPIO_Mode = GPIO_Mode_OUT; //Output type push-pull GPIO_InitDef.GPIO_OType = GPIO_OType_PP; //Without pull resistors GPIO_InitDef.GPIO_PuPd = GPIO_PuPd_NOPULL; //50MHz pin speed GPIO_InitDef.GPIO_Speed = GPIO_Speed_50MHz; //Initialize pins on GPIOG port GPIO_Init(GPIOG, &GPIO_InitDef); |
Our pins are now ready. But leds are still off. We need to turn them on:
1 2 |
//Set PG13 and PG14 pins HIGH GPIO_SetBits(GPIOG, GPIO_Pin_13 | GPIO_Pin_14); |
Or if we would like to put leds back off:
1 2 |
//Set PG13 and PG14 pins LOW GPIO_ResetBits(GPIOG, GPIO_Pin_13 | GPIO_Pin_14); |
Toggle pin is possible too:
1 2 3 4 |
//Toggle PG13 and PG14 pins //If pin was HIGH, than it will be now LOW //If pin was LOW, than it will be now HIGH GPIO_ToggleBits(GPIOG, GPIO_Pin_13 | GPIO_Pin_14); |
On discovery board also has blue “User button” connected to PA0. Let’s configure it as input with enabled pull down resistor.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
//Enable clock for GPOIA RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); //Pin 0 GPIO_InitDef.GPIO_Pin = GPIO_Pin_0; //Mode output GPIO_InitDef.GPIO_Mode = GPIO_Mode_IN; //Output type push-pull GPIO_InitDef.GPIO_OType = GPIO_OType_PP; //With pull down resistor GPIO_InitDef.GPIO_PuPd = GPIO_PuPd_DOWN; //50MHz pin speed GPIO_InitDef.GPIO_Speed = GPIO_Speed_50MHz; //Initialize pin on GPIOA port GPIO_Init(GPIOA, &GPIO_InitDef); |
We have configured pin as input, but how to read value on pin?
1 2 |
//Returs pin state (1 if HIGH, 0 if LOW) GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0) |
This is all. I made a little program to test all. Leds are turned off until you press on blue button.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
#include "stm32f4xx.h" #include "stm32f4xx_rcc.h" #include "stm32f4xx_gpio.h" int main(void) { GPIO_InitTypeDef GPIO_InitDef; RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOG, ENABLE); GPIO_InitDef.GPIO_Pin = GPIO_Pin_13 | GPIO_Pin_14; GPIO_InitDef.GPIO_Mode = GPIO_Mode_OUT; GPIO_InitDef.GPIO_OType = GPIO_OType_PP; GPIO_InitDef.GPIO_PuPd = GPIO_PuPd_NOPULL; GPIO_InitDef.GPIO_Speed = GPIO_Speed_100MHz; //Initialize pins GPIO_Init(GPIOG, &GPIO_InitDef); RCC_AHB1PeriphClockCmd(RCC_AHB1Periph_GPIOA, ENABLE); GPIO_InitDef.GPIO_Pin = GPIO_Pin_0; GPIO_InitDef.GPIO_Mode = GPIO_Mode_IN; GPIO_InitDef.GPIO_OType = GPIO_OType_PP; GPIO_InitDef.GPIO_PuPd = GPIO_PuPd_DOWN; GPIO_InitDef.GPIO_Speed = GPIO_Speed_100MHz; //Initialize pins GPIO_Init(GPIOA, &GPIO_InitDef); //volatile int i; while (1) { if (GPIO_ReadInputDataBit(GPIOA, GPIO_Pin_0)) { GPIO_SetBits(GPIOG, GPIO_Pin_13 | GPIO_Pin_14); } else { GPIO_ResetBits(GPIOG, GPIO_Pin_13 | GPIO_Pin_14); } } } |
And because I don’t always want to initialize leds and button, I made a library that will do this for you.
Library
Features
- Sets led on, off or toggle
- Checks led state if it is on or off
- Checks button state
- Supports STM32F429-Discovery leds and button
- Supports STM32F4-Discovery leds and button
- Supports STM32F401-Discovery leds and button
- Supports Nucleo F401 led and button
- Supports Nucleo F411 led and button
Dependencies
- CMSIS
- STM32F4xx
- STM32F4xx RCC
- STM32F4xx GPIO
- TM
- TM GPIO
- defines.h
- TM GPIO
By default, library don’t know which board is used in your project, so you have to tell it. Open defines.h file or global project’s defines (IDE options) and add various defines, according to the board you use. If you not specify settings, you will get an error “tm_stm32f4_disco.h: Please select your board“.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 |
/** * STM32F4 Discovery: (STM32F407VG) * Open project options and add "STM32F407VG" define (without quotes) * - Leds: * - LED_GREEN on PD12 * - LED_ORANGE on PD13 * - LED_RED on PD14 * - LED_BLUE on PD15 * - Button: (HIGH when pressed) * - Blue button on PA0 * * STM32F429 Discovery: (STM32F429ZI) * Open project options and add "STM32F429ZI" define (without quotes) * - Leds: * - LED_GREEN on PG13 * - LED_RED on PG14 * - Button: (HIGH when pressed) * - Blue button on PA0 * * NUCLEO-F401: (STM32F401RE) * NUCLEO-F411: (STM32F411RE) * Open project options and add "STM32F401RE" or "STM32F411RE" define (without quotes) * - Led: * - LED_GREEN on PA5 * - Button: (LOW when pressed) * - Blue button on PC13 * * STM32F401 Discovery: (STM32F401VC) * Open project options and add "STM32F401VC" define (without quotes) * - Leds: * - LED_GREEN on PD12 * - LED_ORANGE on PD13 * - LED_RED on PD14 * - LED_BLUE on PD15 * - Button: (HIGH when pressed) * - Blue button on PA0 * */ |
Functions and enumerations
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
/** * Configure led pins to output * */ extern void TM_DISCO_LedInit(void); /** * Configure blue button as input * */ extern void TM_DISCO_ButtonInit(void); /** * Turn on LED * * Parameters: * - led: * LED_ALL * LED_GREEN * LED_RED * LED_ORANGE * LED_BLUE */ #define TM_DISCO_LedOn(led) (TM_DISCO_LED_PORT->BSRRL = led) /** * Turn off LED * * Parameters: * - led: * LED_ALL * LED_GREEN * LED_RED * LED_ORANGE * LED_BLUE */ #define TM_DISCO_LedOff(led) (TM_DISCO_LED_PORT->BSRRH = led) /** * Toggle LED * * Parameters: * - led: * LED_ALL * LED_GREEN * LED_RED * LED_ORANGE * LED_BLUE */ #define TM_DISCO_LedToggle(led) (TM_DISCO_LED_PORT->ODR ^= led) /** * Check's if led is on * * Parameters: * - uint16_t led: * LED_GREEN * LED_RED * LED_ORANGE * LED_BLUE * * Return 1 if turned on, otherwise 0 */ #define TM_DISCO_LedIsOn(led) ((TM_DISCO_LED_PORT->ODR & led) != Bit_RESET) /** * Set led's state with one function * * Parameters: * - uint16_t led: * LED_GREEN * LED_RED * LED_ORANGE * LED_BLUE * - uint8_t state: * 0: led is off * > 0: led is on * * Return 1 if turned on, otherwise 0 */ #define TM_DISCO_SetLed(led, state) ((state) ? TM_DISCO_LedOn(led): TM_DISCO_LedOff(led)) /** * Checks if button is pressed * * Returns 1 if is pressed, otherwise 0 */ #define TM_DISCO_ButtonPressed() (((TM_DISCO_BUTTON_PORT->IDR & TM_DISCO_BUTTON_PIN) == 0) != TM_DISCO_BUTTON_PRESSED) |
Example
- When you press the button, led will be turned on.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 |
/** * Keil project for LEDS and BUTTON * * Before you start, select your target, on the right of the "Load" button * * @author Tilen Majerle * @email tilen@majerle.eu * @website http://stm32f4-discovery.net * @ide Keil uVision 5 * @packs STM32F4xx Keil packs version 2.2.0 or greater required * @stdperiph STM32F4xx Standard peripheral drivers version 1.4.0 or greater required */ /* Include core modules */ #include "stm32f4xx.h" /* Include my libraries here */ #include "defines.h" #include "tm_stm32f4_disco.h" int main(void) { /* Initialize System */ SystemInit(); /* Initialize leds on board */ TM_DISCO_LedInit(); /* Initialize button on board */ TM_DISCO_ButtonInit(); while(1) { /* If button pressed */ if (TM_DISCO_ButtonPressed()) { /* Turn on leds */ TM_DISCO_LedOn(LED_RED | LED_GREEN); } else { /* Turn off leds */ TM_DISCO_LedOff(LED_RED | LED_GREEN); } } } |
Project available on Github, download library below.
Leds and buttons for Discovery boards
I hope this tutorial a little bit helps to you.
Recent comments