【51单片机】用定时器扫描矩阵键盘

简介: 【51单片机】用定时器扫描矩阵键盘

用Delay消抖会阻碍程序进程

改用定时器扫描会好很多~

上一篇文章已经发过用延时函数写的矩阵按键了,稍加修改即可。

本次矩阵键盘要写三个函数,建议封装一下哈,这里我命名的是MatrixKeyT

在main.c里声明一下  #include "MatrixKeyT.h"

第一个函数是读取按键键码,仍然采用逐列扫描,把之前的延时都去掉

这里if判断 多了后面的条件,两个条件同时满足,相当于找到对应按键的坐标,这样按键更加稳定,不会出现按键失灵的情况,咱也可以去掉试试,反正电脑又不会爆炸~

1. /**
2. *@brief   名称:矩阵键盘读取按键键码, 内部函数
3.   *@param   参数:无
4.   *@retval返回值:KeyNumber 0代表无按键按下,1~16代表键码
5.   */
6. unsigned char MatrixKey_GetState()
7. {
8.  unsigned char KeyNumber=0;
9. 
10.   P1=0xFF;
11.    P1_3=0;
12.   if(P1_7==0 && P1_3==0){KeyNumber=1;}
13.   if(P1_6==0 && P1_3==0){KeyNumber=5;}
14.   if(P1_5==0 && P1_3==0){KeyNumber=9;}
15.   if(P1_4==0 && P1_3==0){KeyNumber=13;}
16. 
17.   P1=0xFF;
18.   P1_2=0;
19.   if(P1_7==0 && P1_2==0){KeyNumber=2;}
20.   if(P1_6==0 && P1_2==0){KeyNumber=6;}
21.   if(P1_5==0 && P1_2==0){KeyNumber=10;}
22.   if(P1_4==0 && P1_2==0){KeyNumber=14;}
23. 
24.   P1=0xFF;
25.   P1_1=0;
26.   if(P1_7==0 && P1_1==0){KeyNumber=3;}
27.   if(P1_6==0 && P1_1==0){KeyNumber=7;}
28.   if(P1_5==0 && P1_1==0){KeyNumber=11;}
29.   if(P1_4==0 && P1_1==0){KeyNumber=15;}
30. 
31.   P1=0xFF;
32.   P1_0=0;
33.   if(P1_7==0 && P1_0==0){KeyNumber=4;}
34.   if(P1_6==0 && P1_0==0){KeyNumber=8;}
35.   if(P1_5==0 && P1_0==0){KeyNumber=12;}
36.   if(P1_4==0 && P1_0==0){KeyNumber=16;}
37. 
38.   return KeyNumber;
39. }

第二个函数是放在定时器里10ms循环一次的

定义两个静态局部变量,用来存储10ms前后按键键码数值,每10ms这两个变量更新一次,这样代替Delay消抖

在这个MatrixKeyT.c里定义一个全局变量,用来接受显示按键键码数值。

unsigned char Key_KeyNumber;

1. void MatrixKey_Loop(void)
2. {
3.  static unsigned char NowState,LastState;
4.  LastState = NowState;       //按键状态更新
5.  NowState  = MatrixKey_GetState();   //获取当前按键状态
6.  if(LastState == 1 && NowState == 0) {Key_KeyNumber=1;} 
7.  if(LastState == 2 && NowState == 0) {Key_KeyNumber=2;}
8.  if(LastState == 3 && NowState == 0) {Key_KeyNumber=3;}
9.  if(LastState == 4 && NowState == 0) {Key_KeyNumber=4;}
10.   if(LastState == 5 && NowState == 0) {Key_KeyNumber=5;}
11.   if(LastState == 6 && NowState == 0) {Key_KeyNumber=6;}
12.   if(LastState == 7 && NowState == 0) {Key_KeyNumber=7;}
13.   if(LastState == 8 && NowState == 0) {Key_KeyNumber=8;}
14.   if(LastState == 9 && NowState == 0) {Key_KeyNumber=9;}
15.   if(LastState ==10 && NowState == 0) {Key_KeyNumber=10;}
16.   if(LastState ==11 && NowState == 0) {Key_KeyNumber=11;}
17.   if(LastState ==12 && NowState == 0) {Key_KeyNumber=12;}
18.   if(LastState ==13 && NowState == 0) {Key_KeyNumber=13;}
19.   if(LastState ==14 && NowState == 0) {Key_KeyNumber=14;}
20.   if(LastState ==15 && NowState == 0) {Key_KeyNumber=15;}
21.   if(LastState ==16 && NowState == 0) {Key_KeyNumber=16;}//如果10ms前按下按键16,并且现在已经松手,那就认为按键16按下
22. }

这样写的循环按键没有短按长按的功能, 若想加长按短按,可以定义多个计数变量 ,判断条件改成  LastState == 1 && NowState == 1 ,10ms前后都是按键1按下,计数变量++,也就是按下按键  10ms计数变量就会自加1,然后判断阈值,计数变量在10-100以内(100ms-1s)认为是短按,给一个键码数;大于100(大于1s)0认为是长按,给另外一个键码数。

这里没搞明白可以看一下之前写的《独立按键-短按与长按》

最后一个函数把按键键码返回出去

定义一个暂存数据的变量Temp,把按键数值赋值给Temp,把Key_KeyNumber清零(代表未按下),返回值为Temp

1. /**
2.   *@brief   名称:矩阵键盘扫描,获取按键键码
3.   *@param   参数:无  (放在主函数while里 赋值给一个 代表键码的变量)
4.   *@retval返回值:KeyNumber 0代表无按键按下,1~16代表键码
5.   */
6. unsigned char Key(void)
7. {
8.  unsigned char Temp = 0;
9.  Temp = Key_KeyNumber; //赋值给暂存变量
10.   Key_KeyNumber = 0;    //清零
11.   return Temp;      //返回暂存变量
12. }

我把这个MatrixKeyT.c一起放在下边了哈,有需要的直接复制

1. #include <REGX52.H>
2. #include "MatrixKeyT.h"
3. 
4. unsigned char Key_KeyNumber;
5. 
6. 
7. /**
8.   *@brief   名称:矩阵键盘扫描,获取按键键码
9.   *@param   参数:无  (放在主函数while里 赋值给一个 代表键码的变量)
10.   *@retval返回值:KeyNumber 0代表无按键按下,1~16代表键码
11.   */
12. unsigned char Key(void)
13. {
14.   unsigned char Temp = 0;
15.   Temp = Key_KeyNumber; //赋值给暂存变量
16.   Key_KeyNumber = 0;    //清零
17.   return Temp;      //返回暂存变量
18. }
19. 
20. 
21. /**
22. *@brief   名称:矩阵键盘读取按键键码, 内部函数(不需要外部调用的)
23.   *@param   参数:无
24.   *@retval返回值:KeyNumber 0代表无按键按下,1~16代表键码
25.   */
26. unsigned char MatrixKey_GetState()
27. {
28.   unsigned char KeyNumber=0;
29. 
30.   P1=0xFF;
31.    P1_3=0;
32.   if(P1_7==0 && P1_3==0){KeyNumber=1;}
33.   if(P1_6==0 && P1_3==0){KeyNumber=5;}
34.   if(P1_5==0 && P1_3==0){KeyNumber=9;}
35.   if(P1_4==0 && P1_3==0){KeyNumber=13;}
36. 
37.   P1=0xFF;
38.   P1_2=0;
39.   if(P1_7==0 && P1_2==0){KeyNumber=2;}
40.   if(P1_6==0 && P1_2==0){KeyNumber=6;}
41.   if(P1_5==0 && P1_2==0){KeyNumber=10;}
42.   if(P1_4==0 && P1_2==0){KeyNumber=14;}
43. 
44.   P1=0xFF;
45.   P1_1=0;
46.   if(P1_7==0 && P1_1==0){KeyNumber=3;}
47.   if(P1_6==0 && P1_1==0){KeyNumber=7;}
48.   if(P1_5==0 && P1_1==0){KeyNumber=11;}
49.   if(P1_4==0 && P1_1==0){KeyNumber=15;}
50. 
51.   P1=0xFF;
52.   P1_0=0;
53.   if(P1_7==0 && P1_0==0){KeyNumber=4;}
54.   if(P1_6==0 && P1_0==0){KeyNumber=8;}
55.   if(P1_5==0 && P1_0==0){KeyNumber=12;}
56.   if(P1_4==0 && P1_0==0){KeyNumber=16;}
57. 
58.   return KeyNumber;
59. }
60. 
61. 
62. void MatrixKey_Loop(void)
63. {
64.   static unsigned char NowState,LastState;
65.   LastState = NowState;       //按键状态更新
66.   NowState  = MatrixKey_GetState();   //获取当前按键状态
67.   if(LastState == 1 && NowState == 0) {Key_KeyNumber=1;}
68.   if(LastState == 2 && NowState == 0) {Key_KeyNumber=2;}
69.   if(LastState == 3 && NowState == 0) {Key_KeyNumber=3;}
70.   if(LastState == 4 && NowState == 0) {Key_KeyNumber=4;}
71.   if(LastState == 5 && NowState == 0) {Key_KeyNumber=5;}
72.   if(LastState == 6 && NowState == 0) {Key_KeyNumber=6;}
73.   if(LastState == 7 && NowState == 0) {Key_KeyNumber=7;}
74.   if(LastState == 8 && NowState == 0) {Key_KeyNumber=8;}
75.   if(LastState == 9 && NowState == 0) {Key_KeyNumber=9;}
76.   if(LastState ==10 && NowState == 0) {Key_KeyNumber=10;}
77.   if(LastState ==11 && NowState == 0) {Key_KeyNumber=11;}
78.   if(LastState ==12 && NowState == 0) {Key_KeyNumber=12;}
79.   if(LastState ==13 && NowState == 0) {Key_KeyNumber=13;}
80.   if(LastState ==14 && NowState == 0) {Key_KeyNumber=14;}
81.   if(LastState ==15 && NowState == 0) {Key_KeyNumber=15;}
82.   if(LastState ==16 && NowState == 0) {Key_KeyNumber=16;}
83. }

再写定时器0初始化函数定时器0的中断函数

1. //定时器0初始化模板   //1毫秒@11.0592MHz
2. void Timer0_Init(void)   //1毫秒@11.0592MHz
3. {
4.  TMOD &= 0xF0;   //设置定时器模式
5.  TMOD |= 0x01;   //设置定时器模式
6.  TL0 = 0x66;   //设置定时初值
7.  TH0 = 0xFC;   //设置定时初值
8.  TF0 = 0;    //清除TF0标志
9.  TR0 = 1;    //定时器0开始计时
10.   ET0=1;
11.   EA=1;
12.   PT0=0;  
13. }

main.c也复制一下吧

1. #include <REGX52.H>
2. #include "MatrixKeyT.h"
3. 
4. unsigned char KeyNum;
5. 
6. 
7. //定时器0初始化模板   //1毫秒@11.0592MHz
8. void Timer0_Init(void)   //1毫秒@11.0592MHz
9. {
10.   TMOD &= 0xF0;   //设置定时器模式
11.   TMOD |= 0x01;   //设置定时器模式
12.   TL0 = 0x66;   //设置定时初值
13.   TH0 = 0xFC;   //设置定时初值
14.   TF0 = 0;    //清除TF0标志
15.   TR0 = 1;    //定时器0开始计时
16.   ET0=1;
17.   EA=1;           //总中断开启
18.   PT0=0;  
19. }
20. 
21. 
22. void main()
23. {
24.   Timer0_Init();
25. 
26.   while(1)
27.   {
28. 
29.     KeyNum = Key();    //按键返回接口
30. 
31.     if(KeyNum == 2)    //如果按键2按下
32.       P2_0=~P2_0;    //第一个灯取反
33.     if(KeyNum == 7)    //如果按键7按下
34.       P2_2=~P2_2;    //第三个灯取反
35. 
36. 
37. 
38.   }
39. 
40. }
41. 
42. 
43. void Timer0_Routine() interrupt 1  //定时器0的中断函数
44. {
45.   static unsigned intT0Count;
46. 
47.   TL0 = 0x66;   //设置定时初值//1毫秒@11.0592MHz
48.   TH0 = 0xFC;   //设置定时初值
49.   T0Count++;
50. 
51.   if(T0Count>=10) //10ms
52.   {
53.     MatrixKey_Loop();
54.     //清零重记次
55.     T0Count=0;
56. 
57.   }
58. }


相关文章
|
2月前
【51单片机】通过定时器中断 在8位数码管显示时间
【51单片机】通过定时器中断 在8位数码管显示时间
|
2月前
【51单片机】开发板上矩阵键盘键码在数码管上的显示,按下键盘在数码管上显示对应段码
【51单片机】开发板上矩阵键盘键码在数码管上的显示,按下键盘在数码管上显示对应段码
|
2月前
|
算法
51单片机不用定时器的数码管倒计时
51单片机不用定时器的数码管倒计时
|
5月前
|
传感器
51单片机矩阵键盘超详解!(内含LCD1602代码)
51单片机矩阵键盘超详解!(内含LCD1602代码)
76 0
【51单片机】初学者必学的一个矩阵键盘基本项目——(读矩阵键盘的数字显示在LCD屏上)(7)
【51单片机】初学者必学的一个矩阵键盘基本项目——(读矩阵键盘的数字显示在LCD屏上)(7)
|
5月前
|
数据安全/隐私保护
【51单片机】初学者必学的一个矩阵键盘基本项目——(矩阵键盘密码锁)(8)
【51单片机】初学者必学的一个矩阵键盘基本项目——(矩阵键盘密码锁)(8)
定时器+按键控制LED流水灯模式+定时器时钟——“51单片机”
定时器+按键控制LED流水灯模式+定时器时钟——“51单片机”
|
5月前
|
传感器
单片机定时器中断
单片机定时器中断
|
5月前
|
数据安全/隐私保护
C51单片机实现矩阵键盘密码锁
C51单片机实现矩阵键盘密码锁

热门文章

最新文章