找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 3204|回复: 9
打印 上一主题 下一主题
收起左侧

单片机单键长按,单击、双击及三击响应程序请教

[复制链接]
跳转到指定楼层
楼主
ID:91521 发表于 2020-5-30 15:25 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
我要做一个警告灯小程序,需要单片机识别单按键,实现对长按,单击、双击及三击的响应,由于是初学,一点头绪也没有,请各位高人指导!另外还有要对各种按键响应程序融会贯通,需要掌握什么基础知识呢?
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:332444 发表于 2020-5-30 17:17 | 只看该作者
三击的响应?有单击 双击 长按可参:https://blog.csdn.net/xianfajushi/article/details/82281411
回复

使用道具 举报

板凳
ID:162664 发表于 2020-5-30 22:22 | 只看该作者
初学啊。
简单说需要几点:
1:mcu的定时器设置、中断设置。
2:io口输入输出、读取。内部结构暂时不需要太深刻的理解。
3:基本的c51语言。
4:了解按键的消抖的问题。
5:因为你目前的功能,是对于上升沿、下降沿、的判断问题。可以考虑看看自己度娘下边的红字部分。吴坚鸿讲的东西嘛,干这行的普遍已经用到了的东西,可能没意识到或者不屑于将这种东西的问题,有人总结还是可以收藏看看的。
从业将近十年!手把手教你单片机程序框架(连载)
回复

使用道具 举报

地板
ID:681584 发表于 2020-5-31 17:09 | 只看该作者
#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 #define key_input        P30/***************************************************************************程序功能:一个按键的单击、双击、长按。三种按键方式,然后做不同的处理。   ***************************************************************************/ 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_input;  //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;} /***************************************************************************函数功能:中层按键处理函数,调用底层函数一次,处理双击事件的判断,                                        返回上层正确的无键、单击、双击、长按四种状态本函数由上层循环调用,间隔10ms***************************************************************************/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内肯定读到的都是无键事件,因为长按大于1000ms                                //在1s前底层返回的都是无键                                                                                                                                                key_return = key_click;  //500ms内没有再次出现单击事件,返回单击事件                               
直接贴上源码

key_state_buffer2 = key_state_0;  //返回初始状态                                                                                }                        break;        }                return key_return;}
————————————————
版权声明:本文为CSDN博主「沉默的小宇宙」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/qq997758497/java/article/details/80606710
回复

使用道具 举报

5#
ID:715652 发表于 2020-5-31 23:03 | 只看该作者
#include<reg51.h>
sbit KEY=P1^0;  //检测端口
int t0=0; //按键次数变量
void DelayMs(int x)  //延时
{
        int i;
        while(x--) for(i=0;i<120;i++);
}
int KEY_SCAN(bit a)  //按键检测
{
        int t=0;
        if(!a)
        {
                DelayMs(5);
                while(!a)        t=++t%50,DelayMs(50);  //按键时长
                t0=++t0%4;   //按键次数
        }
        if(t0==1 && t<5)        return 1;   //单击
        if(t0==2 && t<5)        return 2;   //双击
        if(t0==3 && t<5)        return 3;   //三击
        if(t>5)                return 4;  //长按
        return 0;
}
void main()
{
        int i=0,j=0;
        while(1)
        {
                i=KEY_SCAN(KEY);  //会进行覆盖
                DelayMs(100);
                j++;
                if(j==20)        t0=0;   //长时间不按,清除按键次数为0
        }
}
回复

使用道具 举报

6#
ID:715652 发表于 2020-5-31 23:12 | 只看该作者
  1. #include<reg51.h>
  2. sbit KEY=P1^0;  
  3. int t0=0;
  4. void DelayMs(int x)  
  5. {
  6.         int i;
  7.         while(x--) for(i=0;i<120;i++);
  8. }
  9. int KEY_SCAN(bit a)  
  10. {
  11.         int t=0;
  12.         if(!a)
  13.         {
  14.                 DelayMs(5);
  15.                 while(!a)        t=++t%50,DelayMs(50);  //按键的时长
  16.                 t0=++t0%4;   
  17.         }
  18.         if(t0==1 && t<5)        return 1;   //单击
  19.         if(t0==2 && t<5)        return 2;   //双击
  20.         if(t0==3 && t<5)        return 3;   //三击
  21.         if(t>5)                return 4;  //长按
  22.         return 0;
  23. }
  24. void main()
  25. {
  26.         int i=0,j=0;
  27.         while(1)
  28.         {
  29.                 i=KEY_SCAN(KEY);  //按键返回的值会覆盖
  30.                 DelayMs(100);
  31.                 j++;
  32.                 if(j==20)        t0=0;   //长时间不按键,清除按键次数
  33.         }
  34. }
  35. //希望有用,我也是新手!
复制代码
回复

使用道具 举报

7#
ID:719007 发表于 2020-6-1 09:12 | 只看该作者
用状态机
可以参考www点amobbs点com/thread-4991902-1-1.html
回复

使用道具 举报

8#
ID:91521 发表于 2020-6-2 18:01 | 只看该作者
本帖最后由 daiya 于 2020-6-3 10:45 编辑

5楼好奇妙的算法,似乎有问题,在实验板上实现不了
回复

使用道具 举报

9#
ID:91521 发表于 2020-6-3 10:33 | 只看该作者

我在实验板上试了,行不通,每次都由1击逐渐过渡到3击
回复

使用道具 举报

10#
ID:401564 发表于 2020-6-3 19:37 | 只看该作者
你已经懂得看别人的算法了,那就自己写代码了,不要等别人的代码,这是不现实的,大多的只能给你一个参考意见或者直接复制一段代码给你,网上很多是没有真正验证过的
你先画个流程图,然后写代码,烧录验证,不要仿真
不行,改代码,烧录验证,不要仿真
再不行,再改代码,再烧录验证,不要仿真
再不行,再改代码.............
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

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