amoBBS 阿莫电子论坛

 找回密码
 注册
搜索
bottom↓
查看: 3259|回复: 39

请问马潮老师4个独立按键,带短按,支持长按怎么弄?书上只能一个按键的。

[复制链接]
发表于 2011-8-10 11:02:10 | 显示全部楼层 |阅读模式
请问马潮老师4个独立按键,带短按,支持长按怎么弄?
书上只能一个按键的。
342页有2个按键的程序,但不支持长按功能。
请马老师点拨下。
等待


//4。***342页,按键扫描函数代码
//原代码不理想,请改成如下:
unsigned char read_key(void)  
{  
    static unsigned char key_state = 0,key_old;  
    unsigned char key_press,key_return = key_no;  

    key_press = key_input & key_mask;        // 读按键I/O电平  
    switch (key_state)  
    {  
        case key_state_0:                    // 按键初始态  
            if (key_press != key_mask)  
            {  
                 key_old = key_press;        // 记录原电平                    
                 key_state = key_state_1;    // 键被按下,状态转换到键确认态   
            }               
            break;   
        case key_state_1:                    // 按键确认态  
            if (key_press == key_old)        // 与原电平比较(消抖处理)
            {  
                if (key_press == 0b01000000) key_return = key_k1;  
                else if (key_press == 0b10000000) key_return = key_k2;   
                key_state = key_state_2;        // 状态转换到键释放态  
            }  
            else  
                key_state = key_state_0;        // 按键已抬起,转换到按键初始态  
            break;  
        case key_state_2:  
            if (key_press == key_mask) key_state = key_state_0;  //按键已释放,转换到按键初始态  
            break;
    }  
    return key_return;  
}
发表于 2011-8-10 11:26:41 | 显示全部楼层
不知道这里是怎么消抖的
发表于 2011-8-10 12:07:30 | 显示全部楼层
回复【楼主位】jacky82512
请问马潮老师4个独立按键,带短按,支持长按怎么弄?
书上只能一个按键的。
342页有2个按键的程序,但不支持长按功能。
请马老师点拨下。
等待
//4。***342页,按键扫描函数代码  
//原代码不理想,请改成如下:  
unsigned char read_key(void)   
{   
    static unsigned char key_state = 0,key_old;   
    unsigned char key_press,key_return = key_no;   
    key_press = key_input & key_mask;        // 读按键i/o电平   
    switch (key_state)   
    {   
        case key_state_0:                  ......
-----------------------------------------------------------------------

学习,最关键的是真正掌握设计思想和方法,而不是单一的“程序”。书中287页开始介绍的“连_发”功能实现,就是“短”和“长”的例子。一个键和N个键,基本的思路和方法都是相同的。
 楼主| 发表于 2011-8-10 12:25:41 | 显示全部楼层
回复【1楼】lindabell  欧海
-----------------------------------------------------------------------

定时器实现的
 楼主| 发表于 2011-8-10 12:30:12 | 显示全部楼层
回复【2楼】machao  
-----------------------------------------------------------------------
那个是1个按键实现“短按”和“长按”的例子。
或许是我还没有体会其中的真谛。
还没有想到4个按键怎么弄。
正纳闷呢。
发表于 2011-8-10 12:55:49 | 显示全部楼层
回复【4楼】jacky82512
回复【2楼】machao   
-----------------------------------------------------------------------
那个是1个按键实现“短按”和“长按”的例子。
或许是我还没有体会其中的真谛。
还没有想到4个按键怎么弄。
正纳闷呢。

-----------------------------------------------------------------------

从你3、4楼的回答,可以说“针木有”体会其中的“真谛”。

一句定时器实现消抖,没有根本说到点上。

实际的产品系统是多样的,你使用4个键,别人可能是3个键。假如就是4个键,那么可能需要其中1、2、3或4个支持长按。没有一本书能把所有可能的代码都给出的。

因此,只有真正掌握最基本的思想和方法(也就是你说的“真谛”),才能举一反三,在实际中应用。

在我们目前的教学和学习的理念下,很难能掌握“真谛”,现在大家适应的是“应试教育”的那一套。动不动要求给个代码就是应试教育的体现。
 楼主| 发表于 2011-8-10 14:53:30 | 显示全部楼层
回复【5楼】machao  
-----------------------------------------------------------------------

感觉马老师的话对现在的教育很---;
那我现在改怎么办呢?怎么样做才能真正的理解了真谛。
才能够举一反三。
 楼主| 发表于 2011-8-10 14:57:52 | 显示全部楼层
回复【6楼】jacky82512  
-----------------------------------------------------------------------

只有真正掌握最基本的思想和方法(也就是你说的“真谛”),才能举一反三,在实际中应用。
看到了答案。
发表于 2011-8-10 15:17:34 | 显示全部楼层
实践出真知。
你把马老师程序跑一遍,建议加断点,甚至单步走,看看各寄存器、定时器都什么状态。
有了自己的理解,再试着改改。出了问题再来问,效率会高很多
 楼主| 发表于 2011-8-10 16:26:27 | 显示全部楼层
回复【8楼】packer  
-----------------------------------------------------------------------

莫非你也买了马老师的书。
发表于 2011-8-10 16:45:11 | 显示全部楼层
回复【8楼】packer
实践出真知。
你把马老师程序跑一遍,建议加断点,甚至单步走,看看各寄存器、定时器都什么状态。
有了自己的理解,再试着改改。出了问题再来问,效率会高很多
-----------------------------------------------------------------------

这并不是主要,学习我们这个专业的话,要求在基础学习时(数字逻辑、模拟电路、计算机原理)就应该“真正掌握最基本的思想和方法”。

这个是习惯问题。你没有这样的习惯,到上手学习AVR时才问如何才能“真正掌握最基本的思想和方法”,已经没有用了。
 楼主| 发表于 2011-8-10 16:51:26 | 显示全部楼层
回复【10楼】machao  
-----------------------------------------------------------------------
难道就没有任何的一个办法,让大脑形成一种思维方法。
马老师能不能将你主要的几个思想总结一下,
让论坛的人都受益呢。
给在黑暗中挣扎的人一点光明。
谢谢马老师,那么好的老师。

怎么形成好的“习惯”
发表于 2011-8-10 17:03:25 | 显示全部楼层
针对这个具体问题的解决方法是,把马老师书上的用状态机进行按键识别的状态图看懂,然后对这个状态图做从一个按键到N个按键的改进,再对照着这个状态图写代码。
 楼主| 发表于 2011-8-11 09:28:00 | 显示全部楼层
回复【12楼】ifree64  
-----------------------------------------------------------------------

感谢你。我将去试试看。谢谢你的良好建议
 楼主| 发表于 2011-8-11 11:03:50 | 显示全部楼层
”举一反三“出现了一个奇怪的问题。
短按可以的。
长按以后,目的也能实现,就是长按松开的时候,还会执行相应的短按一次操作。
正在找问题。
把代码付上,马老师帮忙看下。是啥问题。我估计那个地方。

//key define
#define key_input                    PIND                        // 按键输入口

#define key_mask                    0b11110000      // key_mask按键输入屏蔽码
//短按
#define key_no                        0
#define key_short_press_k1            1
#define key_short_press_k2            2
#define key_short_press_k3            3
#define key_short_press_k4            4

//long press长按
#define key_long_press_k1       5
#define key_long_press_k2       6
#define key_long_press_k3       7
#define key_long_press_k4       8

#define key_state_0                    0
#define key_state_1                    1
#define key_state_2                    2
#define key_state_3                    3


unsigned char read_key(void)
{
        static unsigned char key_state = 0, key_time = 0 ,key_old;
        unsigned char key_press, key_return = 0;

        key_press = key_input & key_mask;                // 读按键I/O电平,每一个10MS都要读IO电平是什么电平
        switch (key_state)
        {
                case key_state_0:                                    // 按键初始态
                        if (key_press != key_mask)      // 测试是否有按键按下(第一个10MS检测)
                        {
                            key_old = key_press;        // 记录原电平状态
                            key_state = key_state_1;        // 键被按下,状态转换到键确认态
                        }
                        break;
                case key_state_1:                                    // 按键确认态(第二个10MS检测)
                        if (key_press == key_old)       //
            {
                key_state = key_state_2;        // 按键仍按下,状态转换到计时1
                key_time = 0;                                // 清另按键时间计数器
            }
                        else
                            key_state = key_state_0;        // 按键已抬起,转换到按键初始态
                        break;
                case key_state_2:
                        if (key_press == key_mask)      // 按键已经抬起,利用key_old记录了IO电平的状态
            {
                key_state = key_state_0;        // 按键已释放,转换到按键初始态
                                if     (key_old == 0b01110000)  {key_return = key_short_press_k1;}//key_short_press_k1
                                else if(key_old == 0b10110000)  {key_return = key_short_press_k2;}
                                else if(key_old == 0b11010000)  {key_return = key_short_press_k3;}
                                else if(key_old == 0b11100000)  {key_return = key_short_press_k4;}
                //key_return = 1;                        // 输出"1"
                        }
                        else if (++key_time >= 100)                // 按键时间计数
                        {
                                key_state = key_state_3;        // 按下时间>1s,状态转换到计时2
                                key_time = 0;                                // 清按键计数器
                                if     (key_old == 0b01110000)  {key_return = key_long_press_k1;}//key_long_press_k1
                                else if(key_old == 0b10110000)  {key_return = key_long_press_k2;}
                                else if(key_old == 0b11010000)  {key_return = key_long_press_k3;}
                                else if(key_old == 0b11100000)  {key_return = key_long_press_k4;}
                                //key_return = 2;                        // 输出"2"
                        }
                        break;
                case key_state_3:
                        if (key_press)
                            key_state = key_state_0;    // 按键已释放,转换到按键初始态
                        else
                        {
                                if (++key_time >= 50)                // 按键时间计数
                                {
                                        key_time = 0;                        // 按下时间>0.5s,清按键计数器
                                    if     (key_old == 0b01110000)  {key_return = key_long_press_k1;}//key_long_press_k1
                                    else if(key_old == 0b10110000)  {key_return = key_long_press_k2;}
                                    else if(key_old == 0b11010000)  {key_return = key_long_press_k3;}
                                    else if(key_old == 0b11100000)  {key_return = key_long_press_k4;}
                                        //key_return = 2;                    // 输出"2"
                                }
                        }
                        break;
        }       
    return key_return;
}

//我估计是这里判断有问题,还不知道怎么解决。
if (key_press == key_mask)      // 按键已经抬起,利用key_old记录了IO电平的状态

马老师帮下忙看看
 楼主| 发表于 2011-8-11 11:06:39 | 显示全部楼层
为啥呢?马老师原来那个单个按键的长按,短按的都可以的。
 楼主| 发表于 2011-8-11 11:11:17 | 显示全部楼层

(原文件名:图像0868.jpg)

传个照片
 楼主| 发表于 2011-8-11 12:12:14 | 显示全部楼层
问题解决了。感谢马老师了。
发表于 2011-8-11 13:13:59 | 显示全部楼层
有2个问题
1、只有按下1秒后,才能从state2->state3,所以state3会在1+0.5秒后输出按键
2、state3的0.5秒会不停被执行


(原文件名:avr key.JPG)
发表于 2011-8-11 13:33:43 | 显示全部楼层
记号。
 楼主| 发表于 2011-8-11 15:32:04 | 显示全部楼层
回复【18楼】packer  
-----------------------------------------------------------------------

程序的目的就是此目的。
敢问这个状态图是用什么分析的,能否告知呢?我也想学习下这个分析的方法。
大侠QQ多少?
发表于 2011-8-11 16:08:15 | 显示全部楼层
回复【17楼】jacky82512
问题解决了。感谢马老师了。
-----------------------------------------------------------------------

既然已经解决了,那么是什么原因造成的问题应该交流的。仅索取就不上路了。
 楼主| 发表于 2011-8-11 16:11:40 | 显示全部楼层
case key_state_3:
if (key_press)  //这里的问题
    key_state = key_state_0;    // 按键已释放,转换到按键初始态


==>>

case key_state_3:
if (key_press==key_mask)  //
    key_state = key_state_0;    // 按键已释放,转换到按键初始态
 楼主| 发表于 2011-8-11 16:15:54 | 显示全部楼层
还想知道怎么做双击(连续单机2次),就像单击鼠标那样

还有连续单击N次(连续单机N次),比如连续单机PIND.7  10次,进入一个菜单或者做一件事情。怎么取实现呢?能提供例子或者资料啥的吗

怎么来实现?能否请马老师点拨下。

书上面有类似的例子吗?多少页
 楼主| 发表于 2011-8-12 14:24:21 | 显示全部楼层
现在在困难里挣扎呢,马老师帮下忙
发表于 2011-8-12 15:37:24 | 显示全部楼层
这个问题在我的栏目中有过讨论,首先你必须明白和彻底明确一个按键双(N)击的过程,正确的用状态图描述整个过程,然后才能开始程序的设计。

先分析简单的情况:一个按键实现双击的过程和定义(从考虑问题简单出发,此处不考虑短按还是长按,按下一次按键,不管长短,都算一击):

对于一个按键,如果定义了有双击功能,通常也就包含着单击的过程,那么在实际过程中,如何定义单击和双击的过程?关键点在于2次按键之间的时间间隔!假定定义2次按键间隔时间门限为500ms,那么:

第一次按键释放后,如果在500ms内没有再一次的按键,那么返回的就是单击按键值
如果在第一次按键释放后,在500ms内又出现了按键过程,那么返回的是双击按键值

你先从简单开始,进行设计。使用状态机的方法。
 楼主| 发表于 2011-8-12 16:02:34 | 显示全部楼层
回复【25楼】machao  
-----------------------------------------------------------------------

马老师,能否贴一个,一个按键的,单击,长按,双击(或者N击)的状态图?供参考

请问下,马老师书上面的“连_发”是怎么击  按键? 即怎么操作按键

连_发是不是就是连续单击很多次?

//看过你在另外一个帖子的回复
楼上说的对,使用状态机的方法可以实现,但是这个回答并没有根本的解决问题:就是那些状态?如何确定,它们之间如何转换?

这个不是编程问题,而是首先你必须搞清楚和确定实际按键过程中单击、双击、长按、连_发之间的关系。

在这4个之间,首先要给出单击、双击的非常具体的定义,否则你是不能进入代码设计的。

lz提到了“关键是单击后,是不是要等到确定没有双击,才处理键”已经涉及到了关键点,问题是你所定义的“单击”是什么样的具体过程。什么情况下才会发生“双击”,这个过程又是如何定义的。

请先给出所谓的“单击”、“双击”、“长按”的具体描述,如果能说清楚了,才能进一步的考虑如何编程实现这些按键过程的判别和处理。


我来说下我理解的“单击”、“双击”、“长按”的具体描述,请马老师贴个状态参考下。或者一个按键的实现这3个功能的简单代码。相信很多人都在琢磨这个,等待马老师的答案。期待啊

“单击” 按一下,
“双击” 按1下后,500毫秒后紧接着 在按第二次
“N击”  按1下后,500毫秒后紧接着 在按第二次,500毫秒后紧接着 在按第3次,500毫秒后紧接着 在按第n次----
“长按” 是按下超过1S以上
 楼主| 发表于 2011-8-13 07:56:46 | 显示全部楼层
相当的期待啊
 楼主| 发表于 2011-8-13 12:52:07 | 显示全部楼层

(原文件名:图像0936.jpg)

昨天晚上又看了马老师的书,琢磨出一个图,请马老师指正。
 楼主| 发表于 2011-8-14 12:28:40 | 显示全部楼层
马老师不在线?
 楼主| 发表于 2011-8-15 11:22:12 | 显示全部楼层
马老师?
 楼主| 发表于 2011-8-15 12:43:53 | 显示全部楼层
神啊,救救我吧
 楼主| 发表于 2011-8-16 11:45:07 | 显示全部楼层
马老师怎么不来了呢?
 楼主| 发表于 2011-8-17 08:13:53 | 显示全部楼层
每次来看帖都抱有大的,解决问题的愿望,最近总是失望。
发表于 2011-8-21 11:35:59 | 显示全部楼层
老师对这种问题可能失望了吧。。。。
发表于 2011-12-5 18:15:17 | 显示全部楼层
mark
发表于 2011-12-5 18:20:20 | 显示全部楼层
回复【36楼】371278638
回复【16楼】jacky82512  
-----------------------------------------------------------------------
能否把你的这个程序代码给我参考一下。。。。。最近也遇见了类似的问题我的邮箱是371278638@qq.com!谢谢!
-----------------------------------------------------------------------

留下邮箱的可能要遭莫大封_杀喽。。。。注意安全啊。。。
发表于 2011-12-6 15:48:09 | 显示全部楼层
回复【38楼】ShawnLinson 昇
-----------------------------------------------------------------------

这这。。。。。。。OMG!
友情提示:标题不合格、重复发帖,将会被封锁ID。详情请参考:论坛通告:封锁ID、获得注册邀请码、恢复被封ID、投诉必读
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|阿莫电子论坛(原ourAVR/ourDEV) ( 公安备案:44190002001997(交互式论坛) 工信部备案:粤ICP备09047143号 )

GMT+8, 2019-9-18 22:47

阿莫电子论坛, 原"中国电子开发网"

© 2004-2018 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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