june2008 发表于 2010-7-3 11:02:12

马老师,麻烦给钦点一下,状态机按键,逼上绝路了!!

小弟的程序,基于状态机的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:43

先检查你连线有没有错误,再一个你的问题是什么?

dllgdx 发表于 2010-7-3 13:32:04

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

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


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

就这么搭配。

DFVX 发表于 2010-7-4 15:00:53

。。。不想说也没工夫看你程序

ba_wang_mao 发表于 2010-7-6 15:14:17

马老师的按键状态机如下:
    
    状态0:
       按键输出;
            NOP();
            NOP();
       按键输出;
            读键端口
          if (有按键按下)
                  转状态1
    状态1: 
       读键端口
          if (前后两次相同)
       {
                  置按键标志
                  转状态2,等等按键释放
               }
               else
         转状态0
    状态2:
       按键输出;       
            读键端口
       if (按键已经释放)---> 读到的按键值==NO_KEY
         转状态0   



    你仔细对照一下,程序是否和上面的状态机一致?  

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

状态机学习中

jhjkdz 发表于 2013-12-23 10:09:20

状态机学习。。。。

const_J 发表于 2014-2-11 09:13:49

有一个地方,我没看懂
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:00

const_J 发表于 2014-2-11 09:13
有一个地方,我没看懂
uchar get_key(void)
{


你先去学学static的用法吧

const_J 发表于 2014-2-12 09:45:27

sbk100 发表于 2014-2-11 14:25
你先去学学static的用法吧

哦,不好意思,没注意后面的      case 0:      
            if( KeyPress !=NO_KEY )
            {
            KeyState = 1;
                KeyPrev1= KeyPress;
            }
页: [1]
查看完整版本: 马老师,麻烦给钦点一下,状态机按键,逼上绝路了!!