Skip navigation
All Places > Contribute your knowledge > Blog


This presentation is aimed at helping users to control the toggling of a LED

by an interrupt using a simple timer
This example was developed using the Keil programing environment for

a nucleo stm32l476 board


This project is only a simple introduction to STM32 for students at phelma, school of engineering in

Physics, Applied Physics, Electronics & Materials Science at Grenoble (France)


JC Toussaint

Full Professor at Phelma



I wanted to share with you a document I received from AC6 directly about using their IDE: System Workbench for STM32: or SW4STM32 as we call it.


Hope you find it useful.


I am also attaching a short Hands-on I did at customers.







When you are doing IAP you will need to have a project for your application code which is located at an address after the user bootlaoder and settable in the code. You also need to relocate the vector table.


This code example does that.


The zip file contains a set of sources files that build the application to be loaded into Flash memory using In-Application Programming (IAP, through USART for example).


To build such application, some special configuration has to be performed:


1. Set the program load address at 0x08004000, using your toolchain linker file
2. Relocate the vector table at address 0x08004000, using the "NVIC_SetVectorTable"


@note Care must be taken when using HAL_Delay(), this function provides accurate delay (in milliseconds)
based on variable incremented in SysTick ISR. This implies that if HAL_Delay() is called from
a peripheral ISR process, then the SysTick interrupt must have higher priority (numerically lower)
than the peripheral interrupt. Otherwise the caller ISR process will be blocked.
To change the SysTick interrupt priority you have to use HAL_NVIC_SetPriority() function.

@note The application need to ensure that the SysTick time base is always set to 1 millisecond
to have correct HAL operation.

Four LEDs are toggled with a timing defined by the Delay function.


Hope it helps.





Make sure first of all that you have a part number ending in P in the STM32L on the Nucleo board: this will ensure that the STM32L supports external SMPS.


On the Nucleo board a SMPS has been populated and the idea is to measure the overall power consumption of the MCU with and without the use of SMPS.


Startting with the STM32CubeL4 Firmware Package V1.7.0, we provide the STM32 Nucleo PWR GUI tool allowing a quick assessment of STM32L4 low power performance.


The STM32 Nucleo Power GUI tool is readily available under Utilities/PC_Software/STM32Nucleo_Power_GUI


It connects to the STM32 Nucleo hardware boards  supported by the firmware package and allows selecting the various low-power modes and benchmarking codes thanks to the available binary files.


To use "STM32 Nucleo Power GUI tool"  : 

    - Connect the STM32 Nucleo board to a PC with a 'USB type A to Micro-B'

      (Nucleo-144) or 'USB type A to Mini-B' (Nucleo-64) cable through USB

      connector CN1 to power the board.

    - Select the wanted binary available under “STM32Nucleo_Power_GUI/Binaries” and reprogram

      (e.g. with STM32 ST-LINK Utility, available for download from the STM32 Nucleo firmware.

      Once done, to ensure all IOs are at their reset levels, unplug then plug

      the board again.

    - Connect an amperemeter to the IDD jumper (JP5 for Nucleo-144, JP6 for Nucleo-64).     

    - Unzip "Nucleo" on your laptop or desktop and launch Qtserial.exe.

    - Obey the instructions appearing on the screen in connecting to the COM port

      associated with the Nucleo board.

    - Pick one low power mode proposed among those by the GUI tool and press


    - Measure the MCU power consumption on the amperemeter.

    - Reset the board before picking up another low power mode. 


Binaries available under " STM32Nucleo_Power_GUI/Binaries " folder are

      - STM32L476RG_NUCLEO.hex for STM32L476RG Nucleo board

      - STM32L496ZG_NUCLEO.hex for STM32L496ZG Nucleo board without external SMPS

      - STM32L496ZG_NUCLEO_extSMPS.hex for STM32L496ZG Nucleo board with external SMPS


The GUI will permit to enter different low power modes and see the difference


Best Regards.



Dear Reader:

I guess In All " UART IO Operation Functions" such as HAL_UART_Transmit(), HAL_UART_Receive(), ...

the second input argument which is (uint8_t *pData) should be modified as (uint16_t *pData) so we would not encounter a problem in a 9_bit communication, otherwise in a 9_bit communication the following lines in those functions may malfunction:

temp = (uint16_t *)pData;

huart -> Instance -> DR = (*temp & (uint16_t)0x01FF);

best regards




I did a training this week and would like to share it with you.


It is perfect for beginners to get started with SW4STM32: first we turn on a LED, then we move to more advanced examples.


You will need to use a STM32L476 Nucleo board.









In our STM32 the VREFINT (Voltage reference) is connected internally to an ADC channel.




I wrote a code to be able to read VREFINT using ADC.


The code reads the data and then convert it in mV unit depending on VREF+.


I ran the code on a Nucleo F767.


I read the following values: 1206 mV which is within spec:




I am attaching my code. It is using STM32Cube_FW_F7_V1.6.0.


To run the code copy and unzip it at:




I used Keil uVision 5 for IDE.





I2C master




I just finished porting a software implementation of I2C master to a STM8S.


It implements the read and write registers functions:


You will find the functions located in BB_I2C.c:


The functions read and write 16 bit data:


Read register function:

BB_I2C_Result BB_I2C_ReadReg (uint8_t regAddress, uint16_t* pValue, uint8_t SlaveAddressshiftedByOne)

Parameters are:

regAddress: 8 bit internal register address where to write

pValue: 16 bit address of the variable where the read will be stored

SlaveAddressshiftedByOne: 8 bit I2C address of the device you want to address over I2C shifted by one bit to the left



The function return a Boolean

BB_I2C_OK: Pass

BB_I2C_ERR: Error



Write register function:

BB_I2C_Result BB_I2C_WriteReg (unsigned char regAddress, uint16_t value, uint8_t SlaveAddressshiftedByOne)


Parameters are:

regAddress: 8 bit internal register address where to write

value: 16 bit value to write

SlaveAddressshiftedByOne: 8 bit I2C address of the device you want to address over I2C shifted by one bit to the left



The function return 1 or 0:

BB_I2C_OK: Pass

BB_I2C_ERR: Error



In your application code you need first to call: BB_I2C_Init();

This function will initialize the IOs.


You will also need to include BB_I2C.h:

#include "BB_i2c.h"


To customize the IOs used you will need to edit: BB_I2C.h

#define BB_I2C_SDA GPIO_PIN_6
#define BB_I2C_SCL GPIO_PIN_7


You can also edit the I2C slave address (address NOT shifted by one bit to the left) just below:

#define SLAVE_ADDRESS 0x28 // I2C address of the STUSB device


I attaching below a project example:

The zip file contains the project files and user files.

It needs to be unzip in the STM8S/A Standard Peripheral Library (I used version 2.2.0) at the following location:



I used STVD and Cosmic so the Project is located at:



I used the project "stm8s103"


For hardware I used a STM8S-Discovery board.


Here is my set-up:


STM8S I2C Master Software


In my set-up PD6 is I2C SDA and PD7 is I2C SCL.


I connected those IOs to SDA and SCL of the Slave device (a STUSB device).


I connected also the ground.


You need to make sure that the pull-ups are installed on SCL and SDA.


Here is the test I did:
 BB_I2C_WriteReg (0x81, 0xAA55, 0x50);
BB_I2C_ReadReg (0x81, &Register_readvalue_2, 0x50);



I wrote value 0xAA55 at register address 0x81 of the STUSB chip which I2C address is 0x50.


I then wrote it back and checked that the return value is indeed 0xAA55 and it was the case.


Please see my code attached.







Recently I had to write a sample code for a customer in order to turn on the read out protection of the flash to a level 1.


I did it for a STM32L15x Nucleo or Discovery board but it can be easily ported to another family of STM32.


The code is simple: if the level of readout protection is not set to 1, it will set it to level 1.


If the STM32 RDP is already at level 1 it will do nothing.


I have attached my code zipped.


Unzip it at:




Use the IDE of your choice to build and load the code : IAR, Keil or SW4STM32.

Then once code is built and loaded.


Reset the board so that code will execute.


Now try to use ST-LINK Utility to access the flash: the tool will tell you that the read operation cannot be made because the readout protection has been activated.







Here is the important part of the code to execute:


  /* Unlock the Flash to enable the flash control register access *************/

  /* Unlock the Options Bytes *************************************************/

  /* Get pages write protection status ****************************************/

  /* Check if readoutprtection is enabled ***********************/
  if((OptionsBytesStruct.RDPLevel) == OB_RDP_LEVEL_0)
    OptionsBytesStruct.OptionType= OPTIONBYTE_RDP;
    OptionsBytesStruct.RDPLevel   = OB_RDP_LEVEL_1;
    if(HAL_FLASHEx_OBProgram(&OptionsBytesStruct) != HAL_OK)
      /* Error occurred while options bytes programming. **********************/
      while (1)


    /* Generate System Reset to load the new option byte values ***************/

  /* Lock the Options Bytes *************************************************/

One past challenge was to drive 3 SPI slaves sensors in parallel.


- A global signal to tell them when to "start measuring"

- Each slave notifies by EXTI interrupt when their data is ready to flow out

- Data was significant quantity (few kilobytes, not necessarily the same dats size for each slave)

- Sometime the strategy required for all sensors to wait for each other during the process.

- The sequence to launch a measurement and read out all data has to be nearly transparent to the user code


==> Use code would tell which pseudo sequence to run, launch it, do other things and either wait for a callback when complete, or read a complete flag updated by the interrupt based sequencer.


After some thinking and several itterations came up the concept of a pseudo state machine:


A typical MCU core has a program pointer, read the opcode, execute it and goes to the next one. Usually the core is running based on its internal clock.


The concept was to mimic an MCU core except that it takes one interrupt event to go to the next op-code and execute it.

The state machine is then interrupt based.


This implementation can be found in the attached source file.

Op codes can be created on demand, changed for each application.

Only one interrupt must be armed to trigger the next op code execution.

All interrupts must be same level to keep the system easy to manage and maintain.

To kickstart a sequencer, it must be called from the user code and mimic an interrupt = disable interrupts before calling the sequencer for the first time.


FTM is a composite state machines built from the 3 other individual state machines FT1, FT2 and FT3.


This was an interesting project as it emulates a hidden under the hood complex peripheral running in the background without RTOS, touches parallelism simple programming and scalability of the solution looked elegant and interesting.

People are mostly visual and over the years Microcontrollers were having ways to optically interact with users.

Here is a quick summary of the various display interfaces and technologies supported by the STM32 family.


LEDs: This is the simplest way for a microcontroller (MCU) to optically interact. Each LED will consume 5mA for decent brightness, however, remember that 4 LEDS will consume as much as an STM32L4 at 80MHz... LEDs can be smartly connected to a TIMER.CC channel to be brightness modulated by PWM (Pulse Width Modulation).


LCD Displays: Some are backlighted, some are reflective (as you calculator), some are transflective (both).

Some are Black and White, some have Greyscale and some have Colors (which number depends on the driver chipset)

Some will have a capacitive touch screen overlaid (On Cell) with typically I2C interface plus interrupt pin, some will have the capacitive layer within the display plane and are called In Cell (In LCD Pixel Cell).


A simple segmented LCD Display can be directly driven by some STM32.

Dot matrix LCD Display come with a display controller with specific interfaces to communicate with MCU.


Here are the typical interfaces:


I2C LCD Display : Quite rare however handy for debug because you need only 2 GPIOs to generate an I2C bus.

If the LCD is character base, it won't require lots of Flash/RAM resources from the STM32.


SPI LCD Display: This enables higher throughput which could be dot matrix display type

NHD-C0216CZ-FSW-FBW-3V3 Newhaven Display Intl | Optoelectronics | DigiKey


Then for higher throughput of pixel update, there is the typically 8 bit parallel interface called 8080/6800 type LCD Display


NHD-320240WX-CoTFH-V#I040 (NO Mounting tabs) NHD?320240WX?C0TFH?V#I040 [94.7mm x 71.7mm] - $59.95 : Newhaven Display Int… 


When the display resolution increases and the color depth is also increasing to become close to smart phone, the quantity of information to throughput grows significantly, especially if video animation is a demand.


Historically, you'll have a pixel interface:


16 Million colors = 256 Red x 256 Green x 256 Blue = 24 bit for one pixel = 24 GPIO for the color information

This is the 24 bit parallel interface. Add a pixel clock and some sync signals (DE=Data Enable) and that's all what is needed to drive such type of display.

Need to use less pins?

Exist 16 bit mode color palette would be reduced to 5:6:5 (32 Red, 64 Green, 32 Blue Levels for 65k Colors)

If the resolution is VGA = 640x480 pixels refreshed at 50 Hz, the data throughput is getting tough.

For long video cables a specific technology was introduced named LVDS (Low Voltage Differential Signaling)

With this, multiple CMOS lines are replaced by a PLL used to serialize bits in a differential pair which can pass more bitrate than the CMOS equivalent. In display usually 7 digital signals are stuffed in one differential pair.

TTL to LVDS, LVDS to TTL conversion chipsets are available to stretch the length of the video cable whenever needed.

This was typically used in laptop between the motherboard and the display, using a hidden flex ribbon.


Detail: HSYNC and VSYNC are typically no longer needed, DE (Display Enable) toggles at pixel frequency and tells if the pixel is valid or not (blanking pixels or lines). In the display the LVDS receiver is called TCON (Timing Controller). 


For short distance when power consumption and pincount is critical, a newer standard was created : DSI (Display Serial Interface) from MIPI a standardization organisation aiming a smartphone design. This interface enables even higher data rate to reduce the number of differential pairs needed. This DSI interface is also available on some of the latest STM32 such as STM32F469.

Display Technologies:


LCD : Light polarisation modulated by liquid crystals. Mature technology

OLED : Light is emitted by each pixel (array of LEDs). Trying to replace LCD technology. Better contrast.

e-Paper : Bistable Displays which only require energy when the display content changes. Slow and Low power


Hope this help.

More details will be added as time goes.