【STM32嵌入式系统设计与开发---拓展】——1_10矩阵按键

这里写目录标题

1、矩阵按键


通过将4x4矩阵按键的每一行依次设为低电平,同时保持其它行为高电平,然后读取所有列的电平状态,可以检测到哪个按键被按下。如果某列变为低电平,说明对应行和列的按键被按下。这样逐行扫描即可确定按键的位置。


2、代码片段分析

c 复制代码
/*********************************************************************
 @Function  : 矩阵键盘行列读写操作
 @Parameter : ReadIo  :读输入的IO
							WirteIo :写输出的IO
 @Return    : 行列IO输出状态
**********************************************************************/
uint8_t GPIO_KEY_RW(uint16_t ReadIo,uint16_t WirteIo)
{
  uint16_t Wdata=0,Rdata=0;	
	/* 写操作 */
	KeyBordSetOut(KEY_ALL);               //设置IO
	if(WirteIo==0x0f00)
	   GPIO_SetBits(GPIOE,KEY_LINE);      //写行
	else 
     GPIO_ResetBits(GPIOE,KEY_LIST);    //写列		
     Wdata = GPIO_ReadOutputData(GPIOE);//读输出	
     Wdata &= WirteIo;                  //取有效区域
	
	/* 读操作 */
     KeyBordSetIn(ReadIo);              //设置IO 
     Rdata = GPIO_ReadInputData(GPIOE); //读输入
     Rdata &= ReadIo;                   //取有效区域
	
	/* 状态返回	*/
	   Rdata |= Wdata;                    //合并两次读取的数据
     return (uint8_t)(Rdata>>8);        //移位返回
}

初始化:

Wdata 和 Rdata 初始化为 0。

写操作:

检查 WirteIo 是否为 0x0f00(二进制:0000111100000000):

如果是,则设置 GPIOE 中对应 KEY_LINE 的位(具体位取决于 KEY_LINE 的定义)。

如果不是,则复位 GPIOE 中对应 KEY_LIST 的位(具体位取决于 KEY_LIST 的定义)。

读取 GPIOE 的输出数据到 Wdata。

Wdata 与 WirteIo 进行与操作,保留有效区域的数据。

读操作:

使用 ReadIo 设置IO方向。

读取 GPIOE 的输入数据到 Rdata。

Rdata 与 ReadIo 进行与操作,保留有效区域的数据。

状态返回:

将 Wdata 和 Rdata 进行或操作,合并两次读取的数据。

返回 Rdata 右移8位后的值。

假设按下第一个按键

假设按下的是第一个按键,具体的步骤如下:

初始化:

Wdata = 0

Rdata = 0

写操作:

WirteIo == 0x0f00 假设为真,则设置 GPIOE 对应 KEY_LINE 的位。

读取 GPIOE 输出数据:

假设 GPIOE 输出数据为 0000111100000000(二进制)。

Wdata &= WirteIo:

Wdata = 0000111100000000 & 0000111100000000 = 0000111100000000

读操作:

设置IO方向,具体操作取决于 KeyBordSetIn 函数。

读取 GPIOE 输入数据:

假设按下第一个按键时,GPIOE 输入数据为 0000000100000000(二进制)。

Rdata &= ReadIo:

Rdata = 0000000100000000 & ReadIo(假设 ReadIo 为 0000000100000000),结果 Rdata = 0000000100000000

状态返回:

Rdata |= Wdata:

Rdata = 0000000100000000 | 0000111100000000 = 0000111100000000

返回值:

将 Rdata 右移8位后返回:Rdata >> 8 = 00001111

所以函数返回值为 0x0F(二进制:00001111)


c 复制代码
/*********************************************************************
 @Function  : 矩阵键盘键值扫描
 @Parameter : N/A
 @Return    : 键值
**********************************************************************/
uint8_t KeyBoardScan(void)
{
	uint8_t KeyValue=0,Key=0;
	uint8_t a = 0;
	/* 检测键盘是否有按键按下,0x0f表示所有列都未按下 */
	if(GPIO_KEY_RW(KEY_LIST,KEY_LINE)!=0x0f)
	{
			/* 测试列状态 */
		  Key = GPIO_KEY_RW(KEY_LIST,KEY_LINE); // 读取列的状态

			/* 判断列状态并映射为按键值 */
			switch(Key)
			{
				case(0x1F):    // 第一列所有行都按下
						KeyValue = 1; // 对应键值为1
						break;
				case(0x2F):    // 第二列所有行都按下
						KeyValue = 2; // 对应键值为2
						break;
				case(0x4F):    // 第三列所有行都按下
						KeyValue = 3; // 对应键值为3
						break;
				case(0x8F):    // 第四列所有行都按下
						KeyValue = 4; // 对应键值为4
						break;
			}
			
			/* 测试行状态 */
			Key = GPIO_KEY_RW(KEY_LINE,KEY_LIST); // 读取行的状态
		
			/* 判断行状态并映射为按键值 */
			switch(Key)
			{
				case(0x0E):    // 第一行所有列都按下
						KeyValue = KeyValue; // 保持当前列的键值不变
						break;
				case(0x0D):    // 第二行所有列都按下
						KeyValue = KeyValue + 4; // 当前列的键值加4,对应第二行
						break;
				case(0x0B):    // 第三行所有列都按下
						KeyValue = KeyValue + 8; // 当前列的键值加8,对应第三行
						break;
				case(0x07):    // 第四行所有列都按下
						KeyValue = KeyValue + 12; // 当前列的键值加12,对应第四行
						break;
			}

			
			/* 按键松手检测 */
		  while((a < 50) && (Key != 0x00)) // 循环检测按键是否松手,最多检测50次
			{
					delay_ms(5);                          // 延时5毫秒
					Key = GPIO_KEY_RW(KEY_LINE,KEY_LIST); // 再次读取行的状态
					a += 1;                               // 计数器加1
			}
	}
	
	/* 返回键值 */
	return KeyValue;
}
相关推荐
三佛科技-1341638421233 分钟前
FT32F103系列与APM32F103,STM32F103之间的对比,能否替换?
单片机·嵌入式硬件·物联网·智能家居·pcb工艺
李永奉1 小时前
杰理可视化SDK开发-蓝牙的可发现可连接和回连
单片机·嵌入式硬件·物联网·语音识别
【ql君】qlexcel3 小时前
Visual Studio Code开发STM32设置头文件宏定义uint32_t报错
vscode·stm32·vs code·头文件宏定义·uint32_t报错·uint8_t报错·uint16_t报错
振浩微433射频芯片3 小时前
标签界的“千里眼”:VRT5312,150cm超远读写距离,重新定义RFID新可能!
科技·单片机·嵌入式硬件·物联网
andylauren3 小时前
论单点接地的重要性——从MP3模块噪声问题看接地设计的关键
嵌入式硬件
修勾勾L4 小时前
使用VSCode开发嵌入式开发详细教程——步骤二项目实战
嵌入式硬件
染予4 小时前
定时器时钟源介绍
单片机·嵌入式硬件
时空自由民.4 小时前
ESP32编译固件内存信息解读
单片机·性能优化
LCMICRO-133108477465 小时前
长芯微LPS6288完全P2P替代TPS61288,是一款具有 15A 开关电流的全集成同步升压转换器
stm32·单片机·嵌入式硬件·fpga开发·硬件工程·同步升压转换器
FreakStudio5 小时前
MicroPython对接大模型:uopenai + 火山方舟实现文字聊天和图片理解
python·单片机·ai·嵌入式·面向对象·电子diy