搜索
bottom↓
回复: 24

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

[复制链接]

出0入0汤圆

发表于 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;
}

阿莫论坛20周年了!感谢大家的支持与爱护!!

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2008-7-18 14:40:04 | 显示全部楼层
程序好象没看出什么问题。你先简化整个系统软件,就测试这个按键部分,看是硬件还是其它软件的影响。

出0入0汤圆

 楼主| 发表于 2008-7-18 16:55:09 | 显示全部楼层
好的,谢谢马老师!!!

出0入0汤圆

 楼主| 发表于 2008-7-19 08:46:08 | 显示全部楼层
马老师,你好,我把UP键的连_发功能去掉了,就不会有那种按键不响应的现象了,但我觉得UP键和DOWN键是一样的,为什么DOWN键就不会有这种现象,现在还是不得其解,郁闷的要命。

出0入0汤圆

发表于 2008-7-20 13:46:07 | 显示全部楼层
把PORTD的低四位都设置成输入方式上拉有效吗?

出0入0汤圆

 楼主| 发表于 2008-7-21 08:52:31 | 显示全部楼层
马老师,你好,我是这样设置低四位的
PORTD|=0X0F;
DDRD&=~0X0F;

出0入0汤圆

发表于 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有问题,是输入信号的问题。

出0入0汤圆

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

出210入8汤圆

发表于 2008-7-23 09:30:41 | 显示全部楼层
mark,以后用的上。

出0入0汤圆

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

出0入0汤圆

发表于 2008-7-23 11:45:24 | 显示全部楼层
根据你讲的情况,我估计可能是引脚接触不良问题(是焊接的吗?排除假焊、虚焊等。如果是贴片,PCB弯一弯,或稍微重按芯片就好了等)。

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

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

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

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

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

出0入0汤圆

 楼主| 发表于 2008-7-23 13:11:34 | 显示全部楼层
我用的是你的实验板,不是焊接的,是用锁槽,
如果我还是用原来那片单片机,我改一下IO口,比如改成PORTB,PORTA,PORTC,结果还是一样,
纳闷了,不过我还是会去慢慢找,直到找出原因为止。
谢谢马老师!!!!

出0入0汤圆

发表于 2008-7-23 14:09:18 | 显示全部楼层
那可能这块芯片本身不太好了。建议你换一片,如果再发生是再找原因。不要在这里化时间了。

出0入0汤圆

 楼主| 发表于 2008-7-23 15:12:29 | 显示全部楼层
是的,我换了,可以用了,可能买了水货。谢谢了!!

出0入0汤圆

发表于 2009-12-19 23:34:32 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-3-8 21:45:58 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-9-5 21:07:30 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-9-29 20:27:42 | 显示全部楼层
mark

出10入210汤圆

发表于 2010-9-29 20:35:00 | 显示全部楼层
没有碰不到的问题,只有想不到的问题。

出0入0汤圆

发表于 2010-10-3 12:14:14 | 显示全部楼层
up与down的按键硬件对调一下,再程序对调一下,这不就检测出问题所在了吗?

出0入0汤圆

发表于 2010-11-30 17:16:11 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-12-9 13:47:57 | 显示全部楼层
回复【楼主位】harng
-----------------------------------------------------------------------

mark

出0入0汤圆

发表于 2012-2-27 16:44:20 | 显示全部楼层
mark

出0入0汤圆

发表于 2013-10-8 11:45:10 | 显示全部楼层
看不懂 哎

出0入0汤圆

发表于 2014-8-27 21:58:42 | 显示全部楼层
mark,谢谢!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-26 00:21

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

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