单片机按键状态机问题求解

[复制链接]
3958|6
 楼主| gxcmeluopeng 发表于 2013-3-13 18:03 | 显示全部楼层 |阅读模式
学习状态机遇到了问题,向论坛里的大牛求解,谢谢了!!!
#include<reg52.h>

#define uchar unsigned char
#define uint  unsigned int

#define KEY_VALUE_1              0xe0
#define KEY_VALUE_2              0xd0
#define KEY_VALUE_3              0xb0
#define KEY_VALUE_4              0x70
#define KEY_NULL                 0xf0

sbit io_key_1 = P3^4 ;
sbit io_key_2 = P3^5 ;
sbit io_key_3 = P3^6 ;
sbit io_key_4 = P3^7 ;

static uint KeyScan(void)
{
    if(io_key_1 == 0)return KEY_VALUE_1 ;
    if(io_key_2 == 0)return KEY_VALUE_2 ;
    if(io_key_3 == 0)return KEY_VALUE_3 ;
    if(io_key_4 == 0)return KEY_VALUE_4 ;
    return KEY_NULL ;
}
void KeyInit(void)
{
    io_key_1 = 1 ;
    io_key_2 = 1 ;
    io_key_3 = 1 ;
    io_key_4 = 1 ;            
}

#define KEY_LONG_PERIOD        100
#define KEY_CONTINUE_PERIOD    25

#define KEY_DOWN                0x08
#define KEY_LONG                0x04
#define KEY_CONTINUE            0x02
#define KEY_UP                  0x01

#define KEY_STATE_INIT            0
#define KEY_STATE_WOBBLE          1
#define KEY_STATE_PRESS           2
#define KEY_STATE_LONG            3
#define KEY_STATE_CONTINUE        4
#define KEY_STATE_RELEASE         5

unsigned char timer0_10ms_flag;

void GetKey(uint *pKeyValue)
{
    static uint s_u8KeyState = KEY_STATE_INIT ;
    static uint s_u8KeyTimeCount = 0 ;
    static uint s_u8LastKey = KEY_NULL ; //保存按键释放时候的键值
    uint KeyTemp = KEY_NULL;
    KeyTemp = KeyScan() ;        //获取键值
    switch(s_u8KeyState)
    {
        case KEY_STATE_INIT :
                {
                    if(KEY_NULL != (KeyTemp))
                    {
                        s_u8KeyState = KEY_STATE_WOBBLE ;
                    }
                }
        break ;
        case KEY_STATE_WOBBLE :      //消抖
                {
                    s_u8KeyState = KEY_STATE_PRESS ;   
                }
        break ;
        case KEY_STATE_PRESS :
                {
                    if(KEY_NULL != (KeyTemp))
                    {
                        s_u8LastKey = KeyTemp ; //保存键值,以便在释放按键状态返回键值
                        KeyTemp |= KEY_DOWN ; //按键按下
                        s_u8KeyState = KEY_STATE_LONG ;
                    }
                    else
                    {
                        s_u8KeyState = KEY_STATE_INIT ;
                    }
                }
        break ;
        case KEY_STATE_LONG :
                {
                    if(KEY_NULL != (KeyTemp))
                    {
                        if(++s_u8KeyTimeCount > KEY_LONG_PERIOD)
                        {
                            s_u8KeyTimeCount = 0 ;
                            KeyTemp |= KEY_LONG ; //长按键事件发生
                            s_u8KeyState = KEY_STATE_CONTINUE ;
                        }
                    }
                    else
                    {
                        s_u8KeyState = KEY_STATE_RELEASE ;
                    }
                }
        break ;
        case KEY_STATE_CONTINUE :
                {
                    if(KEY_NULL != (KeyTemp))
                    {
                        if(++s_u8KeyTimeCount > KEY_CONTINUE_PERIOD)
                        {
                            s_u8KeyTimeCount = 0 ;
                            KeyTemp |= KEY_CONTINUE ;
                        }
                    }
                    else
                    {
                        s_u8KeyState = KEY_STATE_RELEASE ;
                    }
                }
        break ;
        case KEY_STATE_RELEASE :
                {
                    s_u8LastKey |= KEY_UP ;
                    KeyTemp = s_u8LastKey ;
                    s_u8KeyState = KEY_STATE_INIT ;
                }
        break ;
        default : break ;
    }
    *pKeyValue= KeyTemp ; //返回键值   
}

void init()
{
        TH0=(65536-10000)/256;
        TL0=(65536-10000)%256;
        EA=1;
        ET0=1;
        TR0=1;       
}

void timer0() interrupt 1
{
        TH0=(65536-10000)/256;
        TL0=(65536-10000)%256;
        timer0_10ms_flag=1;
}
void mian()
{
        uint KeyValue=KEY_NULL;
        init();
        KeyInit();
        while(1)
        {
             Timer0MainLoop();
             KeyMainLoop(&KeyValue);
       
       
                if(KeyValue == (KEY_VALUE_1 | KEY_DOWN)) P1 = ~1 ;
       
             if(KeyValue == (KEY_VALUE_1 | KEY_LONG)) P1 = ~2 ;
       
             if(KeyValue == (KEY_VALUE_1 | KEY_CONTINUE)) { P1 ^= 0xf0;}
       
              if(KeyValue == (KEY_VALUE_1 | KEY_UP)) P1 = 0xa5 ;

        }
}
下面的两个函数怎么来的
Timer0MainLoop();
KeyMainLoop(&KeyValue);
具体的内容是什么??
向大牛求解。

       
一路向南 发表于 2013-3-14 20:56 | 显示全部楼层
这个程序是那位叫红金龙吸味的人写的,我用过他的这个程序。很好。。。
woshiaokeman 发表于 2013-7-4 22:52 | 显示全部楼层
帮顶起,我也疑惑!
woshiaokeman 发表于 2013-7-9 20:46 | 显示全部楼层
outstanding 发表于 2013-7-20 15:17 | 显示全部楼层
这个代码写的不错。。
zhj2015 发表于 2015-7-18 20:38 | 显示全部楼层
我也在纠结这个问题
gjbb163 发表于 2015-11-6 11:35 | 显示全部楼层
Timer0MainLoop();这个函数可能是忘记写了吧,
KeyMainLoop(&KeyValue);,&是取地址,这个函数的形参是指针形式的,就是将键值的地址取出来,在函数内将扫描的按键值直接写入地址中,这是地址操作,
您需要登录后才可以回帖 登录 | 注册

本版积分规则

4

主题

5

帖子

1

粉丝
快速回复 在线客服 返回列表 返回顶部