C51 2.按键
前言
轻触按键是通过内部的金属弹片受力弹动来实现接通和断开
也正应如此这种按键都存在抖动
祝愉快
1.原理图
P3口为正极,当按下K1时,P31口的电流通过K1到GND,这样P31的电平就为0了。所有当按下K1时,P31输出0。
-
P14到P17为行选择,P10到P13为列选择。当我们按下S1,P17和P13被连通了。
-
那么为了检测那个按键按下,我们就给P10到P13循环赋值0,当给一个引脚赋值0后检测P14到P17,看看哪一个引脚也同样变为了0,这两个引脚就对应出了我们按下的那个按键。
-
我们可以看到这里用了两层循环,外层为列扫描,内层为行扫描。列扫描时我们将列引脚设置为0然后判断行引脚,看看他是否为0,如果是,则就是这对行列所对应的按键被按下了。
2.按键抖动
因为按键在按下和松开时会发生抖动,那么我们在取值时就跳过按下和松开时,只在中间的时间段取值。
那么我们就要使用到Delay。
3.Delay
Delay是通过代码中每一行命令花费的时间的叠加来控制延时一段时间。
4.C代码
独立按键
#include <REGX52.H>
void main()
{
while(1)
{
if(P3_1==0 || P3_0==0) //如果K1按键或K2按键按下
{
P2_0=0; //LED1输出0,点亮
}
else
{
P2_0=1; //LED1输出1,熄灭
}
}
}
-
上面的代码没有考虑按键抖动,不提倡。
-
可以看到我们把独立按键的代码放在死循环中,因为我们按下按键这一事件是不确定什么时候发生的,那么我们就要一直等下去,一旦按下了按键 if 就会触发。
Delay
void Delay(unsigned int xms)
{
unsigned char i, j;
while(xms)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
xms--;
}
}
- 可以看到Delay里没有实质性意义的代码
- 我们通过_NOP_ 、while循环还有调用函数本身来凑到一个我们想要的延时
独立按键+Delay
#include <REGX52.H>
void Delay(unsigned int xms)
{
unsigned char i, j;
while(xms)
{
i = 2;
j = 239;
do
{
while (--j);
} while (--i);
xms--;
}
}
void main()
{
while(1)
{
if(P3_1==0) //如果K1按键按下
{
Delay(20); //延时消抖
while(P3_1==0); //松手检测
Delay(20); //延时消抖
P2_0=~P2_0; //LED1取反
}
}
}
- 将Delay放在按下后和松手后
矩阵键盘
#include <REGX52.H>
#include "Delay.h"
/**
* @brief 矩阵键盘读取按键键码
* @param 无
* @retval KeyNumber 按下按键的键码值
如果按键按下不放,程序会停留在此函数,松手的一瞬间,返回按键键码,没有按键按下时,返回0
*/
unsigned char MatrixKey()
{
unsigned char KeyNumber=0;
P1=0xFF; //复位 全部置1
P1_3=0; //一列置0
if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=1;} //判断那一行为0
if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=5;}
if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=9;}
if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=13;}
P1=0xFF; //复位
P1_2=0; //下一列置0
if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=2;}
if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=6;}
if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=10;}
if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=14;}
P1=0xFF;
P1_1=0;
if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=3;}
if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=7;}
if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=11;}
if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=15;}
P1=0xFF;
P1_0=0;
if(P1_7==0){Delay(20);while(P1_7==0);Delay(20);KeyNumber=4;}
if(P1_6==0){Delay(20);while(P1_6==0);Delay(20);KeyNumber=8;}
if(P1_5==0){Delay(20);while(P1_5==0);Delay(20);KeyNumber=12;}
if(P1_4==0){Delay(20);while(P1_4==0);Delay(20);KeyNumber=16;}
return KeyNumber;
}
-
我们把MatrixKey这样要一直检测的函数放在main的while(1)里面。
-
当然我们还可以把MatrixKey放在计时器中断里面,并且这样做的话我们还可以忽略按键抖动的问题,并且让按键和其他事件可以同时发生。不过这是后话。
总结
-
独立按键的引脚端在接通时被置0,这种发生在硬件上的事件对寄存器的影响是和学习C语言时操作变量遇到的情况是很不同的。
-
寄存器内部数据的变化是不会像变量变化一样写在代码里面的,我们往往要检测寄存器里的数值。
-
Delay等待按键内弹片稳定。
-
Delay在我们之后的学习中也有很大作用,我们往往要等待电流携带数据到达寄存器后再进行操作。(C51反应太慢了,其实后面用的不算多)
-
矩阵键盘利用行列扫秒完成对按键位置的确定。