打印
[STM32F1]

求助各位坛友 如何实现一个按键按顺序执行三个功能呢

[复制链接]
4178|31
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
babyrabbit|  楼主 | 2018-4-12 10:15 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
具体就是下面5个按键有两个作为功能选择键,需要有三种功能。另外三个键作为个十百位按一下加1  0-9循环加  该如何实现呢?
我现在实现了单个按键的长按和短按的状态机扫描  接下来不知道该怎么改了
uint32_t GetKEY(void)

{   
    /* 获取KEY按键的输入电平状态,按键按下时为低电平0 */
    if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_9) == 0)
    {
          return KEY1_DOWN;
    }
   if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_0) == 0)
    {  
          return KEY2_DOWN;
    }
                if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_7) == 0)
    {      
          return KEY3_DOWN;
    }
                if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_6) == 0)
    {      
          return KEY4_DOWN;
    }
                if(GPIO_ReadInputDataBit(GPIOC,GPIO_Pin_1) == 0)
    {      
          return KEY5_DOWN;
    }                                                       
    return NO_KEY;
}

uint32_t ReadKeyStatus(void)
{
        static uint8_t KeyState = KEY_UP;//按键状态
        static uint8_t KeyPrev = NO_KEY; //上一次按键值
        uint8_t KeyPress = NO_KEY;                 //按键值
        uint8_t KeyReturn = KEY_UP;                 //返回按键状态
       
        KeyPress = GetKEY();//得到被按下的状态
       
        switch(KeyState)
        {
                //状态0:没有按键按下
                case KEY_UP:
                        if(KeyPress != NO_KEY)//有按键按下
                        {
                                KeyState = KEY_SURE;//转入状态1
                                KeyPrev = KeyPress;//记录按键值
                        }
                        break;
                //状态1:按键确认状态
                case KEY_SURE:
                        if(KeyPress == KeyPrev)//确认和上次相同
                        {
                                KeyState = KEY_DOWN;//转入状态2
                        }
                        else
                        {
                                KeyState = KEY_UP;//转入状态0
                        }
                        break;
                //状态2:按键按下
                case KEY_DOWN:
                        if(KeyPress != KeyPrev)//按键释放,端口高电平
                        {
                                KeyState = KEY_UP;//转入状态0
                                KeyReturn = KEY_DOWN | KeyPrev;//返回单次按下 或运算得到哪个按键处于什么状态
                        }
               
                        break;                
        }       
        return KeyReturn;
}


评论
babyrabbit 2018-4-13 15:05 回复TA
@xch :确实是 我做按键设置一个百位数时,每按键一次 加一,结果 而是连续加,估计是key-down,保持了10ms状态 如何使用状态机用定时器 精准消抖啊 
xch 2018-4-12 23:10 回复TA
@babyrabbit : 该消的没消,不必消的却消了。按键的感觉一定很差。 你应该在确认按键释放前消除抖动。确认按下则没必要消除抖动, 
babyrabbit 2018-4-12 21:18 回复TA
@babyrabbit :采用状态机的形式 写的按键 
babyrabbit 2018-4-12 20:56 回复TA
@xch :这个程序是在中断中调用的,每隔10ms调用一次。中断程序没有贴出来。 
xch 2018-4-12 20:29 回复TA
@babyrabbit : 按键是极其不可靠的开关.你得加上消除抖动程序. 需要使用定时器中断.在中断之中处理按键 
babyrabbit 2018-4-12 19:56 回复TA
@xch :我是做来用的,请问大神有什么使用的按键检测程序吗,拿来学习一下。 
xch 2018-4-12 16:54 回复TA
这个按键检测软件太像做作业。离实用还差很多 
沙发
kingkits| | 2018-4-12 10:42 | 只看该作者
组合键可以是这样:
KEY1 + KEY1
KEY1 + KEY2
KEY2 + KEY2
KEY2 + KEY1
可以用一个字节来表示:
组合键可以是这样:
KEY1 + KEY1   0B0000 0000
KEY1 + KEY2   0B0000 1111
KEY2 + KEY2   0B1111 1111
KEY2 + KEY1   0B1111 0000

使用特权

评论回复
板凳
babyrabbit|  楼主 | 2018-4-12 11:07 | 只看该作者
kingkits 发表于 2018-4-12 10:42
组合键可以是这样:
KEY1 + KEY1
KEY1 + KEY2

这个怎么用呢?我现在想实现对一个按键,按下三次,每次实现的功能不同:按下一次,开始采集,再按一次,开始加热,再按一次,开始显示;对另一个按键按一下加1,按到9后下一次回0  主要是这两种按键处理

使用特权

评论回复
地板
蝴蝶泉2018| | 2018-4-12 11:27 | 只看该作者
babyrabbit 发表于 2018-4-12 11:07
这个怎么用呢?我现在想实现对一个按键,按下三次,每次实现的功能不同:按下一次,开始采集,再按一次, ...

一个按键要三种状态,必须要有提示呀,有LED没?

使用特权

评论回复
5
fengfeng的恒| | 2018-4-12 11:30 | 只看该作者
babyrabbit 发表于 2018-4-12 11:07
这个怎么用呢?我现在想实现对一个按键,按下三次,每次实现的功能不同:按下一次,开始采集,再按一次, ...

用个变量作标记不就好了,识别到第一按下记1,执行动作1,再次按下+1,执行动作2,以此类推。

使用特权

评论回复
6
babyrabbit|  楼主 | 2018-4-12 13:22 | 只看该作者
本帖最后由 babyrabbit 于 2018-4-12 13:35 编辑
fengfeng的恒 发表于 2018-4-12 11:30
用个变量作标记不就好了,识别到第一按下记1,执行动作1,再次按下+1,执行动作2,以此类推。 ...

void key_Scan()
{               
                KEY = ReadKeyStatus();           
}
void key3()
{        
    static k=0;        
        
        if(k==0&&KEY==KEY2_ONE_DOWN)
        {
     n=444;
         led_on;
         }
    if(k==1&&KEY==KEY2_ONE_DOWN)
        {        
         n=111;               
        }
        if(k==2&&KEY==KEY2_ONE_DOWN)
        {        
        n=345;           
        }
        k++;
        if(k==3)k=0;        
}
其中n为数码管显示的值,把这两个函数放在定时器里,10ms扫一次,数码管也是用定时器做的。这样的问题是每次按完按键,n不完全是按照指定顺序执行,我猜想可能是扫的时间不匹配。请教大神该如何写 一个按键顺序执行三个功能的程序。

使用特权

评论回复
7
fengfeng的恒| | 2018-4-12 13:37 | 只看该作者
babyrabbit 发表于 2018-4-12 13:22
void key_Scan()
{               
                KEY = ReadKeyStatus();           

10ms扫一次每问题,关键是每次确定有按键按下了,K才+1啊,你现在这里每10ms都+1,那肯定不对啊。

使用特权

评论回复
8
kingkits| | 2018-4-12 13:42 | 只看该作者
uint8_t key1_val;
void key1_pused()
{
    key1_val = key1_val <<1;
    key1_val &= 0b00000111;
    ley1_val |= 1;
}
// first key1_val = b1
//second           = b11
// third                 b111

使用特权

评论回复
9
kingkits| | 2018-4-12 13:43 | 只看该作者
建议你还是去学校回回炉,这实在是有点差

使用特权

评论回复
10
sky.sun.zz| | 2018-4-12 14:02 | 只看该作者
babyrabbit 发表于 2018-4-12 11:07
这个怎么用呢?我现在想实现对一个按键,按下三次,每次实现的功能不同:按下一次,开始采集,再按一次, ...

设一个变量,每按一次按键变量加1,执行1个任务。你要执行100个都可以。何止3个?

使用特权

评论回复
11
babyrabbit|  楼主 | 2018-4-12 14:02 | 只看该作者
fengfeng的恒 发表于 2018-4-12 13:37
10ms扫一次每问题,关键是每次确定有按键按下了,K才+1啊,你现在这里每10ms都+1,那肯定不对啊。 ...

我之前写的是没按一次加1,但是也不行,
void key3()
{       
    static k=0;               
        if(k==0&&KEY==KEY2_ONE_DOWN)
        {
     n=444;
         k++;
         }
    if(k==1&&KEY==KEY2_ONE_DOWN)
        {       
         n=111;       
         k++;       
        }
        if(k==2&&KEY==KEY2_ONE_DOWN)
        {       
        n=345;
        k=0;          
        }
               
}
这样写的结果就是直接  显示345

使用特权

评论回复
评论
xch 2018-4-15 23:17 回复TA
第一个if 条件成立后,执行k++,没有return,这时第二个if条件 也满足,执行if后程序,k=2,这样第三个if条件也满足所以n=345. 漏了return 
12
babyrabbit|  楼主 | 2018-4-12 14:04 | 只看该作者
kingkits 发表于 2018-4-12 13:43
建议你还是去学校回回炉,这实在是有点差

现在就是学生一枚,每天就自己摸索,有什么好的学习方式和途径吗  求推荐

使用特权

评论回复
13
kingkits| | 2018-4-12 14:06 | 只看该作者
没啥,
就是多练,遇见过,解决了,就会了

使用特权

评论回复
14
fsdSADASDSA| | 2018-4-12 15:03 | 只看该作者
kingkits 发表于 2018-4-12 14:06
没啥,
就是多练,遇见过,解决了,就会了


使用特权

评论回复
15
mmuuss586| | 2018-4-12 20:57 | 只看该作者
既然有2个按键,1个作为功能切换键好了
按下切换功能

使用特权

评论回复
16
babyrabbit|  楼主 | 2018-4-12 21:22 | 只看该作者
sky.sun.zz 发表于 2018-4-12 14:02
设一个变量,每按一次按键变量加1,执行1个任务。你要执行100个都可以。何止3个? ...

我的程序就是设置了变量k,可是没次直接执行到第三个功能了,状态机里 是抬起按键有效,可是在key3程序里,按一下  直接数码管显示345了。不想想象中逻辑执行,每加一次,执行一个新功能。

使用特权

评论回复
17
1223657347| | 2018-4-13 09:28 | 只看该作者
单击、双击、长按(笑)

使用特权

评论回复
18
ranli55| | 2018-4-13 09:48 | 只看该作者
一个按键也可以弄出很多状态的 短按的时间 0.2 0.5 1  长按 2秒 3秒 5秒 ====  连按2次 3次===== 可以玩出很多花样

使用特权

评论回复
19
sky.sun.zz| | 2018-4-13 13:12 | 只看该作者
babyrabbit 发表于 2018-4-12 21:22
我的程序就是设置了变量k,可是没次直接执行到第三个功能了,状态机里 是抬起按键有效,可是在key3程序里 ...

可能你没有进行按键消抖所致。可以每次按键按下时读按键状态等待按键抬起再加1变量值。

使用特权

评论回复
20
simonliu009| | 2018-4-13 14:27 | 只看该作者
建议用Systick中断去抖,可以参考我的blog**,稍微改一下就能用了。
https://blog.csdn.net/toopoo/article/details/79717272

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

23

主题

88

帖子

3

粉丝