51单片机按键连击

51单片机按键双击

关键字:51单片机  按键双击

//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     } }

原文地址:https://www.cnblogs.com/luxiaolai/p/5252769.html