⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 keyfilt.c

📁 键盘Key滤波功能源代码
💻 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 + -