新闻中心

EEPW首页>嵌入式系统>设计应用> 51单片机按键双击

51单片机按键双击

作者: 时间:2016-11-25 来源:网络 收藏
//hnrain 改

//适用于CEPARK 51开发板

本文引用地址://m.amcfsurvey.com/article/201611/321094.htm

/*****************************************************************************************************************
www.cepark.com电子园 按键高阶攻略设计大赛

名称:2*4矩阵键盘扫描(状态机)
功能:按键0单击时,点亮P0口的第1357个LED,按键1双击时,点亮P0口的2468个LED,按键2三击时,点亮P0口的所有的LED
按键按下的时间间隔小于200ms。 其他键按下时,LED状态不变
作者:alger2009
时间:2009.12.30 星期三
版本:V1.0
其他:该开发板的LED不是单个的LED组成,而是LED逻辑卡;看门狗程序防止程序跑飞

*****************************************************************************************************************/

#include"reg52.h"
#include"intrins.h"
#include"key2.h"


/******宏定义***************************************************************************************************/
#defineNo_key 255//无键按下返回值


/******定义全局变量********************************************************************************************/
unsigned charkeyread_flag=0;//矩阵键盘扫描标志位
unsigned char num=0;//定时计数器计数变量
unsigned charoutdata=0;//返回值

/******2*4矩阵键盘扫描程序**********************************************************************************************
返回值:key_return
key_return=0 单击
key_return=1 双击
key_return=2 三击
key_return=其他,按键无效
************************************************************************************************************************/
unsigned char read_keyboard(void)
{
static unsigned char key_state=0,key_value,key_line;// 列读取变量,行扫描码
static unsigned char key_times=0;//按键击打次数
static unsigned char Tcount=0;//按键连击计时变量
unsigned char key_return=No_key,i;//按键返回值
switch(key_state)
{
case 0://key you meiyou cunzai jiancha//状态0功能: 按键扫描 连击计时 和连击超时处理
key_line=0x10;
if(key_times!=0)Tcount++;//如果不是第一次击打,计时变量加1
if(Tcount>20)//若连击按键按下时间间隔大于200毫秒
{
key_times=0;// 按键击打次数归0
Tcount=0;// 计时变量归0
}
for(i=0;i<2;i++)// 扫描键盘
{
P2=~key_line;// 输入行扫描码
P2=~key_line;// 重复送一次
key_value=0x0f & P2;// 读列电平
if(key_value==0x0f)
key_line<<=1;// 没有按键,继续扫描
else
{
key_state++;// 有按键,停止扫描
break;// 跳出按键扫描
}
}
break;
case 1://状态1功能:确认按键 读取按键值
if(key_value==(0x0f & P2))// 再次读列电平,若非抖动
{
switch(key_line|key_value)//行扫描码和列电平,确认按键
{// 键盘编码,返回编码值
case 0x1e://单击按键0
key_return=1;
break;
case 0x1d:
{
if(key_times==1 && Tcount<20)
key_return=2;//双击按键1
else
key_times++;//第一次按下,计数加1
}
break;
case 0x1b:
{
if(key_times==2 && Tcount<20)
key_return=3;//三击按键2
else
key_times++;//第一次或第二次按下,计数加1
}
break;
case 0x17:
key_return=4;
break;
case 0x27:
key_return=5;
break;
case 0x2b:
key_return=6;
break;
case 0x2d:
key_return=7;
break;
case 0x2e:
key_return=8;
break;
}
key_state++;// 转入等待按键释放状态
}
else
key_state--;// 两次列电平不同返回状态0,(消抖处理)
break;
case 2://状态2功能:按键释放判定
P2=0x0f;// 行线全部输出低电平
P2=0x0f;// 重复送一次
if((P2 & 0x0f)==0x0f)
key_state=0;// 按键释放,返回状态0
break;
}
return key_return;//返回值
}


/******定时器1 定时1毫秒******************************************************************************/
void timer1(void)interrupt3
{
TH1=(65536-1000)/256;
TL1=(65536-1000)%256;
if(++num==10)
{keyread_flag=1;//按键扫描允许标志位
num=0;
}
}


/******定时器初始化**********************************************************************************/
void timer1_initial(void)
{
TH1=(65536-1000)/256;
TL1=(65536-1000)%256; //装初始值
IE=0x88; //开总中断和定时器1中断
TMOD=0x10; //工作方式1
TR1=1; //启动定时器
}


/******看门狗子程序*********************************************************************************/
void clr_wdt(void)
{
WDTRST=0x1e;
WDTRST=0xe1;
}


/******主程序****************************************************************************************/
main(void)
{
P0=0xff;//初始化LED端口
timer1_initial();//定时器1初始化
while(1)
{
if(keyread_flag==1)//矩阵扫描标志位允许
{
keyread_flag=0;
clr_wdt();//调用看门狗 (每2的14次方个机器周期内必须调用一次,使看门狗复位)
outdata=read_keyboard();//读取矩阵键盘返回值
}

if(outdata==1)
P0=0xaa;//单击按键0 点亮第1357个LED
elseif(outdata==2)
P0=0x55;//双击按键1 点亮第2468个LED
elseif(outdata==3)
P0=0x00;//三击按键2 点亮全部LED
}
}



关键词:51单片机按键双

评论


技术专区

关闭