a_less 发表于 2013-3-30 15:38:08

有个按键程序不懂,懂得帮忙解释一下,谢谢

按键长按程序:
void KeyInit(void)
{
    io_key_1 = 1 ;
    io_key_2 = 1 ;
    io_key_3 = 1 ;
    io_key_4 = 1 ;            
}
根据按键硬件连接定义按键键值
#define KEY_VALUE_1            0x0e
#define KEY_VALUE_2            0x0d
#define KEY_VALUE_3                0x0b
#define KEY_VALUE_4                0x07
#define KEY_NULL                  0x0f
下面我们来编写按键的硬件驱动程序。
根据第一章所描述的按键检测原理,我们可以很容易的得出如下的代码:
static uint8 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 ;
}
其中io_key_1等是我们按键端口的定义,如下所示:
sbit io_key_1 = P3^0 ;
sbit io_key_2 = P3^1 ;
sbit io_key_3 = P3^2 ;
sbit io_key_4 = P3^3 ;

KeyScan()作为底层按键的驱动程序,为上层按键扫描提供一个接口,这样我们编写的上层按键扫描函数可以几乎不用修改就可以拿到我们的其它程序中去使用,使得程序复用性大大提高。同时,通过有意识的将与底层硬件连接紧密的程序和与硬件无关的代码分开写,使得程序结构层次清晰,可移植性也更好。对于单片机类的程序而言,能够做到函数级别的代码重用已经足够了。
在编写我们的上层按键扫描函数之前,需要先完成一些宏定义。
//定义长按键的TICK数,以及连_发间隔的TICK数
#define KEY_LONG_PERIOD      100
#define KEY_CONTINUE_PERIOD    25

//定义按键返回值状态(按下,长按,连_发,释放)
#define KEY_DOWN                0x80
#define KEY_LONG                  0x40
#define KEY_CONTINUE            0x20
#define KEY_UP                  0x10

//定义按键状态
#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

接着我们开始编写完整的上层按键扫描函数,按键的短按,长按,连按,释放等等状态的判断均是在此函数中完成。对照状态流程转移图,然后再看下面的函数代码,可以更容易的去理解函数的执行流程。完整的函数代码如下:

void GetKey(uint8 *pKeyValue)
{
    static uint8 s_u8KeyState = KEY_STATE_INIT ;
    static uint8 s_u8KeyTimeCount = 0 ;
    static uint8 s_u8LastKey = KEY_NULL ;//保存按键释放时候的键值
    uint8 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_LONG;
{
if(KEY_NULL!=(KEY_TEMP));
   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 ;
                  }
                }



其中KEYTEMP|=KEY_DOWN;按键按下是是意思?他是怎么检测按键再按下的?
他定义的状态返回值#define KEY_DOWN                0x80            这个0x80是什么意思?寄存器吗?KEYTEMP|=KEY_DOWN到时候表示如果按下键1的temp=10001000?这个是什么意思?

mcu_lover 发表于 2013-3-30 15:49:36

这个程序出处来自于我。替你解答。
KEYTEMP|=KEY_DOWN; 表示当前按键的按键事件产生。
#define KEY_DOWN                0x80
#define KEY_LONG                  0x40
#define KEY_CONTINUE            0x20
#define KEY_UP                  0x10

这些定义只是用一个位来保存相应的按键状态。
假设某个按键键值为0x01 ;
则按键值为 0x01 + KEY_DOWN   = 0x81 时候表示按键按下了
当检测到按键值为 0x01 + KEY_UP    = 0x11 时候表示按键释放了
长按, 连发 同理。            

a_less 发表于 2013-3-30 16:06:30

嘿嘿,原来原创者在这,那敢情好不懂我就上这个帖子发一下,让大哥给讲解讲。
if(KEY_NULL != (KeyTemp))
                  {
                        s_u8LastKey = KeyTemp ; //保存键值,以便在释放按键状态返回键值
                        KeyTemp |= KEY_DOWN ;//按键按下
                        s_u8KeyState = KEY_STATE_LONG ;

执行完,KeyTemp|=KEY_DOWN;
之后的这个语句s_u8Keystate=KEY_STATE_LONG; 是指向下一个case KEY_STATE_LONG吗?还是这个语句有其它用意?
页: [1]
查看完整版本: 有个按键程序不懂,懂得帮忙解释一下,谢谢