STM32 Keypad Interfacing Library 4×4 | Keypad Driver With Examples

Previous Tutorial Previous Tutorial Tutorial 35 Next Tutorial Next Tutorial
STM32 KeyPad Interfacing Driver (Library)
STM32 Course Home Page ????

 

STM32 Keypad LCD Tutorial Library Examples

 

In this tutorial, we’ll be discussing the usage of STM32 GPIO pins to interface and read a keypad matrix, It can be 3×3, 4×4, or whatever. I’ll also show you the Keypad library (driver) that I’ve developed for STM32 microcontrollers and discuss how it works and how it’s been built in this way.

We’ll do some tests, measurements, and spot the light on potential improvements and features that you can make and add to this driver code. But first of all, we’ll discuss how the keypad matrix works and the general procedure for reading buttons in a keypad.

Without further ado, let’s get right into it.

[toc]


   Required Components For LABs   

 

All the example code/LABs/projects in the course are going to be done using those boards below.

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 KeyPAD 4×4 Amazon eBay
Alphanumeric LCD Module Amazon eBay

★ Check The Full Course Complete Kit List

Some Extremely Useful Test Equipment For Troubleshooting:

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.


  Procedure For Reading a Keypad Matrix  

 

Before getting into how to read a keypad matrix, let’s first have a look at how it’s constructed internally and how the buttons are connected together. Here is a diagram down below for the internal structure of a typical 4×4 keypad matrix.

STM32 With Keypad STM32 Keypad Library Code

There exist a few different ways for interfacing such a keypad matrix to a microcontroller. While some of them are interrupt-driven, there are others that work by polling the pins and scanning through all the keys one by one. And we’re going to discuss how to implement a keypad scanning routine that doesn’t utilize the pin interrupt feature of the microcontroller.

Obviously, it’s going to be a little bit slower compared to the interrupt-based method in terms of reaction time, and also it’s time-consuming, however, it’s easily portable and almost guaranteed to work with any microcontroller not only STM32 families. Just keep that in mind.

Keypad Matrix Scanning Procedure

1- Configuration

First of all, we need to configure 8 GPIO pins. Four of which will be inputs and the other 4 are going to be output pins. Then you can hook the column pins to either the input or output pins, but for convenience, I’ll connect them to the 4 output pins. And last but not least, the 4-row pins will be connected to the 4 input pins of the microcontroller. As you can see in the diagram down below.

STM32 Keypad interfacing Library

2- Steady-state

The first state we’ve got to start with each scan cycle is the steady-state in which we output four ones (1’s) to the 4 output pins (columns). So, all the keypad buttons have a 1 on their right-side terminal. Therefore, if any button is pressed, the corresponding row input pin will read a 1, otherwise, it’ll read a zero.

If more than one button in the same row is pressed at the same time, the row input pin will still read a 1. And we’ll see in the next step how to identify which button is pressed in each row.

STM32 Keypad library tutorial

3- Read & Check Activated Rows

After reading the 4-row input pins, we now know the pressed button/buttons are located in which row/rows. So, we’ll cycle through those specific row buttons.

4- Cycle Through Activated Row Buttons

First, we’ll check the left-most button by outputting this [1-0-0-0] bit-pattern to the 4 output column pins. If that first button is pressed, the row input pin should still read a 1, otherwise, it’s going to be a 0.

Then, we’ll move to the next button and will use this bit pattern to check for it [0-1-0-0]. Next [0-0-1-0] and the last button will be checked with [0-0-0-1]. And repeat this step #4 for all rows that found to be activated in step #3.

 


   STM32 Keypad ECUAL Driver   

 

The ECUAL Keypad driver is built for STM32 microcontrollers using some GPIO pins. You’ll have to configure an instance of it and use the APIs to read your keypad 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 KEYPAD driver in the ECUAL directory as usual.

Keypad Driver Code Files

The Keypad driver consists of the following files:

  • KEYPAD.h
  • KEYPAD.c
  • KEYPAD_cfg.h
  • KEYPAD_cfg.c
STM32 Keypad Library Code Files

You’ll need only to modify the configuration files. The source code for this driver is found in (KEYPAD.c) and to use it you’ll include the header (KEYPAD.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 KEYPAD.h & KEYPAD_cfg.c files.

KEYPAD.h File

If you’re willing to use multiple keypad matrices, just adjust that number definition (KEYPAD_UNITS).

KEYPAD Driver APIs

As you’ve seen in the KEYPAD.h file, the provided APIs do all the basic functionalities that you may need from a Keypad driver library. It initializes the required GPIO pins and reads the raw state of the buttons matrix at any instance of time. And it also gives you the main scanning logic in the function KEYPAD_Scan() that you can call periodically within your SysTick ISR or in a task if you’re using an RTOS or whatever.

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.

KEYPAD_cfg.c File

I’ll discuss those configuration parameters in the next section down below.

Available Configurations For ECUAL KEYPAD Driver

From the code above in KEYPAD.h & KEYPAD_cfg.c you can see that there are not many parameters at all in the configuration structure. The config structure will be used to assign the pin you want to the 4-row pins and the 4-column pins, and that’s all.

Typical Usage Application Example

Here is a typical usage application for this driver code in order to initialize a keypad matrix and read a couple of buttons to drive ON or OFF two output LEDs.

Keypad Scan Function

In the KEYPAD.c source code file, you’ll find the implementation of this function “KEYPAD_Scan()“. 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 keypad scanning. It does handle all the logical operations for scanning all buttons in that specific keypad unit in your application and writes out the buttons states to the buffer array that you’ve got to check in the main application.

And yes, it has to be called repeatedly at a steady rate as we’ll see in one of the LAB examples hereafter.

 


 Keypad Buttons Read Example With LEDs – LAB 

 

LAB Number 35
LAB Title STM32 4×4 Keypad Buttons Read & LEDs Control
  • Set up a new project as usual with a system clock @ 72MHz or whatever your uC board supports
  • Add the ECUAL / LEDS driver files to our project. As shown here
  • Add the ECUAL / KEYPAD driver files to our project.
  • Configure 2 LEDs instances in LEDS_cfg.c file
  • Configure 1 Keypad instance in KEYPAD_cfg.c file
  • Initialize the LEDs & Keypad in the main application, read the buttons, turn ON or OFF the LEDs correspondingly.

Keypad buttons functions:

Key 1 Switch ON The Yellow LED
Key 2 Switch ON The Blue LED

 

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 (the one I’ll be using) or any other STM32 part you’ve got

Step3: Go To The RCC Clock Configuration

Step4: Set The System Clock To Be 72MHz or whatever your uC board supports

Step5: Generate The Initialization Code & Open The Project In Your IDE

Step6: Add the ECUAL LEDS driver files to your project

Follow This Tutorial which shows you How To Add Any ECUAL Driver To An STM32 Project step-by-step.

Adding ECUAL Driver To STM32 Project

Step7: Add the ECUAL KEYPAD driver files to your project, same as always

Now, we can start developing our application in the main.c source file.

Here is The Application Code For This LAB (main.c)

Note that the KEYPAD_Scan function is being called from the SysTick callback function once each 5 SysTicks or once/5msec. This callback function needs to be called inside the ISR handler for the SysTick timer. The HAL_Init initializes the SysTick timer (tick time = 1msec) and the HAL_Delay uses it to work as well. So, let’s now open this file (stm32f1xx_it.c) and search for the SysTick handler and call our SysTick_Callback from there as shown below.

Download The STM32 Keypad With LEDs LAB35

 

The Result For This LAB Testing (Video)

 


 STM32 With Keypad & LCD Example – LAB 

 

LAB Number 36
LAB Title STM32 With 4×4 Keypad And LCD 16×2
  • Set up a new project as usual with a system clock @ 72MHz or whatever your uC board supports
  • Add the ECUAL / LCD driver files to our project. As shown here
  • Add the ECUAL / KEYPAD driver files to our project.
  • Create a source folder name it util & Add the util files to our project.
  • Configure 1 LCD instance in LCD_cfg.c file
  • Configure 1 Keypad instance in KEYPAD_cfg.c file
  • Initialize the LCD & Keypad in the main application, read the buttons, write to the LCD correspondingly.

Keypad buttons functions:

Keys [0 -> 9]  Writes “0->9” to the LCD
Keys [ # and *] Writes “#” and “*” to the LCD
Key F1 Right-Shift the entire LCD display
Key F2 Left-Shift the entire LCD display
Key F4 Clear the LCD screen

 

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 (the one I’ll be using) or any other STM32 part you’ve got

Step3: Go To The RCC Clock Configuration

Step4: Set The System Clock To Be 72MHz or whatever your uC board supports

Step5: Generate The Initialization Code & Open The Project In Your IDE

Step6: Add the ECUAL LCD driver files to your project

Follow This Tutorial which shows you How To Add Any ECUAL Driver To An STM32 Project step-by-step.

Adding ECUAL Driver To STM32 Project

Step7: Add the ECUAL KEYPAD driver files to your project, same as always

Step8: Add the util files to your project, as shown in the guide above

Now, we can start developing our application in the main.c source file.

Here is The Application Code For This LAB (main.c)

Note that the KEYPAD_Scan function is being called from the SysTick callback function once each 5 SysTicks or once/5msec. This callback function needs to be called inside the ISR handler for the SysTick timer. The HAL_Init initializes the SysTick timer (tick time = 1msec) and the HAL_Delay uses it to work as well. So, let’s now open this file (stm32f1xx_it.c) and search for the SysTick handler and call our SysTick_Callback from there as shown below.

Download The STM32 Keypad With LCD LAB36

 

The Result For This LAB Testing (Video)

 


 Some Interesting Tests For Keypad Driver Code 

 

I’ve also done some final tests that I’d like to share with you. As 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 the keypad scanning routine and also have a rough estimate for the response time given that the KEYPAD_Scan() function is called once/5msec.

1- Response Time

The time it takes the system to respond to a keypad button press or release event is said to be the response time. And this is what I’ve decided to test out, using 2 channels of my DSO and measure the timing between button & LED signals.

The keypad scan cycle is set to once/5msec as you’ve seen in the code. Hence, you can press/release any button almost anywhere in time between each consecutive scan cycles, therefore, the expected response time can be anywhere from ZERO sec up to 5msec at maximum with an equal probability distribution.

Here in this test, I did find the readings to be exactly as expected ranging from 0 up to 5msec. And you can improve the response time by shortening the measurement cycle, maybe make it 1msec instead of 5msec. And guarantee that the response time will be always shorter than 1msec.

STM32 Keypad Reading Response Time

2- Keypad Scan Execution Time & CPU Load

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 KEYPAD_Scan function and bring it low when it returns. And now for the interesting part!

If you’ve taken the time to check the source code for my KEYPAD driver, you’ll notice that the scanning logic skips over any row that has no button pressed which is obviously a logical thing to do. But the result of that is variance in execution time depending on the current situation,

In other words, when no button is pressed, the execution time is found to be minimal which is obvious. Because the scanning logic will skip over to the end of the function. However, when one or more buttons in the same row is pressed, the execution time increases. It doesn’t increase if more than one button are pressed while they are in the same row. This is also an obvious fact if you’ve checked how the code works.

When 2 buttons of different rows are pressed, the execution time increases a little bit, and it gets to maximum when 4 buttons, one of each row are pressed at the same time.

Note that, if you’re designing a digital lock password system or watch timer or whatever, the user is not expected to click more than one button at the same time. But I did want to test that out and have this piece of info ready if we needed it in the future or just for the sake of curiosity!

Condition The Measured Execution Time CPU Load
No Button is pressed at all 24µs 0.48%
One or all buttons of the 1st row are pressed at once 42µs 0.84%
One or all buttons of the first 2 rows are pressed at once 66µs 1.3%
One or all buttons of the first 3 row are pressed at once 88µs 1.76%
One button of each row or all keypad 16 buttons are pressed at the same time 110µs 2.2%

Generally speaking, you should only care for the first test result at it’s going to be the case for almost any keypad-based project. And it looks ok to me in the meantime we don’t need further optimizations but you can, of course, make it run much quicker as I can clearly see some repeated logic pieces in my code that maybe get reduced in one way or another.

3- Keypad Button Bouncing

I did also notice on the DSO signal that the keypad buttons are bouncing just like any other mechanical switchs. But there is some sort of inherent immunity in our system against this because of the repetitive scanning cycle for the keypad each 5msec, it turns out to be de-coupling the input bouncing from appearing at the LED output almost perfectly.

However and if you’re using a shorter scanning cycle with a fast reaction time to a key press event, the system will be more likely to falsely detect a button press/release event. And it becomes a necessity to implement a debouncing technique. And I’d prefer the one I did previously demonstrate in this article. By including MATH/FIR there you’ll find a simple digital filter that can be used with the keypad button states array to knock-down any high-frequency artifacts caused by the key bouncing.

 

All in all, that’s it for this tutorial! I’d like to revisit this topic again in the future after I collect some questions, suggestions, and corrections from many readers.

 


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 Previous Tutorial Tutorial 35 Next Tutorial Next Tutorial

 

Share This Page With Your Network!
Join Our +25,000 Newsletter Subscribers!

Stay Updated With All New Content Releases. You Also Get Occasional FREE Coupon Codes For Courses & Other Stuff!

Photo of author
Author
Khaled Magdy
Embedded systems engineer with several years of experience in embedded software and hardware design. I work as an embedded SW engineer in the Automotive & e-Mobility industry. However, I still do Hardware design and SW development for DSP, Control Systems, Robotics, AI/ML, and other fields I'm passionate about.
I love reading, writing, creating projects, and teaching. A reader by day and a writer by night, it's my lifestyle. I believe that the combination of brilliant minds, bold ideas, and a complete disregard for what is possible, can and will change the world! I will be there when it happens, will you?

Leave a Comment