yonggandehuo
做自己该做的事情
全部博文(28)
computer(1)
music(0)
2014年(1)
2013年(2)
2012年(4)
2010年(21)
yangzhig
飞鸿无痕
Bean_lee
jobchanc
浪花小雨
Bsolar
tomer
linuxmut
lang1382
lmnos
zk245576
医药护理
hwayw
分类:
2010-08-25 00:14:26
//hnrain 改
//适用于CEPARK 51开发板
/*****************************************************************************************************************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"/******宏定义***************************************************************************************************/#define No_key 255 //无键按下返回值/****** 定义全局变量********************************************************************************************/unsigned char keyread_flag = 0; //矩阵键盘扫描标志位unsigned char num = 0; //定时计数器计数变量unsigned char outdata = 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) interrupt 3{ 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 else if(outdata == 2) P0 = 0x55; //双击按键1 点亮第2468个LED else if(outdata == 3) P0 = 0x00; //三击按键2 点亮全部LED }}
上一篇:是怎么了
下一篇:单片机
登录 注册