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

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

[复制链接]

该用户从未签到

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

EDA365欢迎您登录!

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

x
先前根据以为前辈的程序理解了一段时间,之后自己写了一份控制led灯的简单按键程序2 A! R6 k% W7 s/ y2 C0 l

; m$ _6 V8 p0 C8 a* M/ o单片机源程序如下:
4 o1 A( s, n8 X
  • #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;
  •    }
  • }

  • , o3 u# V3 P2 w& d# N
7 F% o% _; |$ o
复制代码- W% B- g- P5 u- x

0 H, V& U. c# X  V( F  q9 l
, y7 Z7 g! W( q
/ t2 k6 b: O3 Y6 `
7 z$ B* x) M4 c7 G# _$ n, @
3 |5 N7 x3 Q/ i& k" m( M/ z' B) a

5 O; x. J1 {: L7 D  q$ c3 d* \8 _& P5 g$ c+ a+ E) w% q
9 q' b1 ]6 z% w7 O

该用户从未签到

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

该用户从未签到

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

本版积分规则

关闭

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

EDA365公众号

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

GMT+8, 2025-6-4 18:34 , Processed in 0.093750 second(s), 23 queries , Gzip On.

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

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

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