Phone

    00852-6915 1330
  • Contents

4×4 matrix keypad in STM32

Keypads are input devices that are being widely used in many embedded system projects. It can be found in appliances, door locks, and industrial machines. Keypads are used to take input from the user in the form of numbers or characters which can further be used for processing such as password, menu selection and navigating among different options. One of the most common and low-cost keypads is the matrix keypad with 4×4 or 3×3 buttons. In this article we will discuss how a low cost 4×4 matrix keypad can be used in STM32. Before proceeding further, we will need to know few things.

How a 4×4 keypad works?

 4×4 keypad

In microcontrollers usually a pin is used to take input from the user. This input can be either 1 or 0. Multiple 1’s and 0’s can be combined to store more information. For this purpose, multiple input pins will be required. However, this becomes impractical when the input pins required exceed certain number such as 16 or 9 as the microcontrollers do not have this many pins available.

The 4×4 matrix keypad solves this problem and reduced the required number of pins to 8 or 6. It  is made of a thin and flexible membrane. The 16 keys of the 4×4 keypad module are arranged in a matrix of rows and columns. A copper trace connects each of these switches to the others. The rows and column are not connected to each other in normal condition. When we push a key, a column and a row come into contact with each other. In matrix keypads the buttons are divided among rows and columns. Four buttons lie on each row and each column. Thus, columns are connected to external input pins of microcontroller while the rows are connected to output pins of microcontroller. The output pins are high all the time. When a button is pressed the corresponding column goes high and the microcontroller detects it. Finding which column has been activated is easy as each column is connected to a separate pin, however, finding a row is difficult. Once both row and column are identified then the corresponding button can be identified. A clever method to identify the pressed key is to switch off all output pins except one, and then check which input pins is high. Doing this for all the output pins will identify the row. Once the row number is found out, the button can easily be traced out.

matrix keypad in STM32

STM32 F401 implementation

STM32 F401

In CubeMX the relative microcontroller of our choice is selected which in our case is STM32 F401CDU6. The GPIOs that need to be selected as output or external interrupt input are given in the figure above. In the NVIC tab the interrupt should be enabled. Other necessary settings are given below.

  • RCC → Crystal/Ceramic Resonator
  • SYS → Debug → Serial Wire
  • Clock Configuration → HCLK → 84 MHz
  • Clock Configuration → PLL Source Mux → HSE

 

Once the CubeMX code is generated the following code should be added to the /* USER CODE BEGIN PV */ section.

/* USER CODE BEGIN PV */

  GPIO_InitTypeDef GPIO_InitStructPrivate = {0};

  uint32_t previousM = 0;

  uint32_t currentM = 0;

  uint8_t key = 0;

  uint8_t InputData[5] = {0};

  int i = 0;

/* USER CODE END PV */

This code section defines the necessary variables that will come handy later.

In the main.c section in /* USER CODE BEGIN 2 */ the output configured pins should be set to 1.

  /* USER CODE BEGIN 2 */

  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, 1);

  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, 1);

  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, 1);

  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, 1);

  /* USER CODE END 2 */  

While the interrupt callback function void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin) should be added to /* USER CODE BEGIN 4 */ section.

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)

{

  currentM = HAL_GetTick();

  if (currentM - previousM > 10) {

    /*Configure GPIO pins : PB6 PB7 PB8 PB9 to GPIO_INPUT*/

    GPIO_InitStructPrivate.Pin = GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9;

    GPIO_InitStructPrivate.Mode = GPIO_MODE_INPUT;

    GPIO_InitStructPrivate.Pull = GPIO_NOPULL;

    GPIO_InitStructPrivate.Speed = GPIO_SPEED_FREQ_LOW;

    HAL_GPIO_Init(GPIOB, &GPIO_InitStructPrivate);

 

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, 1);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, 0);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, 0);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, 0);

    if(GPIO_Pin == GPIO_PIN_6 && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6))

    {

      key = 68; //ASCII value of D

    }

    else if(GPIO_Pin == GPIO_PIN_7 && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7))

    {

      key = 67; //ASCII value of C

    }

    else if(GPIO_Pin == GPIO_PIN_8 && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8))

    {

      key = 66; //ASCII value of B

    }

    else if(GPIO_Pin == GPIO_PIN_9 && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_9))

    {

      key = 65; //ASCII value of A

    }

 

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, 0);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, 1);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, 0);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, 0);

    if(GPIO_Pin == GPIO_PIN_6 && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6))

    {

      key = 35; //ASCII value of #

    }

    else if(GPIO_Pin == GPIO_PIN_7 && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7))

    {

      key = 57; //ASCII value of 9

      if (i == 4)

      {

       //Send Data

      }

      else

      {

       InputData[i] = 9;

      }

      if(i <= 4)

      {

       i = i + 1;

 

      }

      else

      {

       i = 0;

      }

    }

    else if(GPIO_Pin == GPIO_PIN_8 && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8))

    {

      key = 54; //ASCII value of 6

      if (i == 4)

      {

       //Send Data

      }

      else

      {

       InputData[i] = 6;

      }

      if(i <= 4)

      {

       i = i + 1;

 

      }

      else

      {

       i = 0;

      }

    }

    else if(GPIO_Pin == GPIO_PIN_9 && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_9))

    {

      key = 51; //ASCII value of 3

      if (i == 4)

            {

             //Send Data

            }

            else

            {

             InputData[i] = 3;

            }

            if(i <= 4)

            {

             i = i + 1;

 

            }

            else

            {

             i = 0;

            }

    }

 

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, 0);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, 0);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, 1);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, 0);

    if(GPIO_Pin == GPIO_PIN_6 && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6))

    {

      key = 48; //ASCII value of 0

      if (i == 4)

      {

       //Send Data

      }

      else

      {

       InputData[i] = 0;

      }

      if(i <= 4)

      {

       i = i + 1;

 

      }

      else

      {

       i = 0;

      }

    }

    else if(GPIO_Pin == GPIO_PIN_7 && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7))

    {

      key = 56; //ASCII value of 8

      if (i == 4)

      {

       //Send Data

      }

      else

      {

       InputData[i] = 8;

      }

      if(i <= 4)

      {

       i = i + 1;

 

      }

      else

      {

       i = 0;

      }

    }

    else if(GPIO_Pin == GPIO_PIN_8 && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8))

    {

      key = 53; //ASCII value of 5

      if (i == 4)

      {

       //Send Data

      }

      else

      {

       InputData[i] = 5;

      }

      if(i <= 4)

      {

       i = i + 1;

 

      }

      else

      {

       i = 0;

      }

    }

    else if(GPIO_Pin == GPIO_PIN_9 && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_9))

    {

      key = 50; //ASCII value of 2

      if (i == 4)

      {

       //Send Data

      }

      else

      {

       InputData[i] = 2;

      }

      if(i <= 4)

      {

       i = i + 1;

 

      }

      else

      {

       i = 0;

      }

    }

 

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, 0);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, 0);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, 0);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, 1);

    if(GPIO_Pin == GPIO_PIN_6 && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6))

    {

      key = 42; //ASCII value of *

 

    }

    else if(GPIO_Pin == GPIO_PIN_7 && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7))

    {

      key = 55; //ASCII value of 7

      if (i == 4)

      {

       //Send Data

      }

      else

      {

       InputData[i] = 7;

      }

      if(i <= 4)

      {

       i = i + 1;

 

      }

      else

      {

       i = 0;

      }

    }

    else if(GPIO_Pin == GPIO_PIN_8 && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8))

    {

      key = 52; //ASCII value of 4

      if (i == 4)

      {

       //Send Data

      }

      else

      {

       InputData[i] = 4;

      }

      if(i <= 4)

      {

       i = i + 1;

 

      }

      else

      {

       i = 0;

      }

    }

    else if(GPIO_Pin == GPIO_PIN_9 && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_9))

    {

      key = 49; //ASCII value of 1

      if (i == 4)

      {

       //Send Data

      }

      else

      {

       InputData[i] = 1;

      }

      if(i <= 4)

      {

       i = i + 1;

 

      }

      else

      {

       i = 0;

      }

    }

 

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, 1);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, 1);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, 1);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, 1);

    /*Configure GPIO pins : PB6 PB7 PB8 PB9 back to EXTI*/

    GPIO_InitStructPrivate.Mode = GPIO_MODE_IT_RISING;

    GPIO_InitStructPrivate.Pull = GPIO_PULLDOWN;

    HAL_GPIO_Init(GPIOB, &GPIO_InitStructPrivate);

    previousM = currentM;

 

  }

In the callback function the two lines

currentM = HAL_GetTick();

  if (currentM - previousM > 10)

takes care of the debouncing of the buttons. In keypad it is a common problem that a but hits once is recorded twice or thrice. So, take of that, a little delay is added at the beginning of callback function.

The complete code is given below.

#include "main.h"

 

/* USER CODE BEGIN PV */

  GPIO_InitTypeDef GPIO_InitStructPrivate = {0};

  uint32_t previousM = 0;

  uint32_t currentM = 0;

  uint8_t key = 0;

  uint8_t InputData[5] = {0};

  int i = 0;

/* USER CODE END PV */

 

/* Private function prototypes -----------------------------------------------*/

void SystemClock_Config(void);

static void MX_GPIO_Init(void);

/* USER CODE BEGIN PFP */

 

/* USER CODE END PFP */

 

/* Private user code ---------------------------------------------------------*/

/* USER CODE BEGIN 0 */

 

/* USER CODE END 0 */

 

/**

  * @brief  The application entry point.

  * @retval int

  */

int main(void)

{

  /* USER CODE BEGIN 1 */

 

  /* USER CODE END 1 */

 

  /* MCU Configuration--------------------------------------------------------*/

 

  /* Reset of all peripherals, Initializes the Flash interface and the Systick. */

  HAL_Init();

 

  /* USER CODE BEGIN Init */

 

  /* USER CODE END Init */

 

  /* Configure the system clock */

  SystemClock_Config();

 

  /* USER CODE BEGIN SysInit */

 

  /* USER CODE END SysInit */

 

  /* Initialize all configured peripherals */

  MX_GPIO_Init();

  /* USER CODE BEGIN 2 */

  HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, 1);

  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, 1);

  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, 1);

  HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, 1);

  /* USER CODE END 2 */

 

  /* Infinite loop */

  /* USER CODE BEGIN WHILE */

  while (1)

  {

    /* USER CODE END WHILE */

 

    /* USER CODE BEGIN 3 */

  }

  /* USER CODE END 3 */

}

 

 

/* USER CODE BEGIN 4 */

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)

{

  currentM = HAL_GetTick();

  if (currentM - previousM > 10) {

    /*Configure GPIO pins : PB6 PB7 PB8 PB9 to GPIO_INPUT*/

    GPIO_InitStructPrivate.Pin = GPIO_PIN_6|GPIO_PIN_7|GPIO_PIN_8|GPIO_PIN_9;

    GPIO_InitStructPrivate.Mode = GPIO_MODE_INPUT;

    GPIO_InitStructPrivate.Pull = GPIO_NOPULL;

    GPIO_InitStructPrivate.Speed = GPIO_SPEED_FREQ_LOW;

    HAL_GPIO_Init(GPIOB, &GPIO_InitStructPrivate);

 

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, 1);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, 0);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, 0);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, 0);

    if(GPIO_Pin == GPIO_PIN_6 && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6))

    {

      key = 68; //ASCII value of D

    }

    else if(GPIO_Pin == GPIO_PIN_7 && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7))

    {

      key = 67; //ASCII value of C

    }

    else if(GPIO_Pin == GPIO_PIN_8 && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8))

    {

      key = 66; //ASCII value of B

    }

    else if(GPIO_Pin == GPIO_PIN_9 && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_9))

    {

      key = 65; //ASCII value of A

    }

 

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, 0);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, 1);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, 0);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, 0);

    if(GPIO_Pin == GPIO_PIN_6 && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6))

    {

      key = 35; //ASCII value of #

    }

    else if(GPIO_Pin == GPIO_PIN_7 && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7))

    {

      key = 57; //ASCII value of 9

      if (i == 4)

      {

       //Send Data

      }

      else

      {

       InputData[i] = 9;

      }

      if(i <= 4)

      {

       i = i + 1;

 

      }

      else

      {

       i = 0;

      }

    }

    else if(GPIO_Pin == GPIO_PIN_8 && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8))

    {

      key = 54; //ASCII value of 6

      if (i == 4)

      {

       //Send Data

      }

      else

      {

       InputData[i] = 6;

      }

      if(i <= 4)

      {

       i = i + 1;

 

      }

      else

      {

       i = 0;

      }

    }

    else if(GPIO_Pin == GPIO_PIN_9 && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_9))

    {

      key = 51; //ASCII value of 3

      if (i == 4)

            {

             //Send Data

            }

            else

            {

             InputData[i] = 3;

            }

            if(i <= 4)

            {

             i = i + 1;

 

            }

            else

            {

             i = 0;

            }

    }

 

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, 0);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, 0);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, 1);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, 0);

    if(GPIO_Pin == GPIO_PIN_6 && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6))

    {

      key = 48; //ASCII value of 0

      if (i == 4)

      {

       //Send Data

      }

      else

      {

       InputData[i] = 0;

      }

      if(i <= 4)

      {

       i = i + 1;

 

      }

      else

      {

       i = 0;

      }

    }

    else if(GPIO_Pin == GPIO_PIN_7 && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7))

    {

      key = 56; //ASCII value of 8

      if (i == 4)

      {

       //Send Data

      }

      else

      {

       InputData[i] = 8;

      }

      if(i <= 4)

      {

       i = i + 1;

 

      }

      else

      {

       i = 0;

      }

    }

    else if(GPIO_Pin == GPIO_PIN_8 && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8))

    {

      key = 53; //ASCII value of 5

      if (i == 4)

      {

       //Send Data

      }

      else

      {

       InputData[i] = 5;

      }

      if(i <= 4)

      {

       i = i + 1;

 

      }

      else

      {

       i = 0;

      }

    }

    else if(GPIO_Pin == GPIO_PIN_9 && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_9))

    {

      key = 50; //ASCII value of 2

      if (i == 4)

      {

       //Send Data

      }

      else

      {

       InputData[i] = 2;

      }

      if(i <= 4)

      {

       i = i + 1;

 

      }

      else

      {

       i = 0;

      }

    }

 

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, 0);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, 0);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, 0);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, 1);

    if(GPIO_Pin == GPIO_PIN_6 && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_6))

    {

      key = 42; //ASCII value of *

 

    }

    else if(GPIO_Pin == GPIO_PIN_7 && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7))

    {

      key = 55; //ASCII value of 7

      if (i == 4)

      {

       //Send Data

      }

      else

      {

       InputData[i] = 7;

      }

      if(i <= 4)

      {

       i = i + 1;

 

      }

      else

      {

       i = 0;

      }

    }

    else if(GPIO_Pin == GPIO_PIN_8 && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_8))

    {

      key = 52; //ASCII value of 4

      if (i == 4)

      {

       //Send Data

      }

      else

      {

       InputData[i] = 4;

      }

      if(i <= 4)

      {

       i = i + 1;

 

      }

      else

      {

       i = 0;

      }

    }

    else if(GPIO_Pin == GPIO_PIN_9 && HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_9))

    {

      key = 49; //ASCII value of 1

      if (i == 4)

      {

       //Send Data

      }

      else

      {

       InputData[i] = 1;

      }

      if(i <= 4)

      {

       i = i + 1;

 

      }

      else

      {

       i = 0;

      }

    }

 

    HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, 1);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_3, 1);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_4, 1);

    HAL_GPIO_WritePin(GPIOB, GPIO_PIN_5, 1);

    /*Configure GPIO pins : PB6 PB7 PB8 PB9 back to EXTI*/

    GPIO_InitStructPrivate.Mode = GPIO_MODE_IT_RISING;

    GPIO_InitStructPrivate.Pull = GPIO_PULLDOWN;

    HAL_GPIO_Init(GPIOB, &GPIO_InitStructPrivate);

    previousM = currentM;

 

  }

}

 

 

Leave a Reply

We'd love to hear from you! Feel free to share your thoughts and comments below. Rest assured, your email address will remain private.

Name *
Email *
Captcha *
Rating:

Kynix

  • How to purchase

  • Order
  • Search & Inquiry
  • Shipping & Tracking
  • Payment Methods
  • Contact Us

  • Tel: 00852-6915 1330
  • Email: info@kynix.com
  • Follow Us

authentication

Kynix

© 2008-2026 kynix.com all rights reserved.