51单片机按键计数器程序_MCS-51单片机4×4矩阵按键的扫描

本文介绍了51单片机中4×4矩阵按键的工作原理及消抖处理。通过实例讲解了如何扫描矩阵按键,并利用定时器T0进行1ms的间隔扫描,使用二维数组keybuf和keysta进行消抖判断,确保按键状态的稳定性。
摘要由CSDN通过智能技术生成

以金沙滩工作室的STC89C52单片机开发板为例,记录学习51单片机的笔记,本文章主要讲解了4×4矩阵按键的扫描,教材是金沙滩工作室(www.kingst.org )宋雪松老师编著的《手把手教你学51单片机-C语言版》,所用的开发板是教材配套开发板。在这里推荐一下宋老师的这套教材,感觉还是蛮不错的。下面是该文章的目录:

1.矩阵按键及其原理

2.矩阵按键的消抖

1.矩阵按键及其原理

图1是单片机开发板上的矩阵按键的实物图,图2是矩阵按键的电路原理图。以4×4矩阵按键为例,总共包含了16个按键,包括数字0~9、四个方向键(上下左右)、ESC键和回车键,当然在使用过程中可以定义这些按键为其他功能,灵活多变。

95b37785ca79cc1b611ecd9c06700567.png
图2 4×4矩阵按键的电路图

16个按键占用P2的8个IO口,见上图2,KeyOut1~KeyOut4为输出引脚,KeyIn1~KeyIn4为读取引脚。KeyOut1~KeyOut4均输出高电平时,由于全部KeyIn引脚最上面与+5V接通,故无论某个按键是否按下,KeyIn1~KeyIn4读取到的均为高电平(逻辑1),无法判断是否有按键按下/弹起,当其中的某个KeyOut引脚输出低电平(逻辑0)时,按下该行的某个按键,那么这个按键对应的keyIn引脚将读取到低电平,从而可以在程序中判断某个按键是否被按下。

例如,现在使KeyOut3引脚为0,其余KeyOut引脚为1,那么当按键K12按下时,KeyIn4引脚直接与KeyOut3引脚连通,将其电平拉低,P2.7就可以读取到0,那么就可以判断K12(右键)被按下了。

2.矩阵按键的消抖和扫描

由于按键的机械特性,按键存在“抖动”的情况,比如,当按下某个键的瞬间,这个键可能还会来回抖动几次,当然这种抖动是手指感觉不出来的,但它确实会影响读取到的电平的高低,相反,按键弹起的瞬间,也会存在抖动的情况。如图3,按键抖动通常只持续不到10ms,按下到弹起的整个过程通常持续100ms以上,所以需要进行消抖处理。

e34b2782648ccb545d2c5e107f315cdd.png
图3 按键的抖动

在这里,按键消抖的思路定义一个4X4的二维数组 keybuf[4][4]和keysta[4][4]

unsigned char keybuff[4][4] = {
	{0xFF, 0xFF, 0xFF, 0xFF}, 
	{0xFF, 0xFF, 0xFF, 0xFF}, 
	{0xFF, 0xFF, 0xFF, 0xFF}, 
	{0xFF, 0xFF, 0xFF, 0xFF}
}; //定义在中断函数内

unsigned char KeySta[4][4] = {
	{1, 1, 1, 1},
	{1, 1, 1, 1},
	{1, 1, 1, 1},
	{1, 1, 1, 1},
}; //定义为全局变量

keybuf[4][4]中每一个元素代表了对应按键在某个瞬间的状态,初始化为0xFF(0b11111111),就意味着开始每个按键均为弹起状态。

设置定时/计数器T0的定时时长为1ms,每次中断,就选中keybuff其中一行,依次将该行的四个元素左移一位,并将对应的KeyInx(x = 1, 2, 3, 4)的值写入数组元素的最低位,如此就需要4ms完成四行按键的扫描,但是,通常抖动的时间在10ms左右,那么干脆就在16ms内判断某个按键是否被稳定的按下或者弹起,若在16ms中读取到的某个按键的状态均为0或者1,那么就可以判断这个按键已经被稳定地按下或者弹起了,这时,就将存储按键状态的二维数组KeySta[4][4]中对应的按键的状态置为0或者1。

下面是部分示例代码(定义KeyScan函数专门用于按键的扫描,它在T0的中断函数内被调用)。

#include<reg52.h>

sbit KeyOut4 = P2^0;
sbit KeyOut3 = P2^1;
sbit KeyOut2 = P2^2;
sbit KeyOut1 = P2^3;
sbit KeyIn1 = P2^4;
sbit KeyIn2 = P2^5;
sbit KeyIn3 = P2^6;
sbit KeyIn4 = P2^7;

unsigned char KeySta[4][4] = {
     {1, 1, 1, 1},
     {1, 1, 1, 1}, 
     {1, 1, 1, 1}, 
     {1, 1, 1, 1}
 };
unsigned char code KeyCodeMap[4][4] = {
	{ 0x31, 0x32, 0x33, 0x26 }, //数字键 1、数字键 2、数字键 3、向上键
    { 0x34, 0x35, 0x36, 0x25 }, //数字键 4、数字键 5、数字键 6、向左键
    { 0x37, 0x38, 0x39, 0x28 }, //数字键 7、数字键 8、数字键 9、向下键
    { 0x30, 0x1B, 0x0D, 0x27 } //数字键 0、ESC 键、 回车键、 向右键;
};

void KeyScan()
{
	static unsigned char KeyBuff[4][4] = {
		{0xFF, 0xFF, 0xFF, 0xFF}, 
	    {0xFF, 0xFF, 0xFF, 0xFF}, 
	    {0xFF, 0xFF, 0xFF, 0xFF}, 
	    {0xFF, 0xFF, 0xFF, 0xFF}
	};
	static unsigned char row = 0;
	unsigned char col;
	KeyBuff[row][0] = (KeyBuff[row][0] << 1) | KeyIn1;
	KeyBuff[row][1] = (KeyBuff[row][1] << 1) | KeyIn2;
	KeyBuff[row][2] = (KeyBuff[row][2] << 1) | KeyIn3;
	KeyBuff[row][3] = (KeyBuff[row][3] << 1) | KeyIn4;
	for (col = 0; col < 4; col++)
	{
		if ((KeyBuff[row][col]) & 0x0F == 0x0F)
		{
			KeySta[row][col] = 1;
		}
		else if ((KeyBuff[row][col] & 0x0F) == 0x00)
		{
			KeySta[row][col] = 0;
		}
	}
	row++;
	row  = row & 0x03;
	switch (row)
	{
		case 0: KeyOut4 = 1; KeyOut1 = 0; break;
		case 1: KeyOut1 = 1; KeyOut2 = 0; break;
		case 2: KeyOut2 = 1; KeyOut3 = 0; break;
		case 3: KeyOut3 = 1; KeyOut4 = 0; break;
		default: break;
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值