当前位置:首页 > 每日看点

如何按下一个矩阵键盘,松开后直到按下另个键盘之前,显示不消失?

卡卷网2年前 (2024-11-30)每日看点297

矩阵键盘本质:

矩阵键盘本质是使用8个IO口来进行16个按键的控制读取,可以减小IO口的使用,用4条I/O线作为行线,4条I/O线作为列线组成的键盘。在行线和列线的每个交叉点上,设置一个按键。而这样的按键中按键的个数是4 X 4个。

这样的行列式键盘结构能够有效地提高单片机系统中I/O口的利用率。节约单片机的资源,其本质和独立按键类似,就是进行逐行扫描和逐列扫描,然后判断是第几行的第几列的按键,进而进行整体按键值得确定。

具体实物图如下:

如何按下一个矩阵键盘,松开后直到按下另个键盘之前,显示不消失?  第1张

矩阵键盘扫描的方式有两种: 1.行列扫描,2.逐行/逐列扫描

行列扫描:适用于8个IO口接到了单片机8个连续的IO口,可以使用行列扫描

逐行/逐列扫描:适用于矩阵键盘接到了任意的IO口,则使用逐行,逐列扫描

本文主要说明逐行扫描的方式

逐行/列扫描:

逐行,逐列扫描的本质和行列扫描比较类似,本质是给某一行/某一列,低电平,其余七个全部为高电平,这时候读取电平变换,有电平变低表示按键按下,即可读取按键数据。

逐行扫描:

  1. 置第1行为低电平,其余N-1行和N列为高电平,
  2. 读取列线数据,列线有低电平表示此行有按键按下,比如按下的是1行三列(1x3),那么第三列的列线IO口就为低电平。
  3. 置第2行为低电平,其余N-1行和N列为高电平,,读取列线数据,列线有低电平表示此行有按键按下。
  4. 以此类推,进行逐行扫描。
  5. 根据行线列线的电平不同可以识别是否有按键按下,哪一个按键按下,获取按键号。(N) 根据按键号跳转至对应的按键处理程序。

如何按下一个矩阵键盘,松开后直到按下另个键盘之前,显示不消失?  第2张

硬件连接

行线与列线:在硬件上,4条行线连接到微控制器的输出引脚,而4条列线连接到微控制器的输入引脚。

按键位置:每个按键位于行线和列线的交叉点上。

如何按下一个矩阵键盘,松开后直到按下另个键盘之前,显示不消失?  第3张

GPIO初始化

行线:

通常设置为输出模式,用于向列线发送扫描信号。

扫描信号:

行线的主要功能是向列线发送扫描信号。当某一行线被设置为低电平时,与之相交的列线会被检测(若相对应的按键被按下,列线被检测为低电平)以判断是否有按键被按下。

确定按键行

通过依次将每一行线设置为低电平(可以逐行扫描键盘)。当检测到列线上有低电平时,可以确定被按下的按键位于当前选中的行上。若列线上无低电平,那么将此行线设置为高电平,下一行设置为低电平,进行新一轮按键检测。

列线

设置为输入模式,用于读取按键状态。

读取按键状态

列线的主要功能是读取按键状态。(STM32就靠列线来确认按键状态)当某一行线被选中(设置为低电平)时,微控制器会读取所有列线的电平状态,以判断是否有按键被按下。

注意事项

在实际应用中,还需要考虑去抖处理、中断处理等因素,以确保按键检测的准确性和稳定性。

Cube MX配置GPIO

使用stm32CubeMX软件配置GPIO:

PA0-PA3的配置是一样的(做行线,设置为输出模式)

如何按下一个矩阵键盘,松开后直到按下另个键盘之前,显示不消失?  第4张

PA4-PA7的配置是一样的(做列线,设置为输入模式)

如何按下一个矩阵键盘,松开后直到按下另个键盘之前,显示不消失?  第5张

有用到OLED模块,故配置SCL,SDA,做通讯线

如何按下一个矩阵键盘,松开后直到按下另个键盘之前,显示不消失?  第6张

时钟频率的话,可以选择默认的

如何按下一个矩阵键盘,松开后直到按下另个键盘之前,显示不消失?  第7张

如何按下一个矩阵键盘,松开后直到按下另个键盘之前,显示不消失?  第8张

配置完GPIO的相关资源后,就可以在Keil5软件里编写功能模块

(代码中用到的Delay模块和OLED模块是外部导入的)

(Delay也可以用HAL库自带的,OLED可以网上找找)

#include <main.h> #include "Delay.h" /** * @brief 矩阵键盘读取按键键码 * @param 无 * @retval KeyNumber 按下按键的键码值 如果按键按下不放,程序会停留在此函数,松手的一瞬间,返回按键键码,没有按键按下时,返回0 */ void GPIOAallset() { HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_4, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_5, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_6, GPIO_PIN_SET); HAL_GPIO_WritePin(GPIOA, GPIO_PIN_7, GPIO_PIN_SET); } uint8_t MatrixKey(void) { uint8_t KeyNumber=0; GPIOAallset(); //把PA0-PA7全置为高电平 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_0, GPIO_PIN_RESET); //PA0置0,开始检测第一行 if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4)==0) { Delay_ms(10); while(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4)); //当按钮处于被按下的状态的时候,程序一直卡在循环读取按钮的状态,避免多按钮同时按下时读取错误 Delay_ms(10); KeyNumber=1; } if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5)==0) { Delay_ms(10); while(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5)); Delay_ms(10); KeyNumber=2; } if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6)==0) { Delay_ms(10); while(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6)); Delay_ms(10); KeyNumber=3; } if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7)==0) { Delay_ms(10); while(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7)); Delay_ms(10); KeyNumber=4; } GPIOAallset(); //把PA0-PA7全置为高电平 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET); //PA1置0,开始检测第二行 if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4)==0) { Delay_ms(10); while(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4)); //当按钮处于被按下的状态的时候,程序一直卡在循环读取按钮的状态,避免多按钮同时按下时读取错误 Delay_ms(10); KeyNumber=5; } if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5)==0) { Delay_ms(10); while(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5)); Delay_ms(10); KeyNumber=6; } if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6)==0) { Delay_ms(10); while(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6)); Delay_ms(10); KeyNumber=7; } if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7)==0) { Delay_ms(10); while(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7)); Delay_ms(10); KeyNumber=8; } GPIOAallset(); //把PA0-PA7全置为高电平 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_2, GPIO_PIN_RESET); //PA2置0,开始检测第三行 if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4)==0) { Delay_ms(10); while(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4)); //当按钮处于被按下的状态的时候,程序一直卡在循环读取按钮的状态,避免多按钮同时按下时读取错误 Delay_ms(10); KeyNumber=9; } if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5)==0) { Delay_ms(10); while(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5)); Delay_ms(10); KeyNumber=10; } if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6)==0) { Delay_ms(10); while(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6)); Delay_ms(10); KeyNumber=11; } if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7)==0) { Delay_ms(10); while(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7)); Delay_ms(10); KeyNumber=12; } GPIOAallset(); //把PA0-PA7全置为高电平 HAL_GPIO_WritePin(GPIOA, GPIO_PIN_3, GPIO_PIN_RESET); //PA3置0,开始检测第四行 if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4)==0) { Delay_ms(10); while(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_4)); //当按钮处于被按下的状态的时候,程序一直卡在循环读取按钮的状态,避免多按钮同时按下时读取错误 Delay_ms(10); KeyNumber=13; } if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5)==0) { Delay_ms(10); while(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_5)); Delay_ms(10); KeyNumber=14; } if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6)==0) { Delay_ms(10); while(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_6)); Delay_ms(10); KeyNumber=15; } if(HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7)==0) { Delay_ms(10); while(!HAL_GPIO_ReadPin(GPIOA, GPIO_PIN_7)); Delay_ms(10); KeyNumber=16; } return KeyNumber; }

主函数部分:

while (1) { OLED_ShowString(2, 1,"NUM:"); num = MatrixKey(); if(num) { OLED_ShowNum(2, 5, num, 2); } }

仿真图片:

如何按下一个矩阵键盘,松开后直到按下另个键盘之前,显示不消失?  第9张

扫描二维码推送至手机访问。

版权声明:本文由卡卷网发布,如需转载请注明出处。

本文链接:https://www.kajuan.net/ttnews/2024/11/2236.html

分享给朋友:

相关文章

左手短视频,右手啄木鸟,小红书要抛弃KOC了吗?

左手短视频,右手啄木鸟,小红书要抛弃KOC了吗?

左手短视频,右手啄木鸟,小红书要抛弃KOC了吗?上周六,微博上掀起了声势浩大的声讨小红书的活动,起因是众多博主发现自己的合规笔记被小红书判定违规,且申诉失败。博主们激烈的言辞之间,纷纷将矛头指向了小红书于一个月前推出的「啄木鸟计划」。当晚,…

创业容易吗?

创业容易吗?创建企业不一定是困难或令人生畏的。它可以从一个简单但有力的想法开始,比如小强意识到,如果洗手液能杀死真菌,尤其是拳击台上的真菌,就会更加有用。创业确实需要奉献精神、努力工作和仔细规划——这是没有办法的。虽然这本身可能并不容易,但…

手机买16+256的还是12+512的好?

手机买16+256的还是12+512的好?

到底选大内存还是大存储,一直以来是很多朋友的纠结点,大内存意味着可以应用多开不卡顿,大存储则是可以存入更多文件、应用,如果两个配置价格差距不大(如0-200元),确实有点难选。 不过从实际体验出发,大存储的手机显然更应该优先选择才是。首先,…

为什么扫码支付在中国流行,在发达国家被排斥?

因为这是一种落后的技术。 卖菜的大爷花5毛钱就可以打印出一张二维码来接受付款。 你觉着这种先进么?跟先进完全不沾边的。正是因为不先进,所以才能流行。 卖菜大爷用不起一台先进的、具有NFC感应功能的、还能刷各种银行卡的收款机。 这就是现实。…

拼多多,怎么就成为了年轻人的「赛博菜市场」?

拼多多,怎么就成为了年轻人的「赛博菜市场」?

可惜你不在拼多多买水果蔬菜,很难一句话跟你解释,我只能笨拙的用经历来慢慢讲。 我们公司有微波炉,同事们几乎都是自己带饭来上班,便当荤素搭配、水果零食;都是好看又好吃。 我自己本来就不喜欢外卖,当然也加入了带饭大军: 直到某一天深夜我闲着…

有哪些让你目瞪口呆的 Bug ?

有哪些让你目瞪口呆的 Bug ?

成都有个监狱情况比较特殊,关押的基本全是重犯,而且还都是经济犯和政治犯, 他们以前都是一方大佬,在自己的一亩三分地翻手为云覆手为雨,无非是不小心中箭落马或帮老大顶锅才进监狱, 所以即使进来了,他们依然保持着体面和骄傲,依从性差,虽然不至于和…

发表评论

访客

看不清,换一张

◎欢迎参与讨论,请在这里发表您的看法和观点。