1、单片机按键识别方法
单片机硬件按键有接电源和接地两种接发,我们通过程序判断当前引脚电平的高低来判断按键按下/放开。
程序略…
2、按键消抖的方法
我们知道机械按键在按下和弹起时,会因为产生抖动,出现高低电平快速变化,因此我们必须进行消抖处理。
常用的消抖方法有两种:电容消抖和软件消抖
代码例程:
if(switch_1 == 0)//判断switch_1按键按下时
{
Delay_ms(30);//延时消抖
if(switch_1 == 0)//再次判断switch_1按键按下
{
while(!switch_1);//松手检测
//请将按键功能写在下面
}
}
电容消抖:利用电容的放电延时,采用并联电容法,使两端电压平缓变化,直至电容充放电到达一定电压阀值时,单片机才能读取到电平变化。
软件消抖:写一段延时毫秒级延时函数,在按键按下后延时一段时间再次判断按键电平。但是软件消抖是以CPU资源为代价,会降低程序的执行效率,所以我们在做大型项目开发时,要尽量避免使用延时消抖。
3、矩形键盘原理
矩阵键盘一共有4行和4列一共16个按键组成,确定矩阵键盘上哪一个按键被按下可以采用列扫描和行扫描。
列扫描时先把接在列上面的IO拉高,接在行的所以IO置低,当其中有一列任何一个按键按下,那么整条都会被拉低。
我写好了一段矩阵键盘例程,封装成一个函数库。日后直接调用和工程参考,例程主要功能是当矩阵键盘任何值按下时,向串口发送当前按下矩阵键盘的值,例程带有矩阵键盘松手检测功能。
#include <reg52.h>
#include <intrins.h>
#define uint unsigned int
#define uchar unsigned char
/*常量宏定义*/
#define RECTANGUAR_KRYBOARD_IO P3//矩阵键盘IO口
//串口初始化,波特率9600
void InitUART(void)
{
TMOD = 0x20;//设置定时器1,工作方式2,8位自动重载
SCON = 0x40;//设置串口工作方式1
TH1 = 0xFD;//波特率设置为9600
TL1 = TH1;
PCON = 0x00;//波特率不加倍
EA = 1;//开总中断
ES = 1;//允许串联1中断
TR1 = 1;//启动定时器T1
}
//1ms延时函数
void Delay1ms(void) //@11.0592MHz
{
unsigned char i, j;
_nop_();
i = 2;
j = 199;
do
{
while (--j);
} while (--i);
}
//毫秒延时函数
void delay_ms(uint time)
{
uint i;
for(i=0; i<time; i++)
{
Delay1ms();
}
}
//向串口发送一个字符
void putchar(char ch)
{
SBUF = ch;
while(!TI);TI = 0;
}
//向串口发送一段字符串
void prints(char *s)
{
while(*s != '\0')//发送字符串,直到遇到0才结束
{
SBUF = *s++;
while(!TI);
TI = 0;
}
}
/******************************************************
函数名称:RectanguarKeyboard_Scanning(void)
函数输入:无
函数返回:unsigned int
函数说明:4*4矩阵键盘与独立键盘扫描
调用此函数,需添加RECTANGUAR_KRYBOARD_IO宏定义
*******************************************************/
uint RectanguarKeyboard_Scanning(void)
{
uint num;
//4*4矩阵键盘扫描
RECTANGUAR_KRYBOARD_IO = 0xf0;//列扫描
if(RECTANGUAR_KRYBOARD_IO != 0xf0)//判断按键是否按下
{
delay_ms(5);//软件消抖
if(RECTANGUAR_KRYBOARD_IO != 0xf0)
{
switch(RECTANGUAR_KRYBOARD_IO)//判断那一列被按下
{
case 0xe0: num=1; break;//第一列被按下
case 0xd0: num=2; break;//第二列被按下
case 0xb0: num=3; break;//第三列被按下
case 0x70: num=4; break;//第四列被按下
}
P3 = 0x0f;//行扫描
switch(RECTANGUAR_KRYBOARD_IO)
{
case 0x0e: while(RECTANGUAR_KRYBOARD_IO != 0x0f); return num; //第一行被按下
case 0x0d: while(RECTANGUAR_KRYBOARD_IO != 0x0f); num = num + 4; return num; //第二行被按下
case 0x0b: while(RECTANGUAR_KRYBOARD_IO != 0x0f); num = num + 8; return num; //第三行被按下
case 0x07: while(RECTANGUAR_KRYBOARD_IO != 0x0f); num = num + 12; return num; //第四行被按下
}
}
}
return 0;
}
void main(void)
{
char str[2];
uchar temp = 0;
InitUART();//初始化串口
while(1)
{
temp = RectanguarKeyboard_Scanning();
if(temp != 0)
{
if(temp < 10 && temp != 0)
{
temp = temp + '0';
putchar(temp);
}
else if(temp >= 10 && temp != 0)
{
str[0] = temp / 10 + '0';
str[1] = temp % 10 + '0';
prints(str);
}
temp = 0;
}
}
}