找回密码
 立即注册

QQ登录

只需一步,快速开始

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

C51单片机的按键复用控制两个灯

  [复制链接]
跳转到指定楼层
楼主
ID:326587 发表于 2018-8-30 20:57 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
50黑币
请大神帮帮忙,看下有的程序有什么问题
原想着用一个按键控制两个灯,短按控制第一个灯,长按控制第二个灯。现在长按的话,第二个灯能控制,也能影响第一个灯。这下不会改了

代码在2楼

最佳答案

查看完整内容

使用计数法识别长短按,给你改了一下,你试试。 #include #define key_S 1000 //宏定义短按(约20ms) #define key_L key_S*50 //宏定义长按(约1s) //定义端口 sbit KEY=P1^4; sbit LED1 = P2^0; sbit LED2 = P2^1; unsigned int count=0;//计数变量 int main (void) { LED1=1; LED2=1; KEY=1; //按键输入端口电平置高 while(1) //主循环 { if(!KEY) //如果检测到低电平,说 ...
分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏1 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:213173 发表于 2018-8-30 20:57 | 只看该作者

使用计数法识别长短按,给你改了一下,你试试。
#include<reg52.h>
#define key_S 1000 //宏定义短按(约20ms)
#define key_L key_S*50 //宏定义长按(约1s)
//定义端口
sbit KEY=P1^4;
sbit LED1 = P2^0;
sbit LED2 = P2^1;
unsigned int count=0;//计数变量

int main (void)
{
        LED1=1;
        LED2=1;               
        KEY=1; //按键输入端口电平置高       
        while(1)         //主循环
        {
                if(!KEY)  //如果检测到低电平,说明按键按下
                {  
                        count++;  
                        if(count==key_L)                                //长按
                                LED2=!LED2;
                        if(count>key_L)
                                count=key_L+1;                                //防止count溢出          
                }  
                else                                                                        //按键抬起
                {  
                        if(count>key_S && count<key_L)//短按
                                LED1=!LED1;
                        count=0;                                                        //count清0
                }   
        }
}

评分

参与人数 2黑币 +50 收起 理由
A142989 + 30 很给力!
admin + 20 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

板凳
ID:326587 发表于 2018-8-30 20:59 | 只看该作者
  1. #include<reg52.h>

  2. //定义端口
  3. sbit KEY=P1^4;
  4. sbit LED1 = P2^0;
  5. sbit LED2 = P2^1;

  6. void DelayUs2x(unsigned char t);//函数声明
  7. void DelayMs(unsigned char t);

  8. int main (void)
  9. {
  10. unsigned char num=0,key_press_num;
  11. LED1=1;
  12. LED2=1;               
  13. KEY=1; //按键输入端口电平置高

  14. while(1)         //主循环
  15.   {
  16.   if(!KEY)  //如果检测到低电平,说明按键按下
  17.     {
  18.          DelayMs(20); //延时去抖,一般10-20ms
  19.      if(!KEY)     //再次确认按键是否按下,没有按下则退出
  20.            {
  21.            while(!KEY)
  22.             {
  23.                 key_press_num++;
  24.         DelayMs(10);           //10x200=2000ms=2s
  25.                 if(key_press_num==200) //大约2s
  26.                         {
  27.                        //如果达到长按键标准
  28.                                //则进入长按键动作
  29.                //这里用于识别是否按
  30.                                                            //键还在按下,如果按
  31.                                              //下执行相关动作,否则退出                       
  32.                                 while(!KEY)
  33.                                 {
  34.                                        LED2=!LED2;
  35.                                         DelayMs(200);
  36.                                        
  37.                                 }
  38.                         }                       
  39.                 }
  40.                 LED1=!LED1;                               
  41.             }
  42.                   
  43.         }       
  44.   }
  45. }

  46. //uS延时函数
  47. void DelayUs2x(unsigned char t)
  48. {   
  49. while(--t);
  50. }

  51. //mS延时函数
  52. void DelayMs(unsigned char t)
  53. {
  54.      
  55. while(t--)
  56. {
  57.      //大致延时1mS
  58.      DelayUs2x(245);
  59.          DelayUs2x(245);
  60. }
  61. }
复制代码
回复

使用道具 举报

地板
ID:384109 发表于 2018-8-30 23:11 | 只看该作者
不应该用延时来判断按键时间,应该用定时器来记录按键按下的时间,再来判断是短按,还是长按

评分

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

查看全部评分

回复

使用道具 举报

5#
ID:390267 发表于 2018-8-31 01:24 | 只看该作者
试试我写的这个,看看行不行。我也是新手       

if(key_up==key_press)
        {
                Delay5ms(2);
                if(key_up==key_press)               
                {
                  hold_time=0;
                        while((key_up==key_press)&&(hold_time<20))
                        {
                                Delay5ms(10);
                                hold_time++;       
                        }
                        if((hold_time>1)&&(hold_time<=10))
                                        key_press_num=key_up_code;       
                        else if((hold_time>10)&&(hold_time<=20))
                                        key_press_num=key_down_code;       
                }
        }while(!key_up);

评分

参与人数 2黑币 +70 收起 理由
A142989 + 30 赞一个!
admin + 40 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

6#
ID:98526 发表于 2018-8-31 08:53 | 只看该作者
1、定义一个局部变量
2、长按之后将该标志位置为1
3、在松手之后判断该标志位是否为1
4、如果不为1,确认是短按松开、执行短按功能
5、如果为1,则是长按松开、不执行短按功能


6、按键不要用delay延时,可以在定义一个变量在定时器里面以1ms时基自加,按键函数每当该变量大于9即10ms扫描一次按键状态、如果按键按下将一个静态变量自加,,连续判断到5次以上200次以下是短按,判断到200次以上是长按,5次以下认为是抖动。

评分

参与人数 2黑币 +80 收起 理由
A142989 + 30 赞一个!
admin + 50 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

7#
ID:367460 发表于 2018-8-31 19:36 | 只看该作者
用延时判断的话 主要是防抖程序后面还要加一个判断   看按键是否离开  然后在读取键值

评分

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

查看全部评分

回复

使用道具 举报

8#
ID:363376 发表于 2018-9-1 10:28 | 只看该作者
用定时器记录按键的商家长短就可以了

评分

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

查看全部评分

回复

使用道具 举报

9#
ID:392273 发表于 2018-9-1 13:24 | 只看该作者
用定时器计数
循环判断
按下时计数器加一
抬起时判断计数器值,
        1 执行长按程序, 计数器清零,否则
        2执行短安程序, 计数器清零
否则空操作(去抖)

评分

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

查看全部评分

回复

使用道具 举报

10#
ID:358725 发表于 2018-9-2 22:14 | 只看该作者
根据你的程序思路来看存在一个无法解决的问题,那就是在下面这段程序中

  1.            while(!KEY)
  2.             {
  3.                 key_press_num++;
  4.         DelayMs(10);           //10x200=2000ms=2s
  5.                 if(key_press_num==200) //大约2s
  6.                         {
  7.                        //如果达到长按键标准
  8.                                //则进入长按键动作
  9.                //这里用于识别是否按
  10.                                                            //键还在按下,如果按
  11.                                              //下执行相关动作,否则退出                       
  12.                                 while(!KEY)
  13.                                 {
  14.                                        LED2=!LED2;
  15.                                         DelayMs(200);
  16.                                        
  17.                                 }
  18.                         }                        
  19.                 }
  20.                 LED1=!LED1;     
复制代码
                        

本来你设置为当按键没有释放时,就会进行计数,而不会点亮
LED1。

但是一旦计数值到达标准,LED2就会被点亮,然后延时0.2s,结束当前的while(!KEY)循环,由于程序BUG

1.如果按键仍然不释放LED2就会反复亮灭

2.或当按键释放while(!KEY)循环结束,程序循序执行LED1=!LED1

所以你的设计思路有点小问题

评分

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

查看全部评分

回复

使用道具 举报

11#
ID:358725 发表于 2018-9-2 22:31 | 只看该作者
加一个标志位就行了
#include<reg52.h>
//定义端口
sbit KEY=P1^4;
sbit LED1 = P2^0;
sbit LED2 = P2^1;
void DelayUs2x(unsigned char t);//函数声明
void DelayMs(unsigned char t);
int main (void)
{
unsigned char num=0,key_press_num,marker_bits;
LED1=1;
LED2=1;               
KEY=1; //按键输入端口电平置高
while(1)         //主循环
  {
  if(!KEY)  //如果检测到低电平,说明按键按下
    {
         marker_bits = 1;
         DelayMs(20); //延时去抖,一般10-20ms
     if(!KEY)     //再次确认按键是否按下,没有按下则退出
           {
           while(!KEY)
            {
                key_press_num++;
        DelayMs(10);           //10x200=2000ms=2s
                if(key_press_num==200) //大约2s
                        {
                       //如果达到长按键标准
                               //则进入长按键动作
               //这里用于识别是否按
                                                           //键还在按下,如果按
                                             //下执行相关动作,否则退出                       
                                while(!KEY)
                                {
                                       marker_bits =! marker_bits;
                                       LED2=!LED2;
                                        DelayMs(200);
                                       
                                }
                        }                        
                }
                if  (marker_bits)
                 {
                LED1=!LED1;
                  }                              
            }
                  
        }        
  }
}
//uS延时函数
void DelayUs2x(unsigned char t)
{   
while(--t);
}
//mS延时函数
void DelayMs(unsigned char t)
{
     
while(t--)
{
     //大致延时1mS
     DelayUs2x(245);
         DelayUs2x(245);
}
}



评分

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

查看全部评分

回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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