【STM32扫描4x4矩阵键盘模块】 4x4 matrix keypad interface

这篇具有很好参考价值的文章主要介绍了【STM32扫描4x4矩阵键盘模块】 4x4 matrix keypad interface。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

【STM32扫描4x4矩阵键盘模块】 4x4 matrix keypad interface


4x4矩阵键盘模块

矩阵键盘是将多个按键排布成类似矩阵形式的键盘组。为了减少IO资源的占用,将键盘组的每一行和每一列接入到GPIO。如下图的薄膜型键盘模块,第一个键盘组是3行x4列,所以共使用了3+4=7个GPIO口,即用7个GPIO表现了12个按键的状态;第二个键盘组是4行x4列,共使用了4+4=8个GPIO,即用8个GPIO表现了16个按键的状态。
stm32矩阵键盘扫描程序,STM32,单片机,stm32,嵌入式硬件
怎样用较少的IO口来表示更多的状态呢? 下面分析一下矩阵键盘的原理。

矩阵键盘的原理

下面以4x4矩阵键盘为例:
stm32矩阵键盘扫描程序,STM32,单片机,stm32,嵌入式硬件
如上图所示4x4矩阵,同一行的按键开关一侧连接在行线上,从上到下分别记作R1、R2、R3、R4。同一列的按键开关一侧连接在列线上,从左到右分别记作C1、C2、C3、C4。 R1、R2、R3、R4连接到STM32的GPIO,并设置为输出模式。C1、C2、C3、C4接入到STM32的GPIO,设置为输入上拉模式。

行列扫描法

  1. 第1行输出为0,第2、3、4行输出为1;
  2. 分别判断四根列线
    • C1为低电平, 则按键“1”被按下;
    • C2为低电平, 则按键“2”被按下;
    • C3为低电平, 则按键“3”被按下;
    • C4为低电平, 则按键“A”被按下;

  1. 第2行输出为0,第1、3、4行输出为1;
  2. 分别判断四根列线
    • C1为低电平, 则按键“4”被按下;
    • C2为低电平, 则按键“5”被按下;
    • C3为低电平, 则按键“6”被按下;
    • C4为低电平, 则按键“B”被按下;

  1. 第3行输出为0,第1、2、4行输出为1;
  2. 分别判断四根列线
    • C1为低电平, 则按键“7”被按下;
    • C2为低电平, 则按键“8”被按下;
    • C3为低电平, 则按键“9”被按下;
    • C4为低电平, 则按键“C”被按下;

  1. 第4行输出为0,第1、2、3行输出为1;
  2. 分别判断四根列线
    • C1为低电平, 则按键“*”被按下;
    • C2为低电平, 则按键“0”被按下;
    • C3为低电平, 则按键“#”被按下;
    • C4为低电平, 则按键“D”被按下;

代码实现(基于HAL库)

keypad.h

#ifndef __KEYPAD_H__
#define __KEYPAD_H__


#include "gpio.h"
#include "main.h"

#define KEYPAD_DEBOUNCE_DELAYTIME			20u

#define KEYPAD_COLUMN_4_Pin 				GPIO_PIN_15
#define KEYPAD_COLUMN_4_GPIO_Port 			GPIOB
#define KEYPAD_COLUMN_3_Pin 				GPIO_PIN_14
#define KEYPAD_COLUMN_3_GPIO_Port 			GPIOB
#define KEYPAD_COLUMN_2_Pin 				GPIO_PIN_13
#define KEYPAD_COLUMN_2_GPIO_Port 			GPIOB
#define KEYPAD_COLUMN_1_Pin 				GPIO_PIN_12
#define KEYPAD_COLUMN_1_GPIO_Port 			GPIOB

#define KEYPAD_ROW_4_Pin 					GPIO_PIN_4
#define KEYPAD_ROW_4_GPIO_Port 				GPIOA
#define KEYPAD_ROW_3_Pin 					GPIO_PIN_5
#define KEYPAD_ROW_3_GPIO_Port 				GPIOA
#define KEYPAD_ROW_2_Pin 					GPIO_PIN_6
#define KEYPAD_ROW_2_GPIO_Port 				GPIOA
#define KEYPAD_ROW_1_Pin 					GPIO_PIN_7
#define KEYPAD_ROW_1_GPIO_Port 				GPIOA

#define KEYPAD_ROW_1_LOW					XY_GPIO_SetPinLow(KEYPAD_ROW_1_GPIO_Port, KEYPAD_ROW_1_Pin)
#define KEYPAD_ROW_1_HIGH					XY_GPIO_SetPinHigh(KEYPAD_ROW_1_GPIO_Port, KEYPAD_ROW_1_Pin)

#define KEYPAD_ROW_2_LOW					XY_GPIO_SetPinLow(KEYPAD_ROW_2_GPIO_Port, KEYPAD_ROW_2_Pin)
#define KEYPAD_ROW_2_HIGH					XY_GPIO_SetPinHigh(KEYPAD_ROW_2_GPIO_Port, KEYPAD_ROW_2_Pin)

#define KEYPAD_ROW_3_LOW					XY_GPIO_SetPinLow(KEYPAD_ROW_3_GPIO_Port, KEYPAD_ROW_3_Pin)
#define KEYPAD_ROW_3_HIGH					XY_GPIO_SetPinHigh(KEYPAD_ROW_3_GPIO_Port, KEYPAD_ROW_3_Pin)

#define KEYPAD_ROW_4_LOW					XY_GPIO_SetPinLow(KEYPAD_ROW_4_GPIO_Port, KEYPAD_ROW_4_Pin)
#define KEYPAD_ROW_4_HIGH					XY_GPIO_SetPinHigh(KEYPAD_ROW_4_GPIO_Port, KEYPAD_ROW_4_Pin)


#define KEYPAD_ROW_HIGH_BUT_1 \
{\
	KEYPAD_ROW_1_LOW;\
	KEYPAD_ROW_2_HIGH;\
	KEYPAD_ROW_3_HIGH;\
	KEYPAD_ROW_4_HIGH;\
}

#define KEYPAD_ROW_HIGH_BUT_2 \
{\
	KEYPAD_ROW_1_HIGH;\
	KEYPAD_ROW_2_LOW;\
	KEYPAD_ROW_3_HIGH;\
	KEYPAD_ROW_4_HIGH;\
}

#define KEYPAD_ROW_HIGH_BUT_3 \
{\
	KEYPAD_ROW_1_HIGH;\
	KEYPAD_ROW_2_HIGH;\
	KEYPAD_ROW_3_LOW;\
	KEYPAD_ROW_4_HIGH;\
}

#define KEYPAD_ROW_HIGH_BUT_4 \
{\
	KEYPAD_ROW_1_HIGH;\
	KEYPAD_ROW_2_HIGH;\
	KEYPAD_ROW_3_HIGH;\
	KEYPAD_ROW_4_LOW;\
}


#define KEYPAD_COLUMN_1_CHECK			!XY_GPIO_GetInputPinValue(KEYPAD_COLUMN_1_GPIO_Port, KEYPAD_COLUMN_1_Pin)
#define KEYPAD_COLUMN_2_CHECK			!XY_GPIO_GetInputPinValue(KEYPAD_COLUMN_2_GPIO_Port, KEYPAD_COLUMN_2_Pin)
#define KEYPAD_COLUMN_3_CHECK			!XY_GPIO_GetInputPinValue(KEYPAD_COLUMN_3_GPIO_Port, KEYPAD_COLUMN_3_Pin)
#define KEYPAD_COLUMN_4_CHECK			!XY_GPIO_GetInputPinValue(KEYPAD_COLUMN_4_GPIO_Port, KEYPAD_COLUMN_4_Pin)

#define KEYPAD_NO_PRESSED					(uint8_t)0xFF

typedef enum {
	KEYPAD_Button_0 = 0x00,                     /*!< Button 0 code */
	KEYPAD_Button_1 = 0x01,                     /*!< Button 1 code */
	KEYPAD_Button_2 = 0x02,                     /*!< Button 2 code */
	KEYPAD_Button_3 = 0x03,                     /*!< Button 3 code */
	KEYPAD_Button_4 = 0x04,                     /*!< Button 4 code */
	KEYPAD_Button_5 = 0x05,                     /*!< Button 5 code */
	KEYPAD_Button_6 = 0x06,                     /*!< Button 6 code */
	KEYPAD_Button_7 = 0x07,                     /*!< Button 7 code */
	KEYPAD_Button_8 = 0x08,                     /*!< Button 8 code */
	KEYPAD_Button_9 = 0x09,                     /*!< Button 9 code */
	KEYPAD_Button_STAR = 0x0A,                  /*!< Button START code */
	KEYPAD_Button_HASH = 0x0B,                  /*!< Button HASH code */
	KEYPAD_Button_A = 0x0C,	                   /*!< Button A code. Only on large size */
	KEYPAD_Button_B = 0x0D,	                   /*!< Button B code. Only on large size */
	KEYPAD_Button_C = 0x0E,	                   /*!< Button C code. Only on large size */
	KEYPAD_Button_D = 0x0F,	                   /*!< Button D code. Only on large size */
	KEYPAD_Button_NOPRESS = KEYPAD_NO_PRESSED
} KEYPAD_Button_t;


static inline char *stringFromKeypadButton(KEYPAD_Button_t key)
{
    static char *strings[] = { 	"		KEYPAD_Button_0", "KEYPAD_Button_1", "KEYPAD_Button_2", "KEYPAD_Button_3",
										"KEYPAD_Button_4", "KEYPAD_Button_5", "KEYPAD_Button_6", "KEYPAD_Button_7",
										"KEYPAD_Button_8", "KEYPAD_Button_9", "KEYPAD_Button_STAR", "KEYPAD_Button_HASH",
										"KEYPAD_Button_A", "KEYPAD_Button_B", "KEYPAD_Button_C", "KEYPAD_Button_D"
    						};

    return strings[key];
}

uint8_t KEYPAD_READ(void);

void KEYPAD_Init(void);

void KEYPAD_Debounce_Delay(uint32_t debounceDelay);

#endif /*__KEYPAD_H__ */


keypad.c

#include "keypad.h"


uint8_t KEYPAD_INT_Buttons[4][4] = {
	{0x01, 0x02, 0x03, 0x0C},
	{0x04, 0x05, 0x06, 0x0D},
	{0x07, 0x08, 0x09, 0x0E},
	{0x0A, 0x00, 0x0B, 0x0F},
};

// initialize keypad
void KEYPAD_Init(void)
{

  GPIO_InitTypeDef GPIO_InitStruct = {0};

  /* GPIO Ports Clock Enable */
  __HAL_RCC_GPIOD_CLK_ENABLE();
  __HAL_RCC_GPIOA_CLK_ENABLE();
  __HAL_RCC_GPIOB_CLK_ENABLE();

  /*Configure GPIO pin Output Level */
  HAL_GPIO_WritePin(GPIOA, KEYPAD_ROW_4_Pin|KEYPAD_ROW_3_Pin|KEYPAD_ROW_2_Pin|KEYPAD_ROW_1_Pin, GPIO_PIN_SET);

  /*Configure GPIO pins : PAPin PAPin PAPin PAPin */
  GPIO_InitStruct.Pin = KEYPAD_COLUMN_4_Pin|KEYPAD_COLUMN_3_Pin|KEYPAD_COLUMN_2_Pin|KEYPAD_COLUMN_1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_INPUT;
  GPIO_InitStruct.Pull = GPIO_PULLUP;
  HAL_GPIO_Init(GPIOB, &GPIO_InitStruct);

  /*Configure GPIO pins : PAPin PAPin PAPin PAPin */
  GPIO_InitStruct.Pin = KEYPAD_ROW_4_Pin|KEYPAD_ROW_3_Pin|KEYPAD_ROW_2_Pin|KEYPAD_ROW_1_Pin;
  GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP;
  GPIO_InitStruct.Pull = GPIO_NOPULL;
  GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
  HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

// private function for "PULL DOWN SPECIFIC ROW"
void KEYPAD_INT_PullDownRow(uint8_t row)
{
	switch(row)
	{
	case 1:
		KEYPAD_ROW_HIGH_BUT_1;					// pull down row 1
		break;
	case 2:
		KEYPAD_ROW_HIGH_BUT_2;					// pull down row 2
		break;
	case 3:
		KEYPAD_ROW_HIGH_BUT_3;					// pull down row 3
		break;
	case 4:
		KEYPAD_ROW_HIGH_BUT_4;					// pull down row 4
		break;
	default:
		break;
	}
}

// private function for "check each column after pulling down row"
uint8_t KEYPAD_INT_CheckColumn(uint8_t row)
{
	if(KEYPAD_COLUMN_1_CHECK)
	{
		KEYPAD_Debounce_Delay(KEYPAD_DEBOUNCE_DELAYTIME);
		if(KEYPAD_COLUMN_1_CHECK)
		{
			return KEYPAD_INT_Buttons[row - 1][0];
		}
	}
	if(KEYPAD_COLUMN_2_CHECK)
	{
		KEYPAD_Debounce_Delay(KEYPAD_DEBOUNCE_DELAYTIME);
		if(KEYPAD_COLUMN_2_CHECK)
		{
			return KEYPAD_INT_Buttons[row - 1][1];
		}
	}
	if(KEYPAD_COLUMN_3_CHECK)
	{
		KEYPAD_Debounce_Delay(KEYPAD_DEBOUNCE_DELAYTIME);
		if(KEYPAD_COLUMN_3_CHECK)
		{
			return KEYPAD_INT_Buttons[row - 1][2];
		}
	}
	if(KEYPAD_COLUMN_4_CHECK)
	{
		KEYPAD_Debounce_Delay(KEYPAD_DEBOUNCE_DELAYTIME);
		if(KEYPAD_COLUMN_4_CHECK)
		{
			return KEYPAD_INT_Buttons[row - 1][3];
		}
	}
	return KEYPAD_NO_PRESSED;
}


uint8_t KEYPAD_READ(void)
{
	uint8_t row, check;
	for(uint8_t i = 0; i < 4; i++)
	{
		row = i + 1;
		KEYPAD_INT_PullDownRow(row);
		check = KEYPAD_INT_CheckColumn(row);
		if(check != KEYPAD_NO_PRESSED)
		{
			return check;
		}
	}
	return KEYPAD_NO_PRESSED;
}

__attribute__((weak)) void KEYPAD_Debounce_Delay(uint32_t debounceDelay)
{
	HAL_Delay(debounceDelay);
}
//


main.c文章来源地址https://www.toymoban.com/news/detail-801885.html

int main(void)
{
 
  HAL_Init();

 
  SystemClock_Config();

  
  KEYPAD_Init();
 
  while (1)
  {
    uint8_t key = KEYPAD_READ();
    if(key != KEYPAD_NO_PRESSED)
    {
        printf("key %s pressed\n", stringFromKeypadButton(key));
        while(KEYPAD_READ() != KEYPAD_NO_PRESSED);
    }
 
  }
}

到了这里,关于【STM32扫描4x4矩阵键盘模块】 4x4 matrix keypad interface的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • STM32 Proteus仿真4x4矩阵15位抢答器数码管TM1637显示-0039

    STM32 Proteus仿真4x4矩阵15位抢答器数码管TM1637显示-0039 Proteus 仿真小实验: STM32 Proteus仿真4x4矩阵15位抢答器数码管TM1637显示-0039 功能: 硬件组成:STM32F103R6单片机 +TM1637驱动4位数码管+4x4矩阵键盘+蜂鸣器 1.有一个开启键,点击后蜂鸣器短响一声,开始抢答。此后4位数码管倒计

    2024年02月08日
    浏览(42)
  • 基于FPGA的4x4矩阵键盘控制器verilog开发实现

    欢迎订阅《FPGA学习入门100例教程》、《MATLAB学习入门100例教程》 目录 一、理论基础 二、核心程序 三、测试结果        基于FPGA的4x4矩阵键盘控制器是一种使用FPGA(现场可编程门阵列)来实现对4x4矩阵键盘进行控制的设备。该控制器能够有效地降低硬件资源的使用,提高系

    2024年02月11日
    浏览(51)
  • C51单片机-按下K0至K15,显示按键标号(4x4矩阵键盘电路,1个数码管)

    keil uVision4界面: proteus仿真界面:

    2024年02月04日
    浏览(48)
  • word 如何编写4x4矩阵

    百度上给的教程,打印出来没有对齐 https://jingyan.baidu.com/article/6b182309995f8dba58e159fc.html 百度上的方式试了一下,不会对齐。导致公式看起来很奇怪。 下面方式会自动对齐 摸索了一下发现可以用下面这种方式编写 4x4 矩阵。先创建一个 3x3矩阵,然后选择其中一个矩阵,右键插入

    2024年02月04日
    浏览(51)
  • 矩阵乘法优化:4x4矩阵块优化方法

    MMult_4x4_3.h 一次计算C中的4x4小块 0.24gflops 2.1% 1 MMult_4x4_4.h 一次计算C中的4x4小块 0.24gflops 2.1% 1 MMult_4x4_5.h 一次计算C中的4x4小块,将16个循环合并一个 0.25gflops 2.2% 1 MMult_4x4_6.h 一次计算C中的4x4小块(我们在寄存器中累加C的元素,并对a的元素使用寄存器) 1.75gflops 16.0% 1 MMult_4x4_7.h 在

    2024年02月15日
    浏览(50)
  • STC15WProteus仿真HX711电子秤串口计价称重4x4键盘STC15W4K32S4

    STC15WProteus仿真HX711电子秤串口计价称重4x4键盘STC15W4K32S4 Proteus 仿真小实验: STC15WProteus仿真HX711电子秤串口计价称重4x4键盘STC15W4K32S4 功能: 硬件组成:STC15W4K32S4单片机 +LCD12864显示器+4x4矩阵键盘+HX711电子秤 1.单片机通过HX711读取称重传感器数据计算出重量,重量乘于单价可以

    2024年02月12日
    浏览(46)
  • UG\NX二次开发 获取部件的4x4矩阵

    文章作者:里海 来源网站: https://blog.csdn.net/WangPaiFeiXingYuan 输入部件occ,获取矩阵。用函数UF_ASSEM_ask_transform_of_occ(),比较直接。 输入部件的实例或事例,获取矩阵。用函数UF_ASSEM_ask_component_data()。 通过部件事例获取实例的方法

    2024年02月14日
    浏览(50)
  • UG\NX二次开发 获取部件的4x4矩阵的方法

    文章作者:里海 来源网站: https://blog.csdn.net/WangPaiFeiXingYuan 方法1: 输入部件occ,获取矩阵。用函数UF_ASSEM_ask_transform_of_occ(),比较直接。 方法2: 输入部件的实例或事例,获取矩阵。用函数UF_ASSEM_ask_component_data()。 通过部件事例获取实例的方法 相关函数:    

    2024年02月12日
    浏览(54)
  • Unity矩阵平移旋转缩放Matrix4x4

    最近在研究帧同步定点数物理系统中需要自定义定点数矩阵,所以在这里分享下基础的矩阵案例旋转、平移、缩放。(注意这里本文中的transform组件式基于unity浮点数的教程并非帧同步定点数)参考原文 参数可以参考我上图的参数,这里注意三个顶点是一个面,这里我上述的

    2024年01月17日
    浏览(42)
  • 多轴机械臂运动控制:4x4坐标变换矩阵该用C语言的二维数组还是一维数组?

            做多轴机械臂的运动控制,免不了要对4x4的坐标变换矩阵进行乘法,C语言中可以用二维数组或者一维数组来实现矩阵,下面来比较一下二维数组和一维数组的性能差异。         开发环境:Visual Studio 2022,分别在Debug和Release模式下测试函数Multi4x4和Multi16,Re

    2024年03月25日
    浏览(61)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包