harng 发表于 2008-7-17 09:24:18

马老师,你好,帮我看看我的状态机按键,谢谢!!

马老师,你好,我碰到一个按键问题,百思不得其解,所以又来麻烦你了,我是看了你的书以后,用状态机写了一人非矩阵的按键扫描,大至情况是:UP键(可连_发),DOWN键(可连_发),ENTER键,ESC键,问题是:其它的键都好使,就是UP键为什么要按几下它才有反应呀,UP键和DOWN键都是一样的程序,为什么DOWN键就不会,我已经排除了硬件固障,更换了按键还是一样,所以我在想还是程序问题,一直不知怎么回事,所以请教,谢谢先!!
按键程序如下:
            /******************按键函数***********************************************/
#define key_input        PIND                        // 按键输入口
#define key_mask        0b00001111        // 按键输入屏蔽码
#define key_no                0
#define up                1
#define down        2
#define enter        3
#define esc          4
#define key_state_0        0
#define key_state_1        1
#define key_state_2        2
#define key_state_3 3
#define key_state_4 4
#define key_state_5 5
#define key_state_6 6
unsigned char key_time1=0,key_time2=0,key_return1;
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 == 0b00001110) //UP键检测
                                {
                                key_state = key_state_2; // 状态转换到键释放态
                               key_time1=0;
                               }
                                else if(key_press == 0b00001101) //DOWN键检测
                                {
                               key_state = key_state_3; // 状态转换到键释放态
                               key_time2=0;
                               }
                                else if (key_press == 0b00001011) //ENTER检测
                                {
                                key_return = enter;
                                key_state = key_state_6; // 状态转换到键释放态
                          }
                                else if (key_press == 0b00000111) //ESC键检测
                                {
                               key_return = esc;
                                key_state = key_state_6; // 状态转换到键释放态
                           }
            }
            else
                key_state = key_state_0;      // 按键已抬起,转换到按键初始态
            break;
                case key_state_2:
                  if(key_press ==key_mask)
                        {
                          key_state = key_state_0;
                                key_return=up;
                   }
                        else if(++key_time1>=100)
                        {
                        key_state=key_state_4;
                        key_time1=0;
                        key_return=7;//输出为7时产生连_发功能
                        }
                       
                       break;
                case key_state_3:
                  if(key_press ==key_mask)
                        {
                          key_state = key_state_0;
                                key_return=down;
                   }
                        else if(++key_time2>=100)
                        {
                        key_state=key_state_5;
                        key_time2=0;
                        key_return=8;//输出为8时产生连_发功能
                        }
                       
                       break;
      case key_state_4:
            if (key_press == key_mask) key_state = key_state_0;//按键已释放,转换到按键初始态
                        else
                        {
                          if(++key_time1>=50)//按键计数时间
                          {
                             key_time1=0;    //清按键计时
                               key_return=7;//输出为7时产生连_发功能
                          }
                          
                        }
            break;
                case key_state_5:
                     if(key_press=key_mask) key_state=key_state_0;
                       else if(++key_time2>=50)//按键计数时间
                          {
                             key_time2=0;    //清按键计时
                               key_return=8;//输出为8时产生连_发功能
                          }
                       
                       break;
                case key_state_6:
                     if (key_press == key_mask) key_state = key_state_0;
                  break;
    }
    return key_return;
}

machao 发表于 2008-7-18 14:40:04

程序好象没看出什么问题。你先简化整个系统软件,就测试这个按键部分,看是硬件还是其它软件的影响。

harng 发表于 2008-7-18 16:55:09

好的,谢谢马老师!!!

harng 发表于 2008-7-19 08:46:08

马老师,你好,我把UP键的连_发功能去掉了,就不会有那种按键不响应的现象了,但我觉得UP键和DOWN键是一样的,为什么DOWN键就不会有这种现象,现在还是不得其解,郁闷的要命。

machao 发表于 2008-7-20 13:46:07

把PORTD的低四位都设置成输入方式上拉有效吗?

harng 发表于 2008-7-21 08:52:31

马老师,你好,我是这样设置低四位的
PORTD|=0X0F;
DDRD&=~0X0F;

machao 发表于 2008-7-21 22:24:42

其它不变,改动以下一点:


if (key_press == 0b00001101)    //UP键检测 =======》UP和DOWN的输入换一下
{
key_state = key_state_2; // 状态转换到键释放态
key_time1=0;   
}
else if(key_press == 0b00001110) //DOWN键检测    ======》
{
key_state = key_state_3; // 状态转换到键释放态
key_time2=0;   
}

如果此时UP键不好,是程序有问题,如果是DOWN有问题,是输入信号的问题。

harng 发表于 2008-7-23 08:51:37

马老师,你好,非常感谢您在百忙之中能帮我解答问题
我已经按照您的要求改了一下,变成DOWN键有问题,如你所说是输入信号问题,我不知道输入信号是指哪点。
后来我改了一下key_time1>=100,把它改成key_time1>160,UP键就没问题了。
在后来我就程序没改,什么都没动,直接换了一片单片机,UP键一样好使,一点问题没有,我就奇怪了。
马老师,你能不能帮我讲讲这到底是怎么一回事呀。就上述两种改法。
谢谢!!!

csg0203 发表于 2008-7-23 09:30:41

mark,以后用的上。

harng 发表于 2008-7-23 11:22:15

马老师,你好,非常感谢您在百忙之中能帮我解答问题
我已经按照您的要求改了一下,变成DOWN键有问题,如你所说是输入信号问题,我不知道输入信号是指哪点。
后来我改了一下key_time1>=100,把它改成key_time1>160,UP键就没问题了。
在后来我就程序没改,什么都没动,直接换了一片单片机,UP键一样好使,一点问题没有,我就奇怪了。
马老师,你能不能帮我讲讲这到底是怎么一回事呀。就上述两种改法。
谢谢!!!
 

machao 发表于 2008-7-23 11:45:24

根据你讲的情况,我估计可能是引脚接触不良问题(是焊接的吗?排除假焊、虚焊等。如果是贴片,PCB弯一弯,或稍微重按芯片就好了等)。

因为程序不动,只是把D0定义由UP变成DOWN(0b00001110),那么DOWN就不正常了,问题很可能出在D0这个脚上。

换了芯片,D0接触好了,或原芯片的D0有问题(如受过电流冲击受过伤)。当然,你已经肯定有上拉了。

time的时间变化应该是假向,因为接触不好什么怪现象都会发生,而且是随机的。

如果是软件问题,不知道你的测试程序是否就只是这个按键代码,如果还有其它的功能代码,还使用了许多中断什么的,就比较复杂了。

因此找BUG,要首先要把你认为可能出问题的代码段独立出来单独调试,一个一个的都没有问题,再逐步合在一起调试。这个需要实践、经验、和时间的积累。

harng 发表于 2008-7-23 13:11:34

我用的是你的实验板,不是焊接的,是用锁槽,
如果我还是用原来那片单片机,我改一下IO口,比如改成PORTB,PORTA,PORTC,结果还是一样,
纳闷了,不过我还是会去慢慢找,直到找出原因为止。
谢谢马老师!!!!

machao 发表于 2008-7-23 14:09:18

那可能这块芯片本身不太好了。建议你换一片,如果再发生是再找原因。不要在这里化时间了。

harng 发表于 2008-7-23 15:12:29

是的,我换了,可以用了,可能买了水货。谢谢了!!

zyjclass 发表于 2009-12-19 23:34:32

mark

hexiantu 发表于 2010-3-8 21:45:58

mark

guxingganyue 发表于 2010-9-5 21:07:30

mark

yywin 发表于 2010-9-29 20:27:42

mark

rainbow 发表于 2010-9-29 20:35:00

没有碰不到的问题,只有想不到的问题。

hetiger 发表于 2010-10-3 12:14:14

up与down的按键硬件对调一下,再程序对调一下,这不就检测出问题所在了吗?

qink2008 发表于 2010-11-30 17:16:11

mark

qun453176385 发表于 2011-12-9 13:47:57

回复【楼主位】harng
-----------------------------------------------------------------------

mark

eleven_sue 发表于 2012-2-27 16:44:20

mark

金牛AKI 发表于 2013-10-8 11:45:10

看不懂 哎

ZYBing 发表于 2014-8-27 21:58:42

mark,谢谢!
页: [1]
查看完整版本: 马老师,你好,帮我看看我的状态机按键,谢谢!!