GPIO LED Control – Using HAL Library[2]

In GPIO LED Control – Using HAL Library[1] we created a blank project with HAL layer. Now it is time to control the LED with this driver support.

1. Investigate HAL Library

Let take a look at some essential files to control GPIO LED control.

1.1. stm32f4xx_hal.c

It is the common part of the HAL initialization contains a set of generic and common APIs that can be used by the PPP peripheral drivers and the user to start using the HAL

Important functions:

  • HAL_Init(): used to initialize the HAL library; it must be the first instruction to be executed in the main program (before to call any other HAL function)
  • HAL_Delay(): this function provides minimum delay (in milliseconds) based on variable incremented

1.2. stm32f4xx_hal_gpio.c

Provides firmware functions to manage Initialization, de-initialization and IO operation functions.

Important functions:

  • HAL_GPIO_Init(): Initializes the GPIOx peripheral according to the specified parameters in the GPIO_Init.
  • HAL_GPIO_WritePin(): Sets or clears the selected data port bit
  • HAL_GPIO_TogglePin(): Toggles the specified GPIO pins

Look at these functions in detail, you can see they are using the same register to control GPIO as we know. It helps us more confident to use the function in library.

1.3. stm32f4xx_hal_cortex.c

This file provides functions allowing to configure the NVIC interrupts (IRQ) and Systick.

Important functions:

  • HAL_NVIC_EnableIRQ(): Enables a device specific interrupt in the NVIC interrupt controller
  • HAL_NVIC_DisableIRQ(): Disables a device specific interrupt in the NVIC interrupt controller
  • HAL_NVIC_SetPriority()

All functions is described very detail in each file. Let investigate it more to understand the content and usage.

2. Implement GPIO LED code

  • Include header files for HAL functions:
#include "stm32f4xx_hal.h"
#include "stm32f4xx_hal_gpio.h"
  • Define LED PORT-D and pin 12, 13, 14, 15
/* All LED are on PORT D */

/* Define LED pin */
#define LED0_PIN (1<<12)
#define LED1_PIN (1<<13)
#define LED2_PIN (1<<14)
#define LED3_PIN (1<<15)
  • Insert LED_Init() function for all LED. Same as using register directly, we need to config GPIO follow the steps as my commend.
void LED_Init(void)
    GPIO_InitTypeDef  GPIO_InitStruct;

    /* Enable clock for port D */
    /* Configure the GPIO_LED pin as output mode, pullup option and speed fast */
    GPIO_InitStruct.Pin     = LED0_PIN | LED1_PIN | LED2_PIN | LED3_PIN;
    GPIO_InitStruct.Mode    = GPIO_MODE_OUTPUT_PP;
    GPIO_InitStruct.Pull    = GPIO_PULLUP;
    GPIO_InitStruct.Speed   = GPIO_SPEED_FAST;
    /* Init the LED pin function */
    HAL_GPIO_Init(LED_PORT, &amp;GPIO_InitStruct);
  • Create main function with super loop to turn on LED1
int main(void)
    /* Init to use HAL Library */

    /* Init LED */

        /* Set LED1_PIN to hight value */
        HAL_GPIO_WritePin(LED_PORT, LED1_PIN, GPIO_PIN_SET);     
    return 0;
  • Now build and flash code into STM32F411E-Discovery board, you will see Orange LED is turned on

3. Debug with Keil Arm

However turn on LED is not enough here. Follow my steps and you can see problems:

  • Press debug button
  • Click run button and see the Orange LED is turned on
  • Click stop button and you can see program is stuck in Systick_Handler function

The reason is HAL_Init function cal HAL_InitTick() function, and this function enables Systick interrupt. Now when Systick interrupt happen, it requires Systick_Handler() function, and this architecture require user provide it.

Now we can see the big benefit of using debug feature. Without it, we will lost in our code to find why our code always stuck in first line.

4. Adding interrupt handler

  • Copy the file stm32f4xx_it.h from STM32Cube_FW_F4_V1.24.0\Projects\STM32F411E-Discovery\Templates\Inc to our project folder beside main.c
  • Copy the file stm32f4xx_it.c from STM32Cube_FW_F4_V1.24.0\Projects\STM32F411E-Discovery\Templates\Src to our project folder beside main.c
  • Add these files to our project to modify
  • Add the path to header file
  • Now you need to modify the template file stm32f4xx_it.c, replace main.h header by stm32f4xx_hal.h header
/* Includes ------------------------------------------------------------------*/
#include "stm32f4xx_hal.h"
#include "stm32f4xx_it.h"
  • Take a look at this file and we can see SysTick_Handler function that increase tick each time by calling HAL_IncTick()
  * @brief  This function handles SysTick Handler.
  * @param  None
  * @retval None
void SysTick_Handler(void)
  • Build and run again and you can see when debugging, our program is not stuck in System_Handler requiring anymore. We must reach this result to continue our other work.

5. Toggle LED using HAL_Delay

  • Modify supper loop to toggle LED
        /* Toggle LED1_PIN */
        HAL_GPIO_TogglePin(LED_PORT, LED1_PIN);
        /* Delay 1000 ms */
  • Rebuild and run and you will see Orange LED toggling.
  • Now we are succeed.

6. Conclusion

This post is so long, but it very necessary to help you understand basic concept inside HAL and how to use it. From now on, I believe everything will be simple to you, at least in process of using HAL.

Next post I will guide you the way to debug output signal by using logic analyzer. This step is important to debug other protocol as UART, SPI, I2C, …

For someone got problem on this project, I uploaded project in github:

You can use it to debug your problem.

Hope you enjoy. See you next time.

Leave a Reply

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