amobbs.com 阿莫电子技术论坛

标题: 马老师,麻烦给钦点一下,状态机按键,逼上绝路了!! [打印本页]

作者: june2008    时间: 2010-7-3 11:02
标题: 马老师,麻烦给钦点一下,状态机按键,逼上绝路了!!
小弟的程序,基于状态机的4*4键盘,最简单的想按键弹起时返回键值,但是看了老久了,就是找不出毛病,麻烦给看看吧,快疯了!!!

#define uchar unsigned char
#define uint unsigned int

#define     NO_KEY           0x00

#define key_k1 '1'  
#define key_k2 '2'   
#define key_k3 '3'   
#define key_k4 '4'  
#define key_k5 '5'
#define key_k6 '6'
#define key_k7 '7'
#define key_k8 '8'
#define key_k9 '9'
#define key_k0 '0'
#define key_k10 'A'
#define key_k11 'B'
#define key_k12 'C'
#define key_k13 'D'
#define key_k14 'E'
#define key_k15 'F'

char Key_time_ok;

void initialize_timer(void)
{
     TCNT0=0x00; // {(0xff-0x70)+1}*1024*(1/14.7456MHz)=10ms
TCCR0=0x06; // 定时器0 prescaler=1024
TIMSK=0x01; // OCIE0=1,定时器0溢出标志
SREG = 0x80;          //使能全局中断
}

#pragma interrupt_handler timer0:17
void timer0(void)
{
  TCNT0=0x00;
  Key_time_ok=1;
}


uchar GetKeyCode(void)
{
        uchar i;
        DDRC=0xf0; //高4位输出,低4位输入
    PORTC=0x0f;//高4位输出0,低4位带上拉输入
    //delay_nms(1);
    waitsomeNOP();   //等待8个时钟周期(NOP)
    i=PINC&0x0f;      

    /*获取行地址*/
    DDRC=0x0f;//高4位输入,低4位输出
    PORTC=0xf0;//低4位输出0,高4位带上拉输入
    //delay_nms(1);
        waitsomeNOP();

    i|=PINC&0xf0;
return i;
}

uchar get_key(void)
{
    static char KeyState   = 0;        //按键状态
    static char KeyPrev1   = 0;        //上一次按键
static char KeyPrev    = 0;        //新一次按键
     
    char KeyPress  = NO_KEY;           //按键值
    char KeyReturn = NO_KEY;           //按键返回值  
   
    KeyPress = GetKeyCode();
         
    switch(KeyState)
    {
        //按键初始态00
        case 0:      
            if( KeyPress !=NO_KEY )  
            {  
                KeyState = 1;
KeyPrev1  = KeyPress;
            }
            break;
        //按键确认态01
        case 1:
            if( KeyPress !=NO_KEY  )  
            {
                //与上次按键不同,是乱码
                if(KeyPrev1  != KeyPress)
                {
                    KeyState  = 0;
                }
                else
                {
                    KeyState  = 2;
        switch (KeyPress)                        // 与状态1的相同,确认按键  
                        {              // 键盘编码,返回编码值   
                           case 0Xdb: KeyPrev = key_k0; break;
   case 0X77: KeyPrev = key_k1; break;
                           case 0X7b: KeyPrev = key_k2; break;   
                           case 0X7d: KeyPrev = key_k3; break;   
                           case 0X7e: KeyPrev = key_k4; break;  
                           case 0Xb7: KeyPrev = key_k5; break;
                           case 0Xbb: KeyPrev = key_k6; break;
                           case 0Xbd: KeyPrev = key_k7; break;
                           case 0Xbe: KeyPrev = key_k8; break;
                           case 0Xd7: KeyPrev = key_k9; break;
                           case 0Xdd: KeyPrev = key_k10;break;
                           case 0Xde: KeyPrev = key_k11;break;
                           case 0Xe7: KeyPrev = key_k12;break;
                           case 0Xeb: KeyPrev = key_k13;break;
                           case 0Xed: KeyPrev = key_k14;break;
   case 0Xee: KeyPrev = key_k15;break;
   default :break;
                        }  
}
            }
            else
            {//按键抬起,是抖动,不响应按键
                KeyState = 0;
            }
            break;
            
     
        //按键释放态10
        case 2:
            if(KeyPress == NO_KEY )  
            {
                KeyState   = 0;
                KeyReturn  =  KeyPrev;             //返回按键抬起值
            }   
            break;

        default :break;
    }
return KeyReturn;
}

void main()
{
  initialize_timer();
  while(1)
     {
       Uchar MMtemp;
       if(Key_time_ok==1)
          {
            Key_time_ok=0;
    MMtemp=get_key();           //有按键按下时
   
    if(MMtemp=='1')
      {
    sendbyte(0xff);  
  }

          }
    }
}
作者: monsoonw    时间: 2010-7-3 13:17
先检查你连线有没有错误,再一个你的问题是什么?
作者: dllgdx    时间: 2010-7-3 13:32
回复【楼主位】june2008
-----------------------------------------------------------------------

马老师,小弟的程序………………


马老大,学生的程序………………

就这么搭配。
作者: DFVX    时间: 2010-7-4 15:00
。。。不想说  也没工夫看你程序
作者: ba_wang_mao    时间: 2010-7-6 15:14
马老师的按键状态机如下:
    
    状态0:
       按键输出;
              NOP();
              NOP();
       按键输出;
              读键端口
          if (有按键按下)
                  转状态1
    状态1: 
       读键端口
          if (前后两次相同)
       {
                  置按键标志
                  转状态2,等等按键释放
               }
               else
         转状态0
    状态2:
       按键输出;       
              读键端口
       if (按键已经释放)  ---> 读到的按键值==NO_KEY
         转状态0   



    你仔细对照一下,程序是否和上面的状态机一致?  
作者: 金牛AKI    时间: 2013-10-8 11:47
状态机学习中
作者: jhjkdz    时间: 2013-12-23 10:09
状态机学习。。。。
作者: const_J    时间: 2014-2-11 09:13
有一个地方,我没看懂
uchar get_key(void)
{
    static char KeyState   = 0;        //按键状态
    static char KeyPrev1   = 0;        //上一次按键
static char KeyPrev    = 0;        //新一次按键
     
    char KeyPress  = NO_KEY;           //按键值
    char KeyReturn = NO_KEY;           //按键返回值  
   
    KeyPress = GetKeyCode();
         
    switch(KeyState)
    {
        //按键初始态00
        case 0:      
            if( KeyPress !=NO_KEY )  
            {  
                KeyState = 1;
KeyPrev1  = KeyPress;
            }

KeyState           初始化为0,之后没有被修改过。switch语句永远执行   case 0:      ,你再怎么按,都不会有反应
作者: sbk100    时间: 2014-2-11 14:25
const_J 发表于 2014-2-11 09:13
有一个地方,我没看懂
uchar get_key(void)
{

你先去学学static的用法吧
作者: const_J    时间: 2014-2-12 09:45
sbk100 发表于 2014-2-11 14:25
你先去学学static的用法吧

哦,不好意思,没注意后面的        case 0:      
            if( KeyPress !=NO_KEY )  
            {  
                KeyState = 1;
                KeyPrev1  = KeyPress;
            }





欢迎光临 amobbs.com 阿莫电子技术论坛 (https://www.amobbs.com/) Powered by Discuz! X3.4