jacky82512 发表于 2011-8-10 11:02:10

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

请问马潮老师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;
}

lindabell 发表于 2011-8-10 11:26:41

不知道这里是怎么消抖的

machao 发表于 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个键,基本的思路和方法都是相同的。

jacky82512 发表于 2011-8-10 12:25:41

回复【1楼】lindabell欧海
-----------------------------------------------------------------------

定时器实现的

jacky82512 发表于 2011-8-10 12:30:12

回复【2楼】machao
-----------------------------------------------------------------------
那个是1个按键实现“短按”和“长按”的例子。
或许是我还没有体会其中的真谛。
还没有想到4个按键怎么弄。
正纳闷呢。./emotion/em045.gif

machao 发表于 2011-8-10 12:55:49

回复【4楼】jacky82512
回复【2楼】machao   
-----------------------------------------------------------------------
那个是1个按键实现“短按”和“长按”的例子。
或许是我还没有体会其中的真谛。
还没有想到4个按键怎么弄。
正纳闷呢。./emotion/em045.gif

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

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

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

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

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

在我们目前的教学和学习的理念下,很难能掌握“真谛”,现在大家适应的是“应试教育”的那一套。动不动要求给个代码就是应试教育的体现。

jacky82512 发表于 2011-8-10 14:53:30

回复【5楼】machao
-----------------------------------------------------------------------

感觉马老师的话对现在的教育很---;
那我现在改怎么办呢?怎么样做才能真正的理解了真谛。
才能够举一反三。

jacky82512 发表于 2011-8-10 14:57:52

回复【6楼】jacky82512
-----------------------------------------------------------------------

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

packer 发表于 2011-8-10 15:17:34

实践出真知。
你把马老师程序跑一遍,建议加断点,甚至单步走,看看各寄存器、定时器都什么状态。
有了自己的理解,再试着改改。出了问题再来问,效率会高很多

jacky82512 发表于 2011-8-10 16:26:27

回复【8楼】packer
-----------------------------------------------------------------------

莫非你也买了马老师的书。

machao 发表于 2011-8-10 16:45:11

回复【8楼】packer
实践出真知。
你把马老师程序跑一遍,建议加断点,甚至单步走,看看各寄存器、定时器都什么状态。
有了自己的理解,再试着改改。出了问题再来问,效率会高很多
-----------------------------------------------------------------------

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

这个是习惯问题。你没有这样的习惯,到上手学习AVR时才问如何才能“真正掌握最基本的思想和方法”,已经没有用了。

jacky82512 发表于 2011-8-10 16:51:26

回复【10楼】machao
-----------------------------------------------------------------------
难道就没有任何的一个办法,让大脑形成一种思维方法。
马老师能不能将你主要的几个思想总结一下,
让论坛的人都受益呢。
给在黑暗中挣扎的人一点光明。
谢谢马老师,那么好的老师。

怎么形成好的“习惯”

ifree64 发表于 2011-8-10 17:03:25

针对这个具体问题的解决方法是,把马老师书上的用状态机进行按键识别的状态图看懂,然后对这个状态图做从一个按键到N个按键的改进,再对照着这个状态图写代码。

jacky82512 发表于 2011-8-11 09:28:00

回复【12楼】ifree64
-----------------------------------------------------------------------

感谢你。我将去试试看。谢谢你的良好建议

jacky82512 发表于 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电平的状态

马老师帮下忙看看

jacky82512 发表于 2011-8-11 11:06:39

为啥呢?马老师原来那个单个按键的长按,短按的都可以的。

jacky82512 发表于 2011-8-11 11:11:17

http://cache.amobbs.com/bbs_upload782111/files_44/ourdev_666456B483L4.jpg
(原文件名:图像0868.jpg)

传个照片

jacky82512 发表于 2011-8-11 12:12:14

问题解决了。感谢马老师了。

packer 发表于 2011-8-11 13:13:59

有2个问题
1、只有按下1秒后,才能从state2->state3,所以state3会在1+0.5秒后输出按键
2、state3的0.5秒会不停被执行

http://cache.amobbs.com/bbs_upload782111/files_44/ourdev_666512J8EZ8W.JPG
(原文件名:avr key.JPG)

bingshuihuo888 发表于 2011-8-11 13:33:43

记号。

jacky82512 发表于 2011-8-11 15:32:04

回复【18楼】packer
-----------------------------------------------------------------------

程序的目的就是此目的。
敢问这个状态图是用什么分析的,能否告知呢?我也想学习下这个分析的方法。
大侠QQ多少?

machao 发表于 2011-8-11 16:08:15

回复【17楼】jacky82512
问题解决了。感谢马老师了。
-----------------------------------------------------------------------

既然已经解决了,那么是什么原因造成的问题应该交流的。仅索取就不上路了。

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;    // 按键已释放,转换到按键初始态

jacky82512 发表于 2011-8-11 16:15:54

还想知道怎么做双击(连续单机2次),就像单击鼠标那样

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

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

书上面有类似的例子吗?多少页

jacky82512 发表于 2011-8-12 14:24:21

现在在困难里挣扎呢,马老师帮下忙

machao 发表于 2011-8-12 15:37:24

这个问题在我的栏目中有过讨论,首先你必须明白和彻底明确一个按键双(N)击的过程,正确的用状态图描述整个过程,然后才能开始程序的设计。

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

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

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

你先从简单开始,进行设计。使用状态机的方法。

jacky82512 发表于 2011-8-12 16:02:34

回复【25楼】machao
-----------------------------------------------------------------------

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

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

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

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

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

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

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

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


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

“单击” 按一下,
“双击” 按1下后,500毫秒后紧接着 在按第二次
“N击”按1下后,500毫秒后紧接着 在按第二次,500毫秒后紧接着 在按第3次,500毫秒后紧接着 在按第n次----
“长按” 是按下超过1S以上

jacky82512 发表于 2011-8-13 07:56:46

相当的期待啊

jacky82512 发表于 2011-8-13 12:52:07

http://cache.amobbs.com/bbs_upload782111/files_44/ourdev_667168V7S37W.jpg
(原文件名:图像0936.jpg)

昨天晚上又看了马老师的书,琢磨出一个图,请马老师指正。

jacky82512 发表于 2011-8-14 12:28:40

马老师不在线?

jacky82512 发表于 2011-8-15 11:22:12

马老师?

jacky82512 发表于 2011-8-15 12:43:53

神啊,救救我吧

jacky82512 发表于 2011-8-16 11:45:07

马老师怎么不来了呢?

jacky82512 发表于 2011-8-17 08:13:53

每次来看帖都抱有大的,解决问题的愿望,最近总是失望。

maopudi_love 发表于 2011-8-21 11:35:59

老师对这种问题可能失望了吧。。。。

Trylin 发表于 2011-12-5 18:15:17

mark

ShawnLinson 发表于 2011-12-5 18:20:20

回复【36楼】371278638
回复【16楼】jacky82512
-----------------------------------------------------------------------
能否把你的这个程序代码给我参考一下。。。。。最近也遇见了类似的问题我的邮箱是371278638@qq.com!谢谢!
-----------------------------------------------------------------------

留下邮箱的可能要遭莫大封_杀喽。。。。注意安全啊。。。

371278638 发表于 2011-12-6 15:48:09

回复【38楼】ShawnLinson 昇
-----------------------------------------------------------------------

./emotion/em014.gif./emotion/em014.gif这这。。。。。。。OMG!
页: [1]
查看完整版本: 请问马潮老师4个独立按键,带短按,支持长按怎么弄?书上只能一个按键的。