搜索
bottom↓
回复: 2

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

[复制链接]

出0入0汤圆

发表于 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?这个是什么意思?

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

曾经有一段真挚的爱情摆在我的面前,我没有珍惜,现在想起来,还好我没有珍惜……

出0入264汤圆

发表于 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 时候表示按键释放了
长按, 连发 同理。              

出0入0汤圆

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

本版积分规则

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

GMT+8, 2024-8-26 12:43

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

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