📄 keyfilt.c
字号:
*******************************************************************************/
#include "KEYFILT.h"
#define KEY_BUF_SIZE ((MAX_KEY_NUMS + 7) / 8) //按键状态缓冲区大小
#ifndef NULL
#define NULL (void *)0
#endif
static uint8 s_byKeyOrigin[KEY_BUF_SIZE]; //接收到的键盘状态
static uint8 s_byKeyFiltered[KEY_BUF_SIZE]; //滤波后的键盘状态
static const uint8 *s_pabyFilterTime; //指向用户定义的滤波常数表头
/*******************************************************************************
函数名: GetScanIndexItem
描 述: 得到索引项表的值,每项值占用2个位
调 用:
被调用: CreateMapTable
输 入: pbyBase : 索引项表头
wKeyIdx : 键盘索引号,初始索引为0
输 出: 无
返回值: 表中的值,占用2位
******************************************************************************/
static uint8 GetScanIndexItem(const uint8 *pbyBase, uint16 wKeyIdx)
{
uint8 byTmp;
uint8 byMask; //键值掩码
uint8 byShiftNums; //移位次数
byShiftNums = 2 * (wKeyIdx % 4);
byMask = (0x3 << byShiftNums);
byTmp = *(pbyBase + wKeyIdx / 4); //每个按键占用2个位
byTmp = (byTmp & byMask) >> byShiftNums;
return byTmp;
}
/*******************************************************************************
函数名: SetScanIndexItem
描 述: 设置索引项表中的值,每项值占用2个位
调 用:
被调用:
输 入: pbyBase : 索引项表头
wKeyIdx : 键盘索引号,初始索引为0
byValue : 设置值
输 出: pbyBase : 更改后的索引项表头
返回值: 无
******************************************************************************/
static void SetScanIndexItem(uint8 *pbyBase, uint16 wKeyIdx, uint8 byValue)
{
uint8 byTmp;
uint8 byMask; //键值掩码
uint8 byShiftNums; //移位次数
uint16 wOffAddr; //偏移地址
byShiftNums = 2 * (wKeyIdx % 4);
byMask = (0x3 << byShiftNums);
wOffAddr = (wKeyIdx / 4);
byValue &= 0x3; //只取低2位
byValue = (byValue << byShiftNums);
byTmp = *(pbyBase + wOffAddr);
byTmp &= ~byMask;
byTmp |= byValue;
*(pbyBase + wOffAddr) = byTmp;
}
/*******************************************************************************
函数名: KF_KeyFilt
描 述: 将读入的键盘状态进行滤波处理
调 用:
被调用:
输 入: wKeyNum :实际按钮数
输 出: s_byKeyFiltered :更改滤波后的键盘状态值
返回值: 无
******************************************************************************/
static void KF_KeyFilt(uint16 wKeyNums)
{
static uint8 s_byKeyCurTime[MAX_KEY_NUMS]; //存放递减的滤波数
static uint8 s_byKeyScanNum[KEY_BUF_SIZE * 2]; //保存键值扫描次数,
//每两位表示一个键
static uint8 s_byKeyValue[KEY_BUF_SIZE * 3]; //存放三次扫描得到的键值
static uint16 wI;
static uint8 byA, byB, byC;
static uint8 byIdx;
static uint8 *pbyTmp;
static uint8 byMask;
for(wI = 0; wI < wKeyNums; wI++)
{
if (s_byKeyCurTime[wI] == 0) //若滤波数到0,记录当前采集值
{
if (s_pabyFilterTime == NULL) //用户未传入滤波常数,使用缺省值
{
s_byKeyCurTime[wI] = DEFAULT_FILT_TIME;
}
else
{
s_byKeyCurTime[wI] = s_pabyFilterTime[wI]; //否则使用用户定义值
}
byIdx = GetScanIndexItem(s_byKeyScanNum, wI);
pbyTmp = s_byKeyValue + byIdx * KEY_BUF_SIZE + wI / 8;
byMask = (0x01 << (wI % 8));
if ((s_byKeyOrigin[wI / 8] & byMask) != 0)
{
*pbyTmp |= byMask;
}
else
{
*pbyTmp &= ~byMask;
}
if (++byIdx >= 3)
{
byIdx = 0;
}
SetScanIndexItem(s_byKeyScanNum, wI, byIdx);
}
if (s_byKeyCurTime[wI] > 0) //考虑到初始滤波值为0的可能性
{
s_byKeyCurTime[wI]--;
}
}
//滤波算法 val = (a & b) | (b & c) | (a & c)
for (wI = 0; wI < KEY_BUF_SIZE; wI++)
{
byA = s_byKeyValue[wI];
byB = s_byKeyValue[wI + KEY_BUF_SIZE];
byC = s_byKeyValue[wI + 2 * KEY_BUF_SIZE];
s_byKeyFiltered[wI] = (byA & byB) | (byB & byC) | (byA & byC);
}
}
/*******************************************************************************
函数名: KF_SetFilterTime
描 述: 由用户调用传入滤波常数值
调 用:
被调用:
输 入: pabyFilter : 存放滤波常数表头地址;该指针在用户进行键盘滤波处理时
不得变更,需为一个全局变量或静态变量
输 出: s_pabyFilterTime : 指向用户存放滤波常数表头
返回值: 无
******************************************************************************/
void KF_SetFilterTime(const uint8 *pabyFilter)
{
s_pabyFilterTime = pabyFilter;
}
/*******************************************************************************
函数名: KF_KeyOutput()
描 述: 用户调用得到滤波后键盘的状态值
调 用:
被调用:
输 入:
输 出:
返回值: s_byKeyFiltered : 存放滤波后键盘值的表头地址
******************************************************************************/
uint8 * KF_KeyOutput(void)
{
return s_byKeyFiltered;
}
/*******************************************************************************
函数名: KF_PerMs
描 述: 由用户每毫秒调用,对键盘进行滤波处理;
用户在调用该函数前需调用函数SetFilterTime传入键盘滤波常数,否则滤波
以缺生设置DEFAULT_FILT_TIME进行
调 用: KF_KeyInput :外部函数,得到键盘的状态值
KF_KeyFilt :对键盘状态值进行滤波处理
被调用:
输 入:
输 出:
返回值: 无
******************************************************************************/
void KF_PerMs(void)
{
KF_KeyInput(s_byKeyOrigin, MAX_KEY_NUMS); // 输入键盘状态
KF_KeyFilt(MAX_KEY_NUMS); // 调用键盘滤波函数
}
/*********************************************************************************************************
** End Of File
********************************************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -