我自己写了一段51单片机的代码分享给大家,有完整的注释,和解码过程图解,这个矩阵键盘扫描程序不同于网上那些逐行扫描; 思路新颖,语句简单,识别准确;
扫描子函数中包含变量定义,所有代码就10行;真正做解码的只用了6条语句
这段演示程序中没有任何延时阻塞函数;识别率挺高; 做项目最好加入中断定时扫描;如果单片机资源紧张,也可以在1-3 或者4-7;4条IO口上对地加4个104电容做硬件消抖;
程序在下面,里面还有一个LCD1602的显示函数, 用来演示按键扫描结果!
单片机源程序如下:
- #include <REGX51.H>
- #include "LCD1602.H"
- /*** 0-15键值 ***/
- /*****************
- 0x77,0x7B,0x7D,0x7E
- 0xB7,0xBB,0xBD,0xBE
- 0xD7,0xDB,0xDD,0xDE
- 0xE7,0xEB,0xED,0xEE
- ******************/
- unsigned char Key_Scan(); //按键扫描函数声明
- /* 主函数从这里开始 */
- void main(void)
- {
- static unsigned char Key_Code = 0x00; //定义一个静态变量
-
- LCD_Init(); //初始化LCD1602,用来显示键值
- while(1)
- {
- Key_Code = Key_Scan();
- switch (Key_Code) //演示示例;用switch语句操作键码;比如我在1602液晶屏上显示数字1-16;也可以用数组来操作,自由发挥!
- {
- case 0x77: LCD_ShowNum(1,2,1,2); break;
- case 0x7B: LCD_ShowNum(1,2,2,2); break;
- case 0x7D: LCD_ShowNum(1,2,3,2); break;
- case 0x7E: LCD_ShowNum(1,2,4,2); break;
- case 0xB7: LCD_ShowNum(1,2,5,2); break;
- case 0xBB: LCD_ShowNum(1,2,6,2); break;
- case 0xBD: LCD_ShowNum(1,2,7,2); break;
- case 0xBE: LCD_ShowNum(1,2,8,2); break;
- case 0xD7: LCD_ShowNum(1,2,9,2); break;
- case 0xDB: LCD_ShowNum(1,2,10,2); break;
- case 0xDD: LCD_ShowNum(1,2,11,2); break;
- case 0xDE: LCD_ShowNum(1,2,12,2); break;
- case 0xE7: LCD_ShowNum(1,2,13,2); break;
- case 0xEB: LCD_ShowNum(1,2,14,2); break;
- case 0xED: LCD_ShowNum(1,2,15,2); break;
- case 0xEE: LCD_ShowNum(1,2,16,2); break;
- default: break;
- }
- }
- }
- /* 带返回值的按键扫描函数*/
- unsigned char Key_Scan()
- {
- unsigned char Key_Temp; //定义一个存放组合键码的变量
- unsigned char Key_A,Key_B; // 定义两个变量,Key_A 用于存放正向扫描的键码; Key_B 用于存放反向扫描的键码。
-
- P1 = 0xF0; //把P1口的高4位(P1.4-P1.7)置高,低4位置低;(如果有按键按下 高4位肯定有一条线会被拉低)。
- Key_Temp = P1; //把P1口的状态读回来,传递给Key_Temp。没有按键按下Key_Temp肯定是0XF0; 否则就是其它的数;
- if(Key_Temp!= 0xF0) // 进入if判断语句;如果Key_Temp不等于0XF0,说明有键按下了。
- {
- Key_A = P1; // 把P1口此时被按下的状态传递给Key_A保存
- P1 = 0x0F; //开始反转扫描;把P1口的高4位置低,低4位(P1.0-P1.3)置高;(如果有按键按下 低4位肯定有一条线会被拉低)。
- Key_B = P1; //把P1口此时被按下的状态传递给Key_A保存
- }
- Key_Temp = (Key_A | Key_B); //把正反两次扫描的结果相或, 就会得到按键按下的正确键码
- return Key_Temp; //把键码返回,给其他的函数调用
- }
- //下面是图解正反转扫描的程序工作原理
- /*
- 正向扫描,比如P1.7和P1.3连接的按键被按下 那么P1口的0XF0:1111 0000 就会变成0X70:0111 0000
- P1.3 P1.2 P1.1 P1.0
- 0 0 0 0
- P1.7 1 -+- --- --- ---
- P1.6 1 --- --- --- ---
- P1.5 1 --- --- --- ---
- P1.4 1 --- --- --- ---
- 反向扫描,比如P1.7和P1.3连接的按键被按下 那么P1口的0X0F:0000 1111 就会变成0X07:0000 0111
- P1.3 P1.2 P1.1 P1.0
- 1 1 1 1
- P1.7 0 -+- --- --- ---
- P1.6 0 --- --- --- ---
- P1.5 0 --- --- --- ---
- P1.4 0 --- --- --- ---
- 最后把 正反两次扫描的结果 0X70 与0X07相或 就会得到0X77的键码
- 只要得到正确的键码,就可以用这个键码做任何事情。比如我在液晶屏上显示数字1;表示数字1键被按下。
- */
- //下面这组键值根据不同的接线方式,会有不同的键值,需要提前自己算好;就类似数码管的段码一样;也可以做成一个数组。
- /*** 0-15键值 ***/
- /*****************
- 0x77,0x7B,0x7D,0x7E
- 0xB7,0xBB,0xBD,0xBE
- 0xD7,0xDB,0xDD,0xDE
- 0xE7,0xEB,0xED,0xEE
- ******************/
复制代码 Keil代码下载:
6条语句搞定4X4矩阵按键.rar
(35.42 KB, 下载次数: 45)
|