按键扫描程序2

#ifndef __MULTI_BUTTON_H_
#define __MULTI_BUTTON_H_

#include <REGX52.H>
#include "string.h"

//According to your need to modify the constants.
#define TICKS_INTERVAL    5 //ms
#define DEBOUNCE_TICKS    3 //MAX 8
#define SHORT_TICKS       (300  / TICKS_INTERVAL)
#define LONG_TICKS        (1000 / TICKS_INTERVAL)
#define LONG_HOLD_CYC     (500 / TICKS_INTERVAL)

#define ACTIVE_LEVEL 0


#define BTN0  P0_0
#define BTN1  P1_3
#define BTN2  P2_4
#define BTN3  P3_6
#define BTN4  P3_0
#define BTN5  P2_3
#define BTN6  P1_4
#define BTN7  P3_5



typedef struct
{
    unsigned char lastPinValue;            /* 按键编号 */
    unsigned char PinValue;       /* 按键状态 */
    unsigned short Count;          /* 滤波器计数器 */
    unsigned short LongCount;     /* 长按计数器 */
    unsigned short LongTime;      /* 按键按下持续时间, 0表示不检测长按 */
    unsigned char State;          /* 按键当前状态(按下还是弹起) */
    unsigned char RepeatSpeed;    /* 连续按键周期 */
    unsigned short RepeatCount;    /* 连续按键计数器 */

    unsigned short DelayCount;    /* 延迟计数器,用于双击检测 */
    unsigned char ClickCount;     /* 单击次数 */
    int LastTime;       /* 上次按键时刻 */
} KEY_T;

#define KEY_FILTER_TIME         10
#define KEY_LONG_TIME           200  /* 单位10ms, 持续1秒,认为长按事件 */

#define KEY_DB_CLICK_TIME       25  /* 双击检测时长,单位ms */

#define KEY_MSG_STEP    6   /* 按键消息代码步长(每个键有几个事件代码,顺序排列) */
typedef enum
{
    KEY_NONE = 0,       /* 0 表示按键事件 */

    KEY_1_DOWN,         /* 1键按下 */
    KEY_1_UP,           /* 1键弹起单击 */
    KEY_1_LONG_DOWN,    /* 1键长按 */
    KEY_1_LONG_UP,      /* 1键长按后的弹起 */
    KEY_1_AUTO_UP,      /* 1键长按后自动发码 */
    KEY_1_DB_UP,        /* 1键双击 */

    KEY_2_DOWN,         /* 2键按下 */
    KEY_2_UP,           /* 2键弹起 */
    KEY_2_LONG_DOWN,    /* 2键长按 */
    KEY_2_LONG_UP,      /* 2键长按后的弹起 */
    KEY_2_AUTO_UP,      /* 2键长按后自动发码 */
    KEY_2_DB_UP,        /* 2键双击 */

    KEY_3_DOWN,         /* 3键按下 */
    KEY_3_UP,           /* 3键弹起 */
    KEY_3_LONG_DOWN,    /* 3键长按 */
    KEY_3_LONG_UP,      /* 3键长按后的弹起 */
    KEY_3_AUTO_UP,      /* 3键长按后自动发码 */
    KEY_3_DB_UP,        /* 3键双击 */

    KEY_4_DOWN,         /* 4键按下 */
    KEY_4_UP,           /* 4键弹起 */
    KEY_4_LONG_DOWN,    /* 4键长按 */
    KEY_4_LONG_UP,      /* 4键长按后的弹起 */
    KEY_4_AUTO_UP,      /* 4键长按后自动发码 */
    KEY_4_DB_UP,        /* 4键双击 */

    KEY_5_DOWN,         /* 5键按下 */
    KEY_5_UP,           /* 5键弹起 */
    KEY_5_LONG_DOWN,    /* 5键长按 */
    KEY_5_LONG_UP,      /* 5键长按后的弹起 */
    KEY_5_AUTO_UP,      /* 5键长按后自动发码 */
    KEY_5_DB_UP,        /* 5键双击 */

    KEY_6_DOWN,         /* 5键按下 */
    KEY_6_UP,           /* 5键弹起 */
    KEY_6_LONG_DOWN,    /* 5键长按 */
    KEY_6_LONG_UP,      /* 5键长按后的弹起 */
    KEY_6_AUTO_UP,      /* 5键长按后自动发码 */
    KEY_6_DB_UP,        /* 5键双击 */

    KEY_7_DOWN,         /* 5键按下 */
    KEY_7_UP,           /* 5键弹起 */
    KEY_7_LONG_DOWN,    /* 5键长按 */
    KEY_7_LONG_UP,      /* 5键长按后的弹起 */
    KEY_7_AUTO_UP,      /* 5键长按后自动发码 */
    KEY_7_DB_UP,        /* 5键双击 */

    KEY_8_DOWN,         /* 5键按下 */
    KEY_8_UP,           /* 5键弹起 */
    KEY_8_LONG_DOWN,    /* 5键长按 */
    KEY_8_LONG_UP,      /* 5键长按后的弹起 */
    KEY_8_AUTO_UP,      /* 5键长按后自动发码 */
    KEY_8_DB_UP,        /* 5键双击 */

} KEY_ENUM;


/* 按键FIFO用到变量 */
#define KEY_FIFO_SIZE 10
typedef struct
{
    unsigned char Buf[KEY_FIFO_SIZE]; /* 键值缓冲区 */
    unsigned char Read;               /* 缓冲区读指针1 */
    unsigned char Write;              /* 缓冲区写指针 */
} KEY_FIFO_T;

#ifdef __cplusplus
extern "C" {
#endif

void button_init(void);
void button_ticks(void);
unsigned char bsp_GetKey(void);

#ifdef __cplusplus
}
#endif

#endif
#include "q_button.h"

KEY_T s_tBtn;
KEY_FIFO_T s_tKey; /* 按键FIFO变量,结构体 */

void bsp_PutKey(unsigned char _KeyCode)
{
    s_tKey.Buf[s_tKey.Write] = _KeyCode;

    if (++s_tKey.Write >= KEY_FIFO_SIZE)
    {
        s_tKey.Write = 0;
    }
}

/*
*********************************************************************************************************
*    函 数 名: bsp_GetKey
*    功能说明: 从按键FIFO缓冲区读取一个键值。
*    形    参: 无
*    返 回 值: 按键代码
*********************************************************************************************************
*/
unsigned char bsp_GetKey(void)
{
    unsigned char ret;

    if (s_tKey.Read == s_tKey.Write)
    {
        return KEY_NONE;
    }
    //  else
    {
        ret = s_tKey.Buf[s_tKey.Read];

        if (++s_tKey.Read >= KEY_FIFO_SIZE)
        {
            s_tKey.Read = 0;
        }
        return ret;
    }
}

/**
  * @brief  初始化按钮结构体。
  * @param  pin_level: 读取连接按钮电平的函数指针。
  * @param  active_level: 按钮按下的电平。
  * @retval None
  */
void button_init(void)
{
    memset(&s_tBtn, 0, sizeof(KEY_T));
    //global_button.button_level = pin_level();
    s_tBtn.LongTime = KEY_LONG_TIME;         /* 长按时间 0 表示不检测长按键事件 */
    s_tBtn.Count = KEY_FILTER_TIME / 2;      /* 计数器设置为滤波时间的一半 */

}



// 读取GPIO口状态并映射到内存变量中的bit位
void read_gpio_status(unsigned char *status)
{
    // 读取所有8个GPIO口的状态,并将结果存储到内存变量中
    *status = 0;

    // 读取GPIO口状态的代码示例,需要根据实际情况进行修改
    if (P3_0 == ACTIVE_LEVEL)
    {
        // *status |= (1 << 0);
        *status = 1;
    }
    if (P3_1 == ACTIVE_LEVEL)
    {
        // *status |= (1 << 1);
        *status = 2;
    }
    if (P3_2 == ACTIVE_LEVEL)
    {
        // *status |= (1 << 2);
        *status = 3;
    }
    if (P3_3 == ACTIVE_LEVEL)
    {
        // *status |= (1 << 3);
        *status = 4;
    }
    if (P3_4 == ACTIVE_LEVEL)
    {
        // *status |= (1 << 4);
        *status = 5;
    }
    if (P3_5 == ACTIVE_LEVEL)
    {
        // *status |= (1 << 5);
        *status = 6;
    }
    if (P3_6 == ACTIVE_LEVEL)
    {
        // *status |= (1 << 6);
        *status = 7;
    }
    if (P3_7 == ACTIVE_LEVEL)
    {
        // *status |= (1 << 7);
        *status = 8;
    }


}


/**
  * @brief  按钮驱动核心函数,驱动状态机。
  * @retval None
  */


void button_ticks(void)
{
    if (bHalGetSysTick() % 10 == 0) /* 需要最小时间不要小于5ms,因为有print */
    {
        return;
    }
		
    read_gpio_status(&s_tBtn.PinValue);

    if (s_tBtn.PinValue)
    {
        if (s_tBtn.Count < KEY_FILTER_TIME)
        {
            s_tBtn.Count = KEY_FILTER_TIME;
        }
        else if (s_tBtn.Count < 2 * KEY_FILTER_TIME)
        {
            s_tBtn.Count++;
        }
        else
        {
            s_tBtn.lastPinValue = s_tBtn.PinValue - 1;

            if (s_tBtn.State == 0)
            {
                s_tBtn.State = 1;

                /* 发送按钮按下的消息 */
                bsp_PutKey((unsigned char)(KEY_MSG_STEP * s_tBtn.lastPinValue + KEY_1_DOWN));
            }

            if (s_tBtn.LongTime > 0)
            {
                if (s_tBtn.LongCount < s_tBtn.LongTime)
                {
                    /* 发送长按消息 */
                    if (++s_tBtn.LongCount == s_tBtn.LongTime)
                    {
                        s_tBtn.State = 2;

                        /* 键值放入按键FIFO */
                        bsp_PutKey((unsigned char)(KEY_MSG_STEP * s_tBtn.lastPinValue + KEY_1_LONG_DOWN));
                    }
                }
                else
                {
                    if (s_tBtn.RepeatSpeed > 0)
                    {
                        if (++s_tBtn.RepeatCount >= s_tBtn.RepeatSpeed)
                        {
                            s_tBtn.RepeatCount = 0;
                            /* 常按键后,每隔10ms发送1个按键弹起事件 */
                            bsp_PutKey((unsigned char)(KEY_MSG_STEP * s_tBtn.lastPinValue + KEY_1_AUTO_UP));
                        }
                    }
                }
            }
        }
    }
    else
    {
        if (s_tBtn.Count > KEY_FILTER_TIME)
        {
            s_tBtn.Count = KEY_FILTER_TIME;
        }
        else if (s_tBtn.Count != 0)
        {
            s_tBtn.Count--;
        }
        else
        {
            if (s_tBtn.State != 0)
            {
                /* 2019-12-05 增加,第4个事件, 长按后的弹起 */
                if (s_tBtn.LongTime == 0)
                {
                    /* 发送短按弹起的消息 */
                    bsp_PutKey((unsigned char)(KEY_MSG_STEP * s_tBtn.lastPinValue + KEY_1_UP));
                }
                else
                {
                    if (s_tBtn.State == 2)
                    {
                        /* 发送长按弹起的消息 */
                        bsp_PutKey((unsigned char)(KEY_MSG_STEP * s_tBtn.lastPinValue + KEY_1_LONG_UP));
                    }
                    else
                    {
                        bsp_PutKey((unsigned char)(KEY_MSG_STEP * s_tBtn.lastPinValue + KEY_1_UP));  /* 单击弹起事件 */
                    }
                }
                s_tBtn.State = 0;
            }
        }

        s_tBtn.LongCount = 0;
        s_tBtn.RepeatCount = 0;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值