/*!
* @file BSP_KEY.c
*
* @brief 按键驱动文件
*
* @company
*
* @author 不咸不要钱
*
* @note 无
*
* @version
*
* @date 2019/10/18 星期五
*/
#include "bsp_key.h"
#include "lq_gpio.h"
#include "stdio.h"
static KEY_T xdata s_tBtn[KEY_COUNT];
static KEY_FIFO_T xdata s_tKey; /* 按键FIFO变量,结构体 */
static void bsp_InitKeyVar(void);
static void bsp_InitKeyHard(void);
static void bsp_DetectKey(uint8_t i);
static uint8_t IsKeyDown0(void) {P(C1_GPIO_PORT, C1_PIN) = 1; P(C2_GPIO_PORT, C2_PIN) = 1; P(C3_GPIO_PORT, C3_PIN) = 1; P(C4_GPIO_PORT, C4_PIN) = 0; if (P(R2_GPIO_PORT, R2_PIN) == 0) return 1;else return 0;}
static uint8_t IsKeyDown1(void) {P(C1_GPIO_PORT, C1_PIN) = 0; P(C2_GPIO_PORT, C2_PIN) = 1; P(C3_GPIO_PORT, C3_PIN) = 1; P(C4_GPIO_PORT, C4_PIN) = 1; NOP(50); if (P(R1_GPIO_PORT, R1_PIN) == 0) return 1;else return 0;}
static uint8_t IsKeyDown2(void) {P(C1_GPIO_PORT, C1_PIN) = 0; P(C2_GPIO_PORT, C2_PIN) = 1; P(C3_GPIO_PORT, C3_PIN) = 1; P(C4_GPIO_PORT, C4_PIN) = 1; if (P(R2_GPIO_PORT, R2_PIN) == 0) return 1;else return 0;}
static uint8_t IsKeyDown3(void) {P(C1_GPIO_PORT, C1_PIN) = 0; P(C2_GPIO_PORT, C2_PIN) = 1; P(C3_GPIO_PORT, C3_PIN) = 1; P(C4_GPIO_PORT, C4_PIN) = 1; if (P(R3_GPIO_PORT, R3_PIN) == 0) return 1;else return 0;}
static uint8_t IsKeyDown4(void) {P(C1_GPIO_PORT, C1_PIN) = 1; P(C2_GPIO_PORT, C2_PIN) = 0; P(C3_GPIO_PORT, C3_PIN) = 1; P(C4_GPIO_PORT, C4_PIN) = 1; if (P(R1_GPIO_PORT, R1_PIN) == 0) return 1;else return 0;}
static uint8_t IsKeyDown5(void) {P(C1_GPIO_PORT, C1_PIN) = 1; P(C2_GPIO_PORT, C2_PIN) = 0; P(C3_GPIO_PORT, C3_PIN) = 1; P(C4_GPIO_PORT, C4_PIN) = 1; if (P(R2_GPIO_PORT, R2_PIN) == 0) return 1;else return 0;}
static uint8_t IsKeyDown6(void) {P(C1_GPIO_PORT, C1_PIN) = 1; P(C2_GPIO_PORT, C2_PIN) = 0; P(C3_GPIO_PORT, C3_PIN) = 1; P(C4_GPIO_PORT, C4_PIN) = 1; if (P(R3_GPIO_PORT, R3_PIN) == 0) return 1;else return 0;}
static uint8_t IsKeyDown7(void) {P(C1_GPIO_PORT, C1_PIN) = 1; P(C2_GPIO_PORT, C2_PIN) = 1; P(C3_GPIO_PORT, C3_PIN) = 0; P(C4_GPIO_PORT, C4_PIN) = 1; if (P(R1_GPIO_PORT, R1_PIN) == 0) return 1;else return 0;}
static uint8_t IsKeyDown8(void) {P(C1_GPIO_PORT, C1_PIN) = 1; P(C2_GPIO_PORT, C2_PIN) = 1; P(C3_GPIO_PORT, C3_PIN) = 0; P(C4_GPIO_PORT, C4_PIN) = 1; if (P(R2_GPIO_PORT, R2_PIN) == 0) return 1;else return 0;}
static uint8_t IsKeyDown9(void) {P(C1_GPIO_PORT, C1_PIN) = 1; P(C2_GPIO_PORT, C2_PIN) = 1; P(C3_GPIO_PORT, C3_PIN) = 0; P(C4_GPIO_PORT, C4_PIN) = 1; if (P(R3_GPIO_PORT, R3_PIN) == 0) return 1;else return 0;}
static uint8_t IsKeyDown10(void) {P(C1_GPIO_PORT, C1_PIN) = 1; P(C2_GPIO_PORT, C2_PIN) = 1; P(C3_GPIO_PORT, C3_PIN) = 1; P(C4_GPIO_PORT, C4_PIN) = 0; NOP(50); if (P(R1_GPIO_PORT, R1_PIN) == 0) return 1;else return 0;}
static uint8_t IsKeyDown11(void) {P(C1_GPIO_PORT, C1_PIN) = 1; P(C2_GPIO_PORT, C2_PIN) = 1; P(C3_GPIO_PORT, C3_PIN) = 1; P(C4_GPIO_PORT, C4_PIN) = 0; if (P(R3_GPIO_PORT, R3_PIN) == 0) return 1;else return 0;}
/* 组合按键 key1 && key2 */
static uint8_t IsKeyDown12(void) { return IsKeyDown1() && IsKeyDown2();}
/*!
* @brief fifo初始化
*
* @param fifo_t : FIFO
*
* [url=home.php?mod=space&uid=266161]@return[/url] 无
*
* @note 无
*
* [url=home.php?mod=space&uid=8537]@see[/url] fifo_t tempFifo;
* fifo_init(tempFifo); //fifo初始化
*
* @date 2020/5/21
*/
void fifo_init(fifo_t *fifo)
{
fifo->fifoLen = 0;
fifo->fifoRead = 0;
fifo->fifoWrite = 0;
}
/*!
* @brief fifo压入数据
*
* @param fifo_t : FIFO
* @param data : 入栈数据
*
* @return 0 :成功 1 :失败
*
* @note FIFO_COVER 宏定义进行判断缓冲区满后的操作
*
* @see fifo_t tempFifo;
* fifo_push(tempFifo, 120); //fifo中压入一个数据
*
* @date 2020/5/21
*/
uint8_t fifo_push(fifo_t *fifo, FIFO_TYPE dat)
{
fifo->fifoLen++;
/* 判断缓冲区是否已满 */
if(fifo->fifoLen > FIFO_SIZE)
{
fifo->fifoLen = FIFO_SIZE;
#if FIFO_COVER
return 1;
#else
if(++fifo->fifoRead >= FIFO_SIZE)
{
fifo->fifoRead = 0;
}
#endif
}
fifo->buff[fifo->fifoWrite] = dat;
if(++fifo->fifoWrite >= FIFO_SIZE)
{
fifo->fifoWrite = 0;
}
return 0;
}
/*!
* @brief fifo弹出数据
*
* @param fifo_t : FIFO
* @param data : 出栈数据
*
* @return 0 :成功 1 :失败
*
* @note 无
*
* @see fifo_t tempFifo;
* FIFO_TYPE tempData;
* fifo_push(tempFifo, 120); //fifo中压入一个数据
* fifo_pop(tempFifo, &tempData); //fifo中弹出一个数据
*
* @date 2020/5/21
*/
uint8_t fifo_pop(fifo_t *fifo, FIFO_TYPE *dat)
{
/* 缓冲区为空 */
if(fifo->fifoLen == 0)
{
return 1;
}
fifo->fifoLen--;
*dat = fifo->buff[fifo->fifoRead];
if(++fifo->fifoRead >= FIFO_SIZE)
{
fifo->fifoRead = 0;
}
return 0;
}
/*
*********************************************************************************************************
* 函 数 名: bsp_InitKey
* 功能说明: 初始化按键. 该函数被 bsp_Init() 调用。
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void bsp_InitKey(void)
{
bsp_InitKeyVar(); /* 初始化按键变量 */
bsp_InitKeyHard(); /* 初始化按键硬件 */
}
/*
*********************************************************************************************************
* 函 数 名: bsp_PutKey
* 功能说明: 将1个键值压入按键FIFO缓冲区。可用于模拟一个按键。
* 形 参: _KeyCode : 按键代码
* 返 回 值: 无
*********************************************************************************************************
*/
void bsp_PutKey(uint8_t _KeyCode)
{
fifo_push(&s_tKey, _KeyCode);
}
/*
*********************************************************************************************************
* 函 数 名: bsp_GetKey
* 功能说明: 从按键FIFO缓冲区读取一个键值。
* 形 参: 无
* 返 回 值: 按键代码
*********************************************************************************************************
*/
uint8_t bsp_GetKey(void)
{
uint8_t xdata ret;
if (fifo_pop(&s_tKey, &ret) == 1)
{
return KEY_NONE;
}
else
{
return ret;
}
}
/*
*********************************************************************************************************
* 函 数 名: bsp_GetKeyState
* 功能说明: 读取按键的状态
* 形 参: _ucKeyID : 按键ID,从0开始
* 返 回 值: 1 表示按下, 0 表示未按下
*********************************************************************************************************
*/
uint8_t bsp_GetKeyState(KEY_ID_E _ucKeyID)
{
return s_tBtn[_ucKeyID].State;
}
/*
*********************************************************************************************************
* 函 数 名: bsp_SetKeyParam
* 功能说明: 设置按键参数
* 形 参:_ucKeyID : 按键ID,从0开始
* _LongTime : 长按事件时间
* _RepeatSpeed : 连发速度
* 返 回 值: 无
*********************************************************************************************************
*/
void bsp_SetKeyParam(uint8_t _ucKeyID, uint16_t _LongTime, uint8_t _RepeatSpeed)
{
s_tBtn[_ucKeyID].LongTime = _LongTime; /* 长按时间 0 表示不检测长按键事件 */
s_tBtn[_ucKeyID].RepeatSpeed = _RepeatSpeed; /* 按键连发的速度,0表示不支持连发 */
s_tBtn[_ucKeyID].RepeatCount = 0; /* 连发计数器 */
}
/*
*********************************************************************************************************
* 函 数 名: bsp_ClearKey
* 功能说明: 清空按键FIFO缓冲区
* 形 参:无
* 返 回 值: 按键代码
*********************************************************************************************************
*/
void bsp_ClearKey(void)
{
s_tKey.fifoRead = s_tKey.fifoWrite;
}
/*
*********************************************************************************************************
* 函 数 名: bsp_InitKeyHard
* 功能说明: 配置按键对应的GPIO
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
static void bsp_InitKeyHard(void)
{
//KEY 初始化
PIN_InitPushPull(C1_GPIO_PORT, C1_PIN);
PIN_InitPushPull(C2_GPIO_PORT, C2_PIN);
PIN_InitPushPull(C3_GPIO_PORT, C3_PIN);
PIN_InitPushPull(C4_GPIO_PORT, C4_PIN);
PIN_InitOpenDrain(R1_GPIO_PORT, R1_PIN);
PIN_InitOpenDrain(R2_GPIO_PORT, R2_PIN);
PIN_InitOpenDrain(R3_GPIO_PORT, R3_PIN);
}
/*
*********************************************************************************************************
* 函 数 名: bsp_InitKeyVar
* 功能说明: 初始化按键变量
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
static void bsp_InitKeyVar(void)
{
uint8_t xdata i;
/* 对按键FIFO读写指针清零 */
fifo_init(&s_tKey);
/* 给每个按键结构体成员变量赋一组缺省值 */
for (i = 0; i < KEY_COUNT; i++)
{
s_tBtn[i].LongTime = KEY_LONG_TIME; /* 长按时间 0 表示不检测长按键事件 */
s_tBtn[i].Count = KEY_FILTER_TIME / 2; /* 计数器设置为滤波时间的一半 */
s_tBtn[i].State = 0; /* 按键缺省状态,0为未按下 */
//s_tBtn[i].KeyCodeDown = 3 * i + 1; /* 按键按下的键值代码 */
//s_tBtn[i].KeyCodeUp = 3 * i + 2; /* 按键弹起的键值代码 */
//s_tBtn[i].KeyCodeLong = 3 * i + 3; /* 按键被持续按下的键值代码 */
s_tBtn[i].RepeatSpeed = 0; /* 按键连发的速度,0表示不支持连发 */
s_tBtn[i].RepeatCount = 0; /* 连发计数器 */
}
/* 判断按键按下的函数 */
s_tBtn[0].IsKeyDownFunc = IsKeyDown0;
s_tBtn[1].IsKeyDownFunc = IsKeyDown1;
s_tBtn[2].IsKeyDownFunc = IsKeyDown2;
s_tBtn[3].IsKeyDownFunc = IsKeyDown3;
s_tBtn[4].IsKeyDownFunc = IsKeyDown4;
s_tBtn[5].IsKeyDownFunc = IsKeyDown5;
s_tBtn[6].IsKeyDownFunc = IsKeyDown6;
s_tBtn[7].IsKeyDownFunc = IsKeyDown7;
s_tBtn[8].IsKeyDownFunc = IsKeyDown8;
s_tBtn[9].IsKeyDownFunc = IsKeyDown9;
s_tBtn[10].IsKeyDownFunc = IsKeyDown10;
s_tBtn[11].IsKeyDownFunc = IsKeyDown11;
/* 组合按键 */
s_tBtn[12].IsKeyDownFunc = IsKeyDown12;
}
/*
*********************************************************************************************************
* 函 数 名: bsp_DetectKey
* 功能说明: 检测一个按键。非阻塞状态,必须被周期性的调用。
* 形 参: 按键结构变量指针
* 返 回 值: 无
*********************************************************************************************************
*/
static void bsp_DetectKey(uint8_t i)
{
KEY_T xdata *pBtn;
/*
如果没有初始化按键函数,则报错
if (s_tBtn[i].IsKeyDownFunc == 0)
{
printf("Fault : DetectButton(), s_tBtn[i].IsKeyDownFunc undefine");
}
*/
pBtn = &s_tBtn[i];
if (pBtn->IsKeyDownFunc())
{
if (pBtn->Count < KEY_FILTER_TIME)
{
pBtn->Count = KEY_FILTER_TIME;
}
else if(pBtn->Count < 2 * KEY_FILTER_TIME)
{
pBtn->Count++;
}
else
{
if (pBtn->State == 0)
{
pBtn->State = 1;
/* 发送按钮按下的消息 */
bsp_PutKey((uint8_t)(3 * i + 1));
P27 = 1; //开启蜂鸣器
}
if (pBtn->LongTime > 0)
{
if (pBtn->LongCount < pBtn->LongTime)
{
/* 发送按钮持续按下的消息 */
if (++pBtn->LongCount == pBtn->LongTime)
{
/* 键值放入按键FIFO */
bsp_PutKey((uint8_t)(3 * i + 3));
}
}
else
{
if (pBtn->RepeatSpeed > 0)
{
if (++pBtn->RepeatCount >= pBtn->RepeatSpeed)
{
pBtn->RepeatCount = 0;
/* 常按键后,每隔10ms发送1个按键 */
bsp_PutKey((uint8_t)(3 * i + 1));
}
}
}
}
}
}
else
{
if(pBtn->Count > KEY_FILTER_TIME)
{
pBtn->Count = KEY_FILTER_TIME;
}
else if(pBtn->Count != 0)
{
pBtn->Count--;
}
else
{
if (pBtn->State == 1)
{
pBtn->State = 0;
/* 发送按钮弹起的消息 */
bsp_PutKey((uint8_t)(3 * i + 2));
P27 = 0; //关闭蜂鸣器
}
}
pBtn->LongCount = 0;
pBtn->RepeatCount = 0;
}
}
/*
*********************************************************************************************************
* 函 数 名: bsp_KeyScan
* 功能说明: 扫描所有按键。非阻塞,被systick中断周期性的调用
* 形 参: 无
* 返 回 值: 无
*********************************************************************************************************
*/
void bsp_KeyScan(void)
{
uint8_t xdata i;
for (i = 0; i < KEY_COUNT; i++)
{
bsp_DetectKey(i);
}
}