找回密码
 立即注册

QQ登录

只需一步,快速开始

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

双开关的问题,就是搞不清逻辑了~

  [复制链接]
ID:138119 发表于 2019-2-14 02:40 | 显示全部楼层 |阅读模式
某汽车玻璃升降器:
一个单刀双掷开关,KEY1,KEY2;
两个输出点OUT1,OUT2

不按:KEY1=1; KEY2=1;
轻按:KEY1=0; KEY2=1;
重按:KEY1=1; KEY2=0;

轻按到重按,或重按到轻按的切换过程中:KEY1=1; KEY2=1; 至少有几百毫秒时间。


程序OUT1、OUT2输出要求:

KEY1=0时,OUT1=1;
KEY2=0时,OUT1=1;OUT2=1;
由轻按到重按过程中,保持:OUT1=1;不能中断
重按到轻按的过程中,保持:OUT1=1;不能中断
不按下:OUT1=0;OUT2=0;

搞不清怎么写逻辑了~

请高手大侠们赐教!

回复

使用道具 举报

ID:433992 发表于 2019-2-14 10:31 来自手机 | 显示全部楼层
0 1:1 *  --- ---1 0:1 1--- ---1 1:0 0
回复

使用道具 举报

ID:378182 发表于 2019-2-14 10:45 | 显示全部楼层
OUT1=(NOT KEY1) OR (NOT KEY2)
OUT2=NOT KEY2
回复

使用道具 举报

ID:123289 发表于 2019-2-14 11:58 | 显示全部楼层
当一种开关组合被确认后,0.2秒内不再承认其它其它组合就可以了。
回复

使用道具 举报

ID:138119 发表于 2019-2-14 16:07 | 显示全部楼层
yzwzfyz 发表于 2019-2-14 11:58
当一种开关组合被确认后,0.2秒内不再承认其它其它组合就可以了。

并没有那么简单,
回复

使用道具 举报

ID:362076 发表于 2019-2-14 21:06 | 显示全部楼层
以下为个人愚见。
之所以设计切换过程有双高电平的短暂状态,是为了能够将轻按和重按的事件触发方式转换成两个下降沿中断来处理。这样一来,KEY1的下降沿说明为轻按事件,KEY2的下降沿为重按事件。
有了这两个事件,程序可以分为三个部分,分别是轻按中断服务函数,重按中断服务函数和主程序循环。
其中中断服务函数进行事件处理、状态转换,标志位切换等动作,主循环中使用标志位作为判断依据进行处理。
所以重新叙述要求并处理如下:
当轻按事件发生,置轻按事件发生标志位,同时清空重按事件发生标志位;
当重按事件发生,置重按事件发生标志位,同时清空轻按事件发生标志位。使得两个事件在主循环看来相互独立瞬时发生。
在主循环中判断,按照标志位状态进行“刷新覆盖式”输出,此时OUT1==1的输出一定不会中断(因为切换过程中,没有下降沿,程序保持上一状态对应输出刷新动作)。

这样,我们还需要对松开按键进行处理,因为按照描述,切换过程不算松开,所以松开的过程仅仅是轻按(KEY1==0,KEY2==1)到无按下(KEY1==1,KEY2==1)的过程,然而轻按无论到松开还是重按均需要经过双高电平。
这个过程我没有想到更好的办法,只能使用定时器进行固定时长计时,定时时长稍大于模式切换时长,定时开始于轻按事件处理结束,定时结束后根据当前输入决定是否清空轻按标志位。

评分

参与人数 2黑币 +102 收起 理由
yfpc2006 + 12 很给力!
admin + 90 回帖助人的奖励!

查看全部评分

回复

使用道具 举报

ID:138119 发表于 2019-2-15 03:27 | 显示全部楼层
本帖最后由 yfpc2006 于 2019-2-15 13:21 编辑
凌净清河 发表于 2019-2-14 21:06
以下为个人愚见。
之所以设计切换过程有双高电平的短暂状态,是为了能够将轻按和重按的事件触发方式转换成 ...

没有用中断,用查询的方法,能实现,但偶尔还是有些不稳定,看一下还需要优化什么?

u8 KEY1,KEY2,KEY1_F=0,KEY2_F=0,OUT1=0,OUT2=0,i=0;

void Scan_KEY(void)
{
        if(KEY1==1 && KEY2==1 && KEY1_F==0 && KEY2_F==0)
        {
                OUT1=0;
                OUT2=0;
        }
        else if(KEY1==0 && KEY2==1 && KEY1_F==0 && KEY2_F==0)
        {
                OUT1=1;
                OUT2=0;
                KEY1_F=1;
        }
        else if(KEY1==1 && KEY2==1 && KEY1_F==1 && KEY2_F==0)
        {
                for(i=0;i<50;i++)     //根据响应需求进行调节
                {
                        if(KEY2==0)
                        {
                                OUT2=1;
                                KEY2_F=1;
                                KEY1_F=0;
                                break;
                        }
                        delay_ms(10);      //根据响应需求进行调节
                }
                KEY1_F=0;
                OUT1=0;
        }
        else if(KEY2==0)
        {
                OUT1=1;
                OUT2=1;
                KEY2_F=1;
        }
        else if(KEY1==1 && KEY2==1 && KEY1_F==0 && KEY2_F==1)
        {
                OUT1=1;
                OUT2=0;
        }
        else if(KEY1==0 && KEY2==1 && KEY1_F==0 && KEY2_F==1)
        {
                OUT1=1;
                OUT2=0;
                KEY1_F=1;
        }
        else if(KEY1==1 && KEY2==1 && KEY1_F==1 && KEY2_F==1)
        {
                OUT1=0;
                OUT2=0;
                KEY1_F=0;
                KEY2_F=0;
        }
}

评分

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

查看全部评分

回复

使用道具 举报

ID:362076 发表于 2019-2-15 07:46 | 显示全部楼层
yfpc2006 发表于 2019-2-15 03:27
没有用中断,用查询的方法,能实现,但偶尔还是有些不稳定,看一下还需要优化什么?

u8 KEY1,KEY2,KE ...

中断的方法已经是最优解,你的查询法程序可能存在问题。
按照一个重按并松开的流程,KEY1、2电平变化为:
(KEY1、KEY2)11-01-11-10-11-01-11
根本不会出现同时为0的情况,所以KEY1==0&KEY2==0这条不可能满足。
况且查询法消耗的等待延时达到几百毫秒的话,太长了,建议改为中断,不然无可“优化”。
回复

使用道具 举报

ID:474232 发表于 2019-2-15 07:59 | 显示全部楼层
要优化!不管你是长按还是点按,都要有延时消抖,区别是延时时间不同而己
德飞莱150例有这个案例,坛子里有人发过,下下来看看,能解决你按键不稳定之症!

评分

参与人数 2黑币 +20 收起 理由
static + 5 赞一个!
sheng7533967 + 15 很给力!

查看全部评分

回复

使用道具 举报

ID:213173 发表于 2019-2-15 12:45 | 显示全部楼层
yfpc2006 发表于 2019-2-15 03:27
没有用中断,用查询的方法,能实现,但偶尔还是有些不稳定,看一下还需要优化什么?

u8 KEY1,KEY2,KE ...

无标题.jpg

#include <reg52.h>
#define key_S 5000 //预设延时计数值,根据响应需求进行调节
sbit KEY1=P2^0;
sbit KEY2=P2^1;
sbit OUT1=P3^0;
sbit OUT2=P3^1;

void Key_Scan()                        //按键扫描程序
{
        static unsigned int count_1=0,count_2=0;        //延时计数变量               

        if((KEY1==0)&&(KEY2==1))//轻按
        {
                if(++count_1>=key_S)//计数延时
                {
                        count_1=key_S;//防止溢出
                        OUT1=1;
                        OUT2=0;
                        count_2=0;
                }
        }
        else if((KEY1==1)&&(KEY2==0))//重按
        {
                if(++count_2>=key_S)//计数延时
                {
                        count_2=key_S;//防止溢出
                        OUT1=1;
                        OUT2=1;
                        count_1=0;
                }
        }   
        else //松手不按
        {
                OUT1=0;
                OUT2=0;
                count_1=0;
                count_2=0;
        }
}

void main()
{
        OUT1=0;
        OUT2=0;
        while(1)
        {
                Key_Scan();        //按键扫描
        }
}

评分

参与人数 1黑币 +12 收起 理由
yfpc2006 + 12 很给力!

查看全部评分

回复

使用道具 举报

ID:138119 发表于 2019-2-15 13:20 | 显示全部楼层
凌净清河 发表于 2019-2-15 07:46
中断的方法已经是最优解,你的查询法程序可能存在问题。
按照一个重按并松开的流程,KEY1、2电平变化为 ...

我也想用中断的方式,可惜芯片分配的引脚不支持外部电平变化中断。
所以只能用查询的方式。
回复

使用道具 举报

ID:362076 发表于 2019-2-15 15:59 | 显示全部楼层
yfpc2006 发表于 2019-2-15 13:20
我也想用中断的方式,可惜芯片分配的引脚不支持外部电平变化中断。
所以只能用查询的方式。

原来是这样,那祝你好运
回复

使用道具 举报

ID:474670 发表于 2019-2-15 16:36 | 显示全部楼层
yfpc2006 发表于 2019-2-15 13:20
我也想用中断的方式,可惜芯片分配的引脚不支持外部电平变化中断。
所以只能用查询的方式。

用定时中断作延时,在里面设标识位就行,就不存在引脚分配问题
回复

使用道具 举报

ID:472242 发表于 2019-2-15 18:16 | 显示全部楼层
yfpc2006 发表于 2019-2-15 13:20
我也想用中断的方式,可惜芯片分配的引脚不支持外部电平变化中断。
所以只能用查询的方式。

要学会用定时器中断,ADC中断这些技能做的开关,这样才是解决你多开关的麻烦
回复

使用道具 举报

ID:47286 发表于 2019-2-15 20:03 | 显示全部楼层
你这不是跟VW汽车上的电窗开关一样么 我写过整个电窗控制系统 就是3楼说的等待时间即可 不过得用中断 不能用死循环 不然其它事都干不了

不管你按不按键key2 都会经过key1 所以 key1按下并确定后 做一个标记 直接检测key1释放或者key2按下即可
回复

使用道具 举报

ID:476799 发表于 2019-2-15 22:59 | 显示全部楼层
znz43a 发表于 2019-2-14 10:45
OUT1=(NOT KEY1) OR (NOT KEY2)
OUT2=NOT KEY2

当一种开关组合被确认后,0.2秒内不再承认其它其它组合就可以了
回复

使用道具 举报

ID:138119 发表于 2019-2-16 19:48 | 显示全部楼层
dzbj 发表于 2019-2-15 20:03
你这不是跟VW汽车上的电窗开关一样么 我写过整个电窗控制系统 就是3楼说的等待时间即可 不过得用中断 不能 ...

我也觉得这个开关是小意思啦,可是实际做起来,不知道是不是自己的能力问题,觉得越做越复杂了。
回复

使用道具 举报

ID:138119 发表于 2019-2-16 20:07 | 显示全部楼层
wulin 发表于 2019-2-15 12:45
#include
#define key_S 5000 //预设延时计数值,根据响应需求进行调节
sbit KEY1=P2^0;

大哥哥就是厉害,小女子佩服的很!我都怀疑我是不是做这块的料!?

想到这里,我突然想到很久以前一个考试题,和这个开关很像也是一个单刀双掷开关,一共三个档位:
第一档(KEY1==1 && KEY2==1):关机;
第二档(KEY1==0 && KEY2==1):开风扇;
第三档(KEY1==1 && KEY2==0):开风扇+音乐;
第四档(KEY1==0 && KEY2==1):就是退回后的原第二档,开风扇+音乐+灯光;
第五档(KEY1==1 && KEY2==1):就是退回后的原第一档,关机。
我觉得都是不能做到的事情,看到大哥哥的仿真程序和效果,简直佩服死了!
如果大哥哥把这道题做出来,我会感动死的!
回复

使用道具 举报

ID:472325 发表于 2019-2-16 21:49 | 显示全部楼层
凌净清河 发表于 2019-2-15 15:59
原来是这样,那祝你好运。

妹子,妹子,楼主是妹子,别认错了

评分

参与人数 1黑币 +16 收起 理由
找人PK + 16

查看全部评分

回复

使用道具 举报

ID:138119 发表于 2019-2-16 22:04 | 显示全部楼层
dzbj 发表于 2019-2-15 20:03
你这不是跟VW汽车上的电窗开关一样么 我写过整个电窗控制系统 就是3楼说的等待时间即可 不过得用中断 不能 ...

单刀双掷(带关断)开关,能写出这几个开关状态来?

第0档(K1==1 && K2==1):FLAG=0;
第1档(K1==0 && K2==1):FLAG=1;
第2档(K1==1 && K2==0):FLAG=2;
第3档(K1==0 && K2==1):原第2档:FLAG=3;
第4档(K1==1 && K2==1):原第1档:FLAG=4;

换挡过程(K1==1 && K2==1)。
回复

使用道具 举报

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

本版积分规则

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

Powered by 单片机教程网

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