历史上的今天
今天是:2025年02月09日(星期日)
2020年02月09日 | 基于状态机的按键长按,短按,双击 单片机源程序
2020-02-09 来源:51hei
先前根据以为前辈的程序理解了一段时间,之后自己写了一份控制led灯的简单按键程序
单片机源程序如下:
#include #include #define key_state_0 0 #define key_state_1 1 #define key_state_2 2 #define key_state_3 3 #define key_no 0 #define key_click 1 #define key_double 2 #define key_long 3 sbit KEY = P3^3; sbit LED_E1P = P3^1; sbit LED_G1 = P3^2; sbit LED2 = P5^5; //W2OUT sbit LED3 = P5^4; unsigned char flag; unsigned char cnt = 0; static unsigned char key_driver(void) { static unsigned char key_state_buffer1 = key_state_0; static unsigned char key_timer_cnt1 = 0; unsigned char key_return = key_no; unsigned char key; key = KEY; //read the I/O states switch(key_state_buffer1) { case key_state_0: if(key == 0) key_state_buffer1 = key_state_1; //按键被按下,状态转换到按键消抖和确认状态// break; case key_state_1: if(key == 0) { key_timer_cnt1 = 0; key_state_buffer1 = key_state_2; //按键仍然处于按下状态 //消抖完成,key_timer开始准备计时 //状态切换到按下时间计时状态 } else key_state_buffer1 = key_state_0; //按键已经抬起,回到按键初始状态 break; //完成软件消抖 case key_state_2: if(key == 1) { key_return = key_click; //按键抬起,产生一次click操作 key_state_buffer1 = key_state_0; //转换到按键初始状态 } else if(++key_timer_cnt1 >= 100) //按键继续按下,计时超过1000ms { key_return = key_long; //送回长按事件 key_state_buffer1 = key_state_3; //转换到等待按键释放状态 } break; case key_state_3: //等待按键释放 if(key == 1) //按键释放 key_state_buffer1 = key_state_0; //切回按键初始状态 break; } return key_return; } unsigned char key_read(void) { static unsigned char key_state_buffer2 = key_state_0; static unsigned char key_timer_cnt2 = 0; unsigned char key_return = key_no; unsigned char key; key = key_driver(); switch(key_state_buffer2) { case key_state_0: if(key == key_click) { key_timer_cnt2 = 0; //第一次单击,不返回,到下个状态判断是否会出现双击 key_state_buffer2 = key_state_1; } else key_return = key; //对于无键、长按,返回原事件 break; case key_state_1: if(key == key_click) //又一次单击,时间间隔小于500ms { key_return = key_double; //返回双击事件,回到初始状态 key_state_buffer2 = key_state_0; } else if(++key_timer_cnt2 >= 50) { //这里在下一次的按键来临之前,并且时间是小于500ms的时候,就会一直执行的是这个key_timer_cnt2++.直到下一次的按键到来,再判断看是双击还是单击。 //这里500ms内肯定读到的都是无键事件,因为长按大于1000ms //在1s前底层返回的都是无键 key_return = key_click; //500ms内没有再次出现单击事件,返回单击事件 key_state_buffer2 = key_state_0; //返回初始状态 } break; } return key_return; } void Timer0Init(void) //1毫秒@11.0592MHz { AUXR |= 0x80; //定时器时钟1T模式 TMOD &= 0xF0; //设置定时器模式 TL0 = 0xCD; //设置定时初值 TH0 = 0xD4; //设置定时初值 TF0 = 0; //清除TF0标志 TR0 = 1; //定时器0开始计时 ET0 = 1; } void IO_init() { P3M0 = 0x01; P3M1 = 0x01; P5M0 = 0x00; P5M1 = 0x00; } void main(void) { unsigned char key = 1; Timer0Init(); IO_init(); LED_E1P = 1; LED_G1 = 1; LED2 = 1; LED3 = 0;
上一篇:51单片机是如何产生串口中断的
史海拾趣
|
摘 要:在分析Linux2.6内核新特性的基础上,在S3C2410开发板上移植了2.6内核和新的文件系统,并成功地对H.264编解码多媒体系统提供了支持。 关键词:Linux 内核 嵌入式系统 S3C2410… 查看全部问答> |
|
2010年网络通信产业的三大发展重点是:802.11n成为WLAN主流标准、WiMAX、光接入(由于IPTV服务的推动,EPON和GPON设备出货比重将提升)。 2010年随着中国电信和中国网通陆续推出许多新方案,并且得标厂商将部分订单交由台湾厂商生产(如WiFi ADSL路由 ...… 查看全部问答> |
|
想花3个月时间仔细研究IEEE802.11B协议. 顺便在自己的Windows CE上写个IEEE802.11b驱动. 可是不知道哪里有非常完整的协议规格标准书? 如果有中文就就更好了.… 查看全部问答> |
|
兄弟我做了一个STM32F10XVB的核心小板,包含CPU、晶体、电容、复位,100个管脚用了4个2X13的接插件引出,有个疑问: 将5个VDD接到一块,使用一个脚引出供电?还是使用5个脚供电?5个脚存在回路问题吧?另外VSS呢,地的接法应该怎样? 我初步想 ...… 查看全部问答> |
|
那位大侠有这两本书,现在需要,谢谢!《基于quartus II的fpga/cpld设计与实践》,陈忠平;《基于quartus II的fpga/cpld设计与应用》,赵艳华,wangjiangqiang333@163.com不胜感激!!谢谢:\'(… 查看全部问答> |




