找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 5795|回复: 20
收起左侧

单片机如何检测K1,K2按键同时按下,触发LED反转,且不影响k1,与k2单独工作

  [复制链接]
ID:544423 发表于 2019-6-17 09:52 | 显示全部楼层 |阅读模式
2黑币
      单片机如何检测K1,K2同时按下,触发LED反转,且不影响k1,与k2单独工作

        if(k1==0)                  //检测按键K1是否按下
        {        
                delay(1000);   //消除抖动 一般大约10ms
                if((k1||k2)==0)
                {
                        led=~led;          //led状态取反
                }
        }


                  if(k1==0)                  //检测按键K1是否按下
                        {        
                                delay(1000);   //消除抖动 一般大约10ms
                                if(k1==0)         //再次判断按键是否按下
                                {
                                        led1=~led1;          //led1状态取反
                                }
                                while(!k1);         //检测按键是否松开
                        }
                        
                        if(k2==0)                  //检测按键K1是否按下
                        {        
                                delay(1000);   //消除抖动 一般大约10ms
                                if(k2==0)         //再次判断按键是否按下
                                {
                                        led2=~led2;          //led2状态取反
                                }
                                while(!k2);         //检测按键是否松开
                        }


回复

使用道具 举报

ID:564322 发表于 2019-6-17 10:51 | 显示全部楼层
if(k1==0)                  //检测按键K1是否按下
        {        
                delay(1000);   //消除抖动 一般大约10ms
                if(k2==0)
                {
                        led=~led;          //led状态取反
                }                 else    led1=~led1;
        }

if(k2==0)                  //检测按键K2是否按下
                        {        
                                delay(1000);   //消除抖动 一般大约10ms
                                if(k1==0)      
                                {
                                        led=~led;          //led2状态取反
                                }

                               else  led2=~led2;  
                        }
回复

使用道具 举报

ID:429136 发表于 2019-6-17 11:54 | 显示全部楼层
if(K1==0)  KEY=1;
if(K1==0)  KEY=2;
if(K1==0&&K2==0)  KEY=3;

消抖啥的自己加
回复

使用道具 举报

ID:544423 发表于 2019-6-17 14:52 | 显示全部楼层
Shayven 发表于 2019-6-17 11:54
if(K1==0)  KEY=1;
if(K1==0)  KEY=2;
if(K1==0&&K2==0)  KEY=3;

#include  "reg52.h"

typedef unsigned int u16;          //对数据类型进行声明定义
typedef unsigned char u8;

sbit k1=P3^1;         //定义P31口是k1
sbit k2=P3^0;         //定义P30口是k2
sbit led=P2^0;         //定义P20口是led
sbit led1=P2^1;         //定义P21口是led1
sbit led2=P2^2;         //定义P22口是led2

void delay(u16 i)
{
        while(i--);       
}

int key,linshizhi;

void keypros()
{
                 if(k1==0)                  //检测按键K1是否按下
        {        
                delay(1000);   //消除抖动 一般大约10ms
                if(k1==0)      
                {
                 key=1;         
                }  
        }

          if(k2==0)                  //检测按键K2是否按下
        {        
                delay(1000);   //消除抖动 一般大约10ms
                if(k2==0)      
                {
                   key=2;      
                }  
        }

                 if(k1==0&&k2==0)                  //检测按键K1,K2是否按下
        {        
            delay(1000);   //消除抖动 一般大约10ms
            if(k1==0&&k2==0)
            {
               key=3;      
            }      
        }
}

void xianshi()
{
   linshizhi=key;
   if(linshizhi==1){led=~led;}
   if(linshizhi==2){led1=~led1;}
   if(linshizhi==3){led2=~led2;}
   key=0;
}



void main()
{       
        while(1)
        {       
                keypros();  //按键处理函数
                xianshi();       
        }               
}
        实际实现不了


回复

使用道具 举报

ID:544423 发表于 2019-6-17 14:56 | 显示全部楼层
电子菜 发表于 2019-6-17 10:51
if(k1==0)                  //检测按键K1是否按下
        {        
                delay(1000);    ...

void keypros()
{
         if(k1==0)                  //检测按键K1是否按下
        {        
        delay(1000);   //消除抖动 一般大约10ms
                if(k2==0)
                {
                     led=~led;          //led状态取反
                }   else    led1=~led1;
        }

        if(k2==0)                  //检测按键K2是否按下
        {        
        delay(1000);   //消除抖动 一般大约10ms
                if(k1==0)      
                {
                led=~led;          //led2状态取反
                }  else  led2=~led2;               
        }               
}

   现象不理想
回复

使用道具 举报

ID:332444 发表于 2019-6-17 19:34 | 显示全部楼层
同时按下用“与逻辑”不是用“或逻辑”
回复

使用道具 举报

ID:517466 发表于 2019-6-17 22:46 | 显示全部楼层
楼主代码中的第一个判断中
if(k1==0)                  //检测按键K1是否按下
        {        
                delay(1000);   //消除抖动 一般大约10ms
                if((k1||k2)==0)
                {
                        led=~led;          //led状态取反
                }
        }
改成
if(k1==0 && k2==0)                  //检测按键K1和K2是否同时按下
        {        
                delay(1000);   //消除抖动 一般大约10ms
                if(k1==0 && k2==0)  //检测按键K1和K2是否同时按下
                {
                        led=~led;          //按键K1和K2同时按下, led状态取反
                }
        }
即可
回复

使用道具 举报

ID:544423 发表于 2019-6-18 06:40 | 显示全部楼层
与不是“&&”这个吗
回复

使用道具 举报

ID:56665 发表于 2019-6-18 08:13 | 显示全部楼层
你的程序K1 K2单独按下也可以使LED取反,两个同时按下也是,要用&&。
回复

使用道具 举报

ID:565305 发表于 2019-6-18 09:21 | 显示全部楼层
本帖最后由 egypt 于 2019-6-18 17:31 编辑

多两个变量,记录按住时间长度,不会阻塞其它流程,这种逻辑最简单了

int  k1_count=0, k2_count=0;  

while(1)
{        // 注意 int 在 16bit 机器上可能会超过 32768 变成负数所以下文有30000这个常数
     if(k1==0) { if(k1_count<30000) k1_count++; } else k1_count=0;
     if(k2==0) { if(k2_count<30000) k2_count++; } else k2_count=0;
     
     // 所谓同时按下,代表 k1_count 和 k2_count 都位于 10ms-20ms 之间(10ms的去抖时间)
     // 假设一个先按了20ms 还没松开,另外一个再按下,那就不叫同时,叫先后按下
     // 去抖可以通过连续性判断得到。k1_count 自加不满 10次(每ms算一次)那就是接触不好
     // 补充 k1_count k2_count 赋值是为了防止不停重入。可以根据实际情况自行调整合理方案
     if( k1_count>=10 && k1_count<20 && k2_count>=10 && k2_count<20)
     {    led=~led;
          k1_count=30000; k2_count=30000;
     }
     ... delay(1ms); ...
}
回复

使用道具 举报

ID:564322 发表于 2019-6-18 09:21 | 显示全部楼层
18796492606 发表于 2019-6-17 14:56
void keypros()
{
         if(k1==0)                  //检测按键K1是否按下

具体现象是什么?
回复

使用道具 举报

ID:565305 发表于 2019-6-18 10:28 | 显示全部楼层
我补充一下我回复的 10楼

*   关于去抖,回复中这种以连续性计时作为按下依据,并不是最好(分时间片1ms能否准时、以抖动第一次作为计时依据之类的前置条件等),但是误差也不大

*   关于人手按键,记忆中任天堂的游戏手柄有人可以按出17下每秒,一般人12-13下。两次按键间隔差不多有 60ms 吧

*   所以如果觉得代码中同时性条件太苛刻,可以把程序中 20 的数字改大,如 40 或 50 吧,以测试为准
回复

使用道具 举报

ID:564631 发表于 2019-6-18 16:20 | 显示全部楼层
加多一条 if(看)
回复

使用道具 举报

ID:564631 发表于 2019-6-18 16:21 | 显示全部楼层
if(k1==0&&k2==0)  led=~led;  主体内容就就是这样,加多一条就可以实现了
回复

使用道具 举报

ID:565305 发表于 2019-6-18 18:12 | 显示全部楼层
quanquan12 发表于 2019-6-18 16:21
if(k1==0&&k2==0)  led=~led;  主体内容就就是这样,加多一条就可以实现了

关键是判断 “同时按下瞬间”

如果 k1==0 和 k2==0 这样判断的话,按住 k1 和 k2 一个小时也会进 led 切换,按住一天也会进 led 切换的
回复

使用道具 举报

ID:452821 发表于 2019-6-18 18:56 | 显示全部楼层
18796492606 发表于 2019-6-17 14:52
#include  "reg52.h"

typedef unsigned int u16;          //对数据类型进行声明定义

这样不会一直在反转吗,看上去也就一直是亮的,你可以在按键的时候加一步没有按键按下的时候key为0,这样显示的时候只有检测到key为0之后的下一步才判断键值,不然不判断就不会一直反转看上去一直亮了
回复

使用道具 举报

ID:517466 发表于 2019-6-18 21:14 | 显示全部楼层
我的记忆中,消抖处理一般是20ms。
回复

使用道具 举报

ID:207421 发表于 2019-6-18 22:28 | 显示全部楼层
流程:
1. 判断K1
2. 判断K2
3. 判断K1和K2
以上逻辑都不通,按K1,后面的K2是执行不了的,当你K1执行成功了,那么两个按键同时按下,那就逻辑错误了,不可能跳过执行,用两个中断,配合时间间隙和标志位,可能行吧,很有可能还要用到GOTO
回复

使用道具 举报

ID:566255 发表于 2019-6-18 23:47 | 显示全部楼层
查一下相关书籍也可以
回复

使用道具 举报

ID:565305 发表于 2019-6-19 08:37 | 显示全部楼层
suncat0504 发表于 2019-6-18 21:14
我的记忆中,消抖处理一般是20ms。

要看楼主的按键是什么样的,便宜的软胶垫碳膜,印象中差异比较大,锅仔片的就好些

在示波器量一下波形可以大致看出要去抖的时间去这儿看看别人是怎么测试的吧:
https://blog.csdn.net/xu8023636/article/details/79219880
回复

使用道具 举报

ID:429136 发表于 2019-6-19 11:00 | 显示全部楼层
18796492606 发表于 2019-6-17 14:52
#include  "reg52.h"

typedef unsigned int u16;          //对数据类型进行声明定义

if(K1==0&&K2==0)  KEY=3;
else if(K1==0)  KEY=1;
else KEY=2;
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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