Previous Tutorial | Tutorial 32 | Next Tutorial | |||||
7 Segment Display Interfacing With STM32 | Multiplexing Technique | |||||||
STM32 Course Home Page ???? |
In this tutorial, we’ll discuss How To interface 7 Segment Display using STM32. We’ll also build the ECUAL Seven Segments Display driver library. I’ll show you how I built it, the available APIs, and how to use it. Learn how 7 segment display is multiplexed & the POV effect. And finally, we’ll do a couple of LABs or examples using the ECUAL STM32 7 Segments Display driver. While highlighting all the possible options and configurations in the driver’s config files. Without further ado, let’s get started!
[toc]
Required Components For LABs
All the example code/LABs/projects in the course are going to be done using those boards below.
- Nucleo32-L432KC (ARM Cortex-M4 @ 80MHz) or (eBay)
- Blue Pill STM32-F103 (ARM Cortex-M3 @ 72MHz) or (eBay)
- ST-Link v2 Debugger or (eBay)
QTY | Component Name | ???? Amazon.com | ???? eBay.com |
2 | BreadBoard | Amazon | eBay |
1 | LEDs Kit | Amazon Amazon | eBay |
1 | Resistors Kit | Amazon Amazon | eBay |
1 | Capacitors Kit | Amazon Amazon | eBay & eBay |
2 | Jumper Wires Pack | Amazon Amazon | eBay & eBay |
1 | 9v Battery or DC Power Supply | Amazon Amazon Amazon | eBay |
1 | Micro USB Cable | Amazon | eBay |
1 | Push Buttons | Amazon Amazon | eBay |
1 | LM35 Temperature Sensor | Amazon | eBay |
1 | Potentiometers | Amazon Amazon | eBay |
1 | 3-Digit 7Segments Display Com. Cathode | Amazon | eBay |
★ Check The Full Course Complete Kit List
Some Extremely Useful Test Equipment For Troubleshooting:
- My Digital Storage Oscilloscope (DSO): Siglent SDS1104 (on Amazon.com) (on eBay)
- FeelTech DDS Function Generator: KKMoon FY6900 (on Amazon.com) (on eBay)
- Logic Analyzer (on Amazon.com) (on eBay)
Affiliate Disclosure: When you click on links in this section and make a purchase, this can result in this site earning a commission. Affiliate programs and affiliations include, but are not limited to, the eBay Partner Network (EPN) and Amazon.com.
7 Segments Display Interfacing
7 Segments Display Internally
The 7-Segment display units are basically some LED bars arranged as shown in this picture above. Two types are available to use (common anode and common cathode). The one shown above is a common cathode 7-Segment display unit. For this, you need to give each LED a positive voltage in order to turn it one while the common pin is hooked to the ground. And in common anode type of 7-Segments, you’ll have to drive each LED pin low in order to turn it ON while the common anode pin is hooked to Vdd+.
Controlling the 7-Segment display should be an easy task to do as it doesn’t require anything special other than turning the output pins HIGH & LOW. And just don’t forget to use current-limiting resistors on the output pins. Not all microcontrollers can directly drive LEDs with too much current. Using a CCS (constant current source) can also help to make the brightness of the LED bars evenly distributed.
You can use the following online tool to generate the code for any 7-segment display pattern or number you need to display in your project, it’s a very handy tool.
7-Segment Display Code Generator Online Tool
Interfacing 7 Segments Display
With that being said, a 7-Segment display unit requires 7 pins to be hooked to the (A-B-C-…-G) pins. And if you need to display more than one digit, it’ll turn out to be a waste of GPIO pins. Imagine having to display a 3-Digit value, that’s a 21 GPIO pin required. So, if we’re going to control only one 7-Segment display unit, we can directly do it or use a BCD-To-7Seg converter IC to reduce the required pin count. And if more than one digit is to be displayed, then we do what is called multiplexing as demonstrated in the next section.
POV & 7-Segments Display
Multiple 7-Segment display units can be all hooked together to the same GPIO lines of the microcontroller. And multiplexed by control signals which means the 7-Segment display units are not going to be working together all the time. But they’ll be turned ON and OFF one by one. Doing this so quickly will make the human brain see the multiple 7-Segment units as if they are all turned ON together, and each of which is displaying a different number. This effect is called persistence of vision (POV) and there is a link to an article on that topic at the end of this section as well.
The diagram below show you how can a 3-Digit 7-Segment display unit be hooked to a microcontroller. For this, we use 3 driving transistors to switch ON and OFF each 7-Segment unit individually and perform the multiplexing process to show the right number on the right digit at the right time. And keep repeating!
That was a quick introduction for 7Segments Display. For more info, I’d highly recommend those articles below as well. | |
You can use the following online tool to generate the code for any 7-segment display pattern or number you need to display in your project, it’s a very handy tool.
7-Segment Display Code Generator Online Tool
STM32 7-Segment Display ECUAL Driver
The ECUAL 7-Segments driver is built for STM32 microcontrollers using some GPIO pins. You’ll have to configure an instance of it and use the APIs to control your 7-segment display and that’s all. The code should be easily ported to any other STM32 microcontroller or reconfigured to use any GPIO pins you want just as we’ll see in this section. And here is a link for the course’s repo, and you’ll find the SEVEN_SEGMENTS driver in the ECUAL directory as usual.
7 Segment Display Driver Code Files
The 7-Segments Display driver consists of the following files:
|
You’ll need only to modify the configuration files. The source code for this driver is found in (SEVEN_SEGMENTS.c) and to use it you’ll include the header (SEVEN_SEGMENTS.h). Nothing in the source code needs to be changed at all unless you need to add any extra features or customize the driver for your application’s needs. For today’s labs, we’ll only be changing the configuration files to build some test applications.
Therefore, I’ll write here the code listing for the SEVEN_SEGMENTS.h & SEVEN_SEGMENTS_cfg.c files.
SEVEN_SEGMENTS.h File
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
#define HAL_GPIO_MODULE_ENABLED #include "stm32f1xx_hal.h" // The Number OF 7-Segments Display Units To Be Used In The Project #define SEVEN_SEG_UNITS 1 #define DIGITS 3 typedef struct { GPIO_TypeDef * SEG_GPIO[7]; uint16_t SEG_PIN[7]; GPIO_TypeDef * EN_GPIO[DIGITS]; uint16_t EN_PIN[DIGITS]; }SEVEN_SEG_CfgType; /*-----[ Prototypes For All Functions ]-----*/ void SEVEN_SEG_Init(uint16_t au16_Instance); void SEVEN_SEG_Write(uint16_t au16_Instance, uint16_t au16_Data); void SEVEN_SEG_Enable(uint16_t au16_Instance); void SEVEN_SEG_Disable(uint16_t au16_Instance); void SEVEN_SEG_Main(void); |
If you’re willing to use many 7-Segment display units, just adjust that number definition (SEVEN_SEG_UNITS).
SEVEN_SEGMENTS_cfg.c File
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#include "SEVEN_SEGMENTS.h" const SEVEN_SEG_CfgType SEVEN_SEG_CfgParam[SEVEN_SEG_UNITS] = { // 7-Segments Display Unit 1 Configurations { /* Seven Segments Pins Info */ {GPIOA, GPIOA, GPIOA, GPIOA, GPIOA, GPIOA, GPIOA}, {GPIO_PIN_0, GPIO_PIN_1, GPIO_PIN_2, GPIO_PIN_3, GPIO_PIN_4, GPIO_PIN_5, GPIO_PIN_6}, /* Enable Control Signal's Pins */ {GPIOB, GPIOB, GPIOB}, {GPIO_PIN_14, GPIO_PIN_13, GPIO_PIN_12} } }; |
I’ll discuss those configuration parameters in the next section down below.
7-Segments Display Driver APIs
As you’ve seen in the SEVEN_SEGMENTS.h file, the provided APIs does all the basic functionalities that you may need from a 7-Segment Display driver library. It initialized the required GPIO pins to control the 7-Segment lines and the driving transistors.
The SEVEN_SEG_Write function takes the integer you want to display and pare it into separate digits. The SEVEN_SEG_Main function does the job of sending the data and controlling the drive lines (multiplexing) and all of the logical operations. This can be easily used with any operating system such as what we’re going to build in the future.
The structure of the files and the provided APIs look very intuitive and self-explanatory to me. And the example LABs will put everything under test and you’ll see how and when to use each of these functions.
Available Configurations For ECUAL 7-Segments Driver
From the code above in SEVEN_SEG.h & SEVEN_SEG_cfg.c you can see that there are not many parameters in the configuration structure. Only the GPIO pins that you’re willing to use for the 7-Segment display.
Typical Usage Application Example
Here is a typical usage application for this driver in order to initialize a seven-segment unit instance and read a temperature sensor’s value and write it to the 7-segment display. And also note that the seven segments main function is called from the SysTick timer interrupt handler once each 5msec.
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 |
#include "main.h" #include "../ECUAL/SEVEN_SEGMENTS/SEVEN_SEGMENTS.h" #include "../ECUAL/LM35/LM35.h" uint8_t SysTicks = 0; void SysTick_CallBack(void); void SystemClock_Config(void); static void MX_GPIO_Init(void); int main(void) { uint16_t Temperature = 0; HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); LM35_Init(0); SEVEN_SEG_Init(0); SEVEN_SEG_Enable(0); SEVEN_SEG_Write(0, 0); while (1) { Temperature = (uint16_t)LM35_Read(0); SEVEN_SEG_Write(0, Temperature); HAL_Delay(100); } } void SysTick_CallBack(void) { SysTicks++; if(SysTicks == 5) // Each 5 msec { SEVEN_SEG_Main(); SysTicks = 0; } } |
7-Segments Display Main Function
In the SEVEN_SEGMENTS.c source code file, you’ll find the implementation of this function “SEVEN_SEG_Main()“. I highly recommend that you take the time to figure it out. This function is written in this way in order to be called asynchronously from the main application or the OS dispatcher if you have got a task for the 7-segment display. And it handles all the logical operations and stores context variables to resume it’s operation when called again. And yes, it has to be called repeatedly at a steady rate.
Lowering this rate may cause the display units to have ghosting effects and over-calling this function can lead to similar results. So you’ll have to figure out a good periodicity for this routine and I find 5mSec to be good for me.
7-Segment Display Interfacing With STM32 – LAB
LAB Number | 29 |
LAB Title | STM32 7-Segment Display Interfacing |
- Set up a new project as usual with system clock @ 72MHz
- Add the ECUAL / SEVEN_SEGMENTS driver files to our project
- configure an instance in SEVEN_SEGMENTS_cfg.c file
- Initialize the seven segments instance and make a counter variable that increments twice per second for example or whatever and write it to the display using the write function
And now, let’s build this system step-by-step
Step1: Open CubeMX & Create New Project
Step2: Choose The Target MCU & Double-Click Its Name
STM32F103C8
Step3: Go To The Clock Configuration
Step4: Set The System Clock To Be 72MHz
Step5: Generate The Initialization Code & Open The Project In Your IDE
Step6: Add the ECUAL SEVEN_SEGMENTS driver files to your project
Follow This Tutorial which shows you How To Add Any ECUAL Driver To An STM32 Project step-by-step.
Here is The Application Code For This LAB (main.c)
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 |
#include "main.h" #include "../ECUAL/SEVEN_SEGMENTS/SEVEN_SEGMENTS.h" uint8_t SysTicks = 0; void SysTick_CallBack(void); void SystemClock_Config(void); static void MX_GPIO_Init(void); int main(void) { uint8_t Counter = 0; HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); SEVEN_SEG_Init(0); SEVEN_SEG_Enable(0); SEVEN_SEG_Write(0, 0); while (1) { // Each 300mSec Increase The Counter Value By 1 // & Write It To The 7-Segments Display SEVEN_SEG_Write(0, Counter++); HAL_Delay(300); } } void SysTick_CallBack(void) { SysTicks++; if(SysTicks == 5) // Each 5msec { SEVEN_SEG_Main(); SysTicks = 0; } } |
Note that the SEVEN_SEG_Main function is being called from the SysTick callback function. This function needs to be called inside the ISR handler for the SysTick timer. The HAL_Init initializes the systick timer and the HAL_Delay uses it to work as well. So, let’s open this file (stm32f1xx_it.c) and search for the SysTick handler and call our SysTick_Callback from there are shown below.
1 2 3 4 5 |
void SysTick_Handler(void) { HAL_IncTick(); SysTick_CallBack(); } |
And here is the SEEVEN_SEGMENTS_cfg.c configuration file. As you can see here, I’m using the following GPIO pins.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
#include "SEVEN_SEGMENTS.h" const SEVEN_SEG_CfgType SEVEN_SEG_CfgParam[SEVEN_SEG_UNITS] = { // 7-Segments Display Unit 1 Configurations { /* Seven Segments Pins Info */ {GPIOA, GPIOA, GPIOA, GPIOA, GPIOA, GPIOA, GPIOA}, {GPIO_PIN_0, GPIO_PIN_1, GPIO_PIN_2, GPIO_PIN_3, GPIO_PIN_4, GPIO_PIN_5, GPIO_PIN_6}, /* Enable Control Signal's Pins */ {GPIOB, GPIOB, GPIOB}, {GPIO_PIN_14, GPIO_PIN_13, GPIO_PIN_12} } }; |
Download The STM32 Seven Segments Display LAB29
The Result For This LAB Testing (Video)
Final Remark
Download the code, take your time in reading and understanding what’s going on. And drop me a comment if you’ve got any questions. I’ll be always here for help!
There is a specific pattern being followed in all ECUAL drivers and I hope you get it from those different examples and tutorials. And I’m pretty sure, you’ll be able to optimize and make it even better and customized for your needs.
7-Segments Display + Knob (ADC) – LAB
LAB Number | 30 |
LAB Title | STM32 Seven Segments Display & ADC Knob Analog Input |
- Set up a new project as usual with system clock @ 72MHz
- Set up an ADC analog input channel (CH8 on B0 pin)
- Add the ECUAL / SEVEN_SEGMENTS driver files to our project
- configure an instance in SEVEN_SEGMENTS_cfg.c file
- Initialize the seven segments instance and read the ADC pin and divide the result by 4 and cap it at 999 as we can’t display a larger number than this using only 3 digits
And now, let’s build this system step-by-step
Step1: Open CubeMX & Create New Project
Step2: Choose The Target MCU & Double-Click Its Name
STM32F103C8
Step3: Go To The Clock Configuration
Step4: Set The System Clock To Be 72MHz
Step5: In ADC1 Tab Enable CH8 Analog Input (B0 Pin)
Step6: Generate The Initialization Code & Open The Project In Your IDE
Step7: Add the ECUAL SEVEN_SEGMENTS driver files to your project
Follow This Tutorial which shows you How To Add Any ECUAL Driver To An STM32 Project step-by-step.
Here is The Application Code For This LAB (main.c)
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 |
#include "main.h" #include "../ECUAL/SEVEN_SEGMENTS/SEVEN_SEGMENTS.h" uint8_t SysTicks = 0; ADC_HandleTypeDef hadc1; void SysTick_CallBack(void); void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_ADC1_Init(void); int main(void) { uint16_t AD_RES = 0; uint16_t DATA = 0; HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_ADC1_Init(); SEVEN_SEG_Init(0); SEVEN_SEG_Enable(0); SEVEN_SEG_Write(0, 0); while (1) { // Start ADC Conversion HAL_ADC_Start(&hadc1); // Poll ADC1 Perihperal & TimeOut = 1mSec HAL_ADC_PollForConversion(&hadc1, 1); // Read The ADC Conversion Result AD_RES = HAL_ADC_GetValue(&hadc1); DATA = AD_RES>>2; if(DATA >= 999) { // Cap The Maximum Value To Be Displayed DATA = 999; } SEVEN_SEG_Write(0, DATA); HAL_Delay(100); } } void SysTick_CallBack(void) { SysTicks++; if(SysTicks == 5) // Each 5msec { SEVEN_SEG_Main(); SysTicks = 0; } } |
Note that the SEVEN_SEG_Main function is being called from the SysTick callback function. This function needs to be called inside the ISR handler for the SysTick timer. The HAL_Init initializes the systick timer and the HAL_Delay uses it to work as well. So, let’s open this file (stm32f1xx_it.c) and search for the SysTick handler and call our SysTick_Callback from there are shown below.
1 2 3 4 5 |
void SysTick_Handler(void) { HAL_IncTick(); SysTick_CallBack(); } |
Download The STM32 7-Segments Display With Knob LAB30
The Result For This LAB Testing (Video)
STM32 Temperature Sensor + 7-Segment Display
LAB Number | 31 |
LAB Title | STM32 Seven Segments Display With LM35 Temperature Sensor |
- Set up a new project as usual with system clock @ 72MHz
- Add the ECUAL / LM35 driver files to our project
- Add the ECUAL / SEVEN_SEGMENTS driver files to our project
- configure an LM35 sensor line instance in LM35_cfg.c file
- configure an instance in SEVEN_SEGMENTS_cfg.c file
- Initialize the seven segments instance and the LM35 sensor and read the temperature and write it to the display using the APIs. Sample the temperature sensor 10 times per second and update the display.
And now, let’s build this system step-by-step
Step1: Open CubeMX & Create New Project
Step2: Choose The Target MCU & Double-Click Its Name
STM32F103C8
Step3: Go To The Clock Configuration
Step4: Set The System Clock To Be 72MHz
Step5: In ADC1 Tab Enable AN8 Channel (B0 pin) For The LM35 Sensor
Step6: Generate The Initialization Code & Open The Project In Your IDE
Step7: Add the ECUAL LM35 driver files to your project
Follow This Tutorial which shows you How To Add Any ECUAL Driver To An STM32 Project step-by-step.
Step8: Add the ECUAL SEVEN_SEGMENTS driver files to your project
Here is The Application Code For This LAB (main.c)
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 |
#include "main.h" #include "../ECUAL/SEVEN_SEGMENTS/SEVEN_SEGMENTS.h" #include "../ECUAL/LM35/LM35.h" uint8_t SysTicks = 0; void SysTick_CallBack(void); void SystemClock_Config(void); static void MX_GPIO_Init(void); int main(void) { uint16_t Temperature = 0; HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); LM35_Init(0); SEVEN_SEG_Init(0); SEVEN_SEG_Enable(0); SEVEN_SEG_Write(0, 0); while (1) { Temperature = (uint16_t)LM35_Read(0); SEVEN_SEG_Write(0, Temperature); HAL_Delay(100); } } void SysTick_CallBack(void) { SysTicks++; if(SysTicks == 5) // Each 5msec { SEVEN_SEG_Main(); SysTicks = 0; } } |
Download The STM32 Seven Segments + LM35 Temperature Sensor LAB31
The Result For This LAB Testing (Video)
One Last Testing For STM32 7-Segment Driver
I’ve also done one last test that I’d like to share with you. It was an approximate measurement for the execution time for the function SEVEN_SEG_Main. Because we’re going to build a very basic operating system in the future and also make some RTOS applications, it’s important to know the execution time of such routines like the 7-segment display logic handler.
I’ve used a GPIO pin configured in fast mode push-pull driver output for fast edges switching on the output pin and driven it high before calling the SEVEN_SEG_Main function and bring it low when it returns. And it turned out to be 19μs which is amazing as a beginning and needs no more optimization in the meantime. We may not use this display in the future unless there is some requests by the readers. Because the LCD in I2C mode can be advantageous and displays more digits and information with just two pins that can be also used for other sensors. That’s it for today! and we’ll move on to the next tutorial.
Did you find this helpful? If yes, please consider supporting this work and sharing these tutorials!
Stay tuned for the upcoming tutorials and don’t forget to SHARE these tutorials. And consider SUPPORTING this work to keep publishing free content just like this!
Previous Tutorial | Tutorial 32 | Next Tutorial |