找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 13565|回复: 19
收起左侧

求助:51单片机一个独立按键实现三个功能思路?

  [复制链接]
ID:141497 发表于 2018-3-13 00:17 | 显示全部楼层 |阅读模式
说明:我想做一个独立按键实现三个功能:比如短按打开或者关闭LED1,中按打开或者关闭LED2,长按打开或者关闭LED3。求助各位坛友:要按那种思路编程实现一个独立按键实现三个功能,或者给个参考示例。谢谢了!
回复

使用道具 举报

ID:155507 发表于 2018-3-13 06:41 | 显示全部楼层
我给你来个试试

  1. /*******************************************************
  2. |一个按键两种功能,就是短按一下LED灯亮,
  3. |再按一下灭,长按2秒另一个LED亮,再按一下灭
  4. |
  5. *******************************************************/
  6. #include <reg52.h>
  7. #include <intrins.h>
  8. #define uint unsigned int //宏定义:unit=unsigned int
  9. #define uchar unsigned char

  10. sbit led1=P1^0;
  11. sbit led2=P1^1;

  12. sbit s=P3^5;

  13. uchar flag1,flag2;

  14. void delay(uint);
  15. void keyscan();

  16. void main()
  17. {
  18.         while(1)
  19.         {
  20.                 keyscan();

  21.         }
  22. }
  23. void keyscan()
  24. {
  25.         uint j;
  26.         j=0;
  27.         s=1;
  28.         if(flag1==1||flag2==1)
  29.         {        
  30.                 if(!s)
  31.                 {
  32.                         delay(5);
  33.                         if(!s)
  34.                         {
  35.                                 while(!s);
  36.                                 flag1=0;
  37.                                 flag2=0;
  38.                                 led1=1;
  39.                                 led2=1;
  40.                         }
  41.                 }
  42.         }
  43.         else
  44.         {
  45.                 if(!s)
  46.                 {
  47.                         delay(5);
  48.                         if(!s)
  49.                         {
  50.                                 while(s==0 && j<30000)
  51.                                 {
  52.                                         //        delay(5);
  53.                                         j++;
  54.                                 }
  55.                                
  56.                                 if (j>=30000)
  57.                                 {
  58.                                         flag2=1;
  59.                                         led2=0;
  60.                                         while(!s);        
  61.                                 }
  62.                                 else
  63.                                 {
  64.                                         flag1=1;
  65.                                         led1=0;
  66.                                 }
  67.                                
  68.                                
  69.                         }
  70.                 }
  71.         }        
  72. }
  73. void delay(uint z)
  74. {
  75.         //1ms延时
  76.         uint i,j;
  77.         for(i=z;i>0;i--)
  78.         for(j=110;j>0;j--);
  79. }

复制代码

评分

参与人数 1黑币 +60 收起 理由
admin + 60 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:283686 发表于 2018-3-13 08:07 | 显示全部楼层
按键巡判断两次间隔时间 和 按下后的时间常数  除颤 等因素 就可以实现 。也可以添加条件判断 但是繁琐了  ,缺点是时间控制不好,会产生误操作

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:291092 发表于 2018-3-13 09:01 | 显示全部楼层
可以定义一个变量,比如int n=0;按键按一次变量n的值加1,n=1的时候第一个功能, n=2的时候第二个功能, n=3第三个功能。while循环n>3的时候,变量清0.

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:85726 发表于 2018-3-13 09:04 | 显示全部楼层
按键按下一次时,定义一个变量++,再用if判断即可!

评分

参与人数 1黑币 +20 收起 理由
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:212149 发表于 2018-3-13 10:07 | 显示全部楼层
这个按键的短按、中按、长按的想法我认为较难实现,因为多长算短,多久算长是一个比较难比较难把握。我建议采用中断方式,定时器设置3秒定时,检测3秒内按下几次按键,如果检测到进入一次中断则表示按下一次按键标志位加一,两次表示按下两次按键。3s的定时时间到了,然后查看标志位的值然后进入相应的分支函数操作。

评分

参与人数 1黑币 +40 收起 理由
admin + 40 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:164602 发表于 2018-3-13 10:12 | 显示全部楼层
个人认为:结合定时器比较好。
思路大致是这样的:
当按键按下时,开始定时器计时;松开按键后,停止定时器计时,并判断计时时间长短;根据按键时长,做相应的功能。
这个思路,理论上说,一个按键可以有很多功能的。
但也有一个问题,那就是按键时间长短,应该有很明显的区别,否则,人是不好控制时间长短的。所以通常只有长按和短按两个功能,很好区分。

评分

参与人数 1黑币 +40 收起 理由
admin + 40 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:225288 发表于 2018-3-13 19:16 | 显示全部楼层
这种网上很多的
回复

使用道具 举报

ID:151348 发表于 2018-3-13 21:21 | 显示全部楼层
推荐状态机,看看这个博客,应该对你有所帮助,http://blog.csdn.net/streamlightcwm824/article/details/6545003
回复

使用道具 举报

ID:141497 发表于 2018-3-13 23:01 | 显示全部楼层
非常感谢各位坛友的热心帮助,由于工作需要用到单片机,才开始学习单片机这一块,加上英文不好,学历不高,所以进度很慢,有很多地方不明白,身边没有搞编程的人,只有来论坛求助了。再次感谢各位的宝贵意见,谢谢!!!
回复

使用道具 举报

ID:216962 发表于 2018-9-21 09:58 | 显示全部楼层
谢谢,正想学这个,论坛有你更精彩。
回复

使用道具 举报

ID:230718 发表于 2018-9-23 15:08 | 显示全部楼层
短按 双击 长按
回复

使用道具 举报

ID:111634 发表于 2018-9-23 21:53 | 显示全部楼层
本帖最后由 zl2168 于 2018-9-24 21:34 编辑

一键三用案例。实例93  99.9秒秒表
Proteus仿真一下,确认有效。
实例95 99.9秒秒表.rar (38.86 KB, 下载次数: 29)
回复

使用道具 举报

ID:111634 发表于 2018-9-23 21:55 | 显示全部楼层
本帖最后由 zl2168 于 2018-9-24 21:38 编辑

长按和短按按键功能案例
实例96  能预置初值的倒计时秒表
Proteus仿真一下,确认有效。
实例96 能设置初值的倒计时秒表.rar (40 KB, 下载次数: 25)
回复

使用道具 举报

ID:1042234 发表于 2022-8-17 11:36 | 显示全部楼层
按键按下一次时,定义一个变量++,再用if判断即可!
回复

使用道具 举报

ID:89979 发表于 2022-8-18 23:31 | 显示全部楼层
记录按下和松开时间,通过时间间隔定义你的短按,中按,长按变量,进行相应的操作
回复

使用道具 举报

ID:1034262 发表于 2022-8-19 10:39 | 显示全部楼层
单键我通常3个功能:单击、双击、长按,按下计数、间隔计数即可。
回复

使用道具 举报

ID:190577 发表于 2022-8-19 16:20 | 显示全部楼层
使用状态机编程即可。
// 按键
#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 = P0^4;
sbit key1=P5^0;// 红光
sbit key2=P3^0;//绿光开关
sbit key3=P0^2;        //蓝
sbit key4=P4^0;        //白
sbit key5=P0^3; //加湿度
sbit key6=P5^2;//自动

static unsigned char key_read(void)
{
        static unsigned char key_state_buffer1 = key_state_0;
        static unsigned char key_timer_cnt1 = 0;
                static         unsigned char temp=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)||(key1 == 0)||(key2==0)||(key3==0)||(key4==0)||(key5==0)||(key6==0))
                         {  key_state_buffer1 = key_state_1; temp=0;
                                                         return 0;
                                                 }
                                //按键被按下,状态转换到按键消抖和确认状态//
                        break;
                case key_state_1:
                        if(KEY== 0)
                        {
                                temp=1;
                                                            key_timer_cnt1 = 0;
                                key_state_buffer1 = key_state_2;
                                //按键仍然处于按下状态
                                //消抖完成,key_timer开始准备计时
                                //状态切换到按下时间计时状态
                        }
                                                else if(key1==0)
                                                {
                                                           temp=2;
                                                           // key_timer_cnt1 = 0;
                                key_state_buffer1 = key_state_2;
                                                }
                                                else if(key2==0)
                                                {
                                                            temp=4;
                                                           // key_timer_cnt1 = 0;
                                key_state_buffer1 = key_state_2;
                                                }
                                                else if(key3==0)
                                                {
                                                            temp=5;
                                                           // key_timer_cnt1 = 0;
                                key_state_buffer1 = key_state_2;
                                                }
                                                else if(key4==0)
                                                {
                                                            temp=6;
                                                           // key_timer_cnt1 = 0;
                                key_state_buffer1 = key_state_2;
                                                }
                                                else if(key5==0)
                                                {
                                                            temp=7;
                                                           // key_timer_cnt1 = 0;
                                key_state_buffer1 = key_state_2;
                                                }
                                                else if(key6==0)
                                                {
                                                            temp=8;
                                                           // key_timer_cnt1 = 0;
                                key_state_buffer1 = key_state_2;
                                                }
                        else
                                                {
                                key_state_buffer1 = key_state_0; temp=0;
                                                }
                                //按键已经抬起,回到按键初始状态
                        break;  //完成软件消抖
                case key_state_2:
                                                 if((KEY == 0)||(key1 == 0)||(key2==0)||(key3==0)||(key4==0)||(key5==0)||(key6==0))
                                                {
                                                         key_state_buffer1 = key_state_2;
                                                         if(temp==1)
                                                         {
                                                                 if(++key_timer_cnt1 >= 100)  //按键继续按下,计时超过1000ms
                                                                 {
                                                                    
                                        key_return = key_long;  //送回长按事件
                                        key_state_buffer1 = key_state_3;  //转换到等待按键释放状态
                                                                 }
                                                          }
                                                }
                                                else
                                                {
                                                         key_return = temp;  //按键抬起,产生一次click操作
                             key_state_buffer1 = key_state_0;  //转换到按键初始状态
                                                }
                       /* 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 == 0)||(key1 == 0)||(key2==0)||(key3==0)||(key4==0)||(key5==0)||(key6==0)) //按键释放
                                key_state_buffer1 = key_state_3;  //切回按键初始状态
                                                 else //按键释放
                                key_state_buffer1 = key_state_0;  //切回按键初始状态
                        break;
        }
        return key_return;
}
回复

使用道具 举报

ID:1081244 发表于 2023-5-31 23:17 | 显示全部楼层
笑死,那为什么不干脆点弄计数中断,你这样显的有点业余,单片机本身就有计数功能
回复

使用道具 举报

ID:1080466 发表于 2023-6-1 21:38 | 显示全部楼层
可以定义一个变量,通过取余数的方法来判断会比较方便
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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