找回密码
 注册
关于网站域名变更的通知
查看: 234|回复: 2
打印 上一主题 下一主题

基于状态机的按键长按,短按,双击 单片机源程序

[复制链接]

该用户从未签到

跳转到指定楼层
1#
发表于 2022-8-29 09:51 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式

EDA365欢迎您登录!

您需要 登录 才可以下载或查看,没有帐号?注册

x
先前根据以为前辈的程序理解了一段时间,之后自己写了一份控制led灯的简单按键程序0 }' S1 ~" f* M1 C/ t8 u. K6 l6 P

; R& n1 [7 R* l, D单片机源程序如下:
+ g5 o! i6 D" K, _; h- }6 o6 S
  • #include<stc15w202s.h>
  • #include<stdio.h>
  • #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;
  •                    EA = 1;
  •            while(1)
  •            {
  •              if(flag)
  •                  {
  •                    flag=0;
  •            key = key_read();
  •                    switch(key)
  •                    {
  •                             case key_clickED2 = !LED2; break;
  •                          case key_doubleED2 = !LED2;LED3 = !LED3; break;
  •                          case key_long: LED2 = 1; LED3 = 1; LED_G1 = 0; LED_E1P = 0; break;
  •                          default : break;
  •                    }
  •                  }
  •            }
  • }
  • void Timr0_ISR() interrupt 1
  • {
  •    cnt++;
  •    if(cnt>=10)
  •    {
  •        cnt = 0;
  •               flag = 1;
  •    }
  • }
  • & D+ J' s$ R; w! p# b/ H; P

; ^0 V4 q+ n) B6 c复制代码2 w8 [2 A  r  m; E( \- l
* Q4 F. x6 W3 ^$ q0 ~2 P
. ?7 i; l+ b4 m
# I; p1 a1 P  N: l" S& S8 ]+ Z! S; o
5 d" h( _3 G& [! q: [4 l

3 n9 B5 M6 M6 a2 w( d9 Q. s
* {+ d% |/ ?- ^' M2 a* J/ p2 X7 E! w/ b7 H) J* D8 |/ @
. R8 S0 o- N# W- b$ \, `5 L) s

该用户从未签到

2#
发表于 2022-8-29 10:40 | 只看该作者
很好很好,值得学习!!!

该用户从未签到

3#
发表于 2022-8-29 11:16 | 只看该作者
谢谢分享,谢谢分享
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

推荐内容上一条 /1 下一条

EDA365公众号

关于我们|手机版|EDA365电子论坛网 ( 粤ICP备18020198号-1 )

GMT+8, 2025-6-18 13:54 , Processed in 0.078125 second(s), 23 queries , Gzip On.

深圳市墨知创新科技有限公司

地址:深圳市南山区科技生态园2栋A座805 电话:19926409050

快速回复 返回顶部 返回列表