搜索
bottom↓
回复: 10

给新型的按键扫描程序,仅三行程序添加去抖动

[复制链接]

出0入0汤圆

发表于 2019-5-19 13:36:48 | 显示全部楼层 |阅读模式
原文链接https://www.amobbs.com/thread-4308630-1-1.html
#define Number 20
unsigned char Jitter = Number;      //连续检测20次,每次间隔1ms
unsigned int Value;     //读取的端口,每次和次数据做或操作,原始值为0
unsigned int SaveData;//保存读取的去抖动后的端口数据
unsigned int Trg;
unsigned int Cont;
void KeyRead(unsigned char Time)
{
    if(Time != 0)       //不为0时,1ms时间间隔已到
    {
        if(Jitter == 0)
        {
            SaveData = Value;   //去抖动次数到,保存读取的数据
            Value = 0;          //和端口做or操作
            Jitter =Number;
        }
        else
        {
            --Jitter;
            Value |= GPIO_ReadInputData(GPIOC);//每次去抖动时都是0为有按下,有一次为1,
            //表示已松开,置读取数据以后都为1,到去抖动次数到,再读取是否为0
        }
    }//以上为添加部分
    unsigned int ReadData = SaveData^0xffff;   // 1
    Trg = ReadData & (ReadData ^ Cont);      // 2
    Cont = ReadData;                                // 3
}

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

月入3000的是反美的。收入3万是亲美的。收入30万是移民美国的。收入300万是取得绿卡后回国,教唆那些3000来反美的!

出0入0汤圆

发表于 2019-5-19 15:07:30 | 显示全部楼层
我发一个应用也很久的检测独立按键的程序,是单击短按的,欢迎探讨

只耗费一个位变量和一个unsigned char的全局变量,当然也要定时器 每20毫秒产生一个中断

  1. sbit FlagKeyStatus=0;
  2. unsigned char CntSingleKey=0;   
  3. void KeyProcess(void)  //每20ms执行 一次
  4. {            
  5.           if(FlagKeyStatus==0)    //  没有按键按下
  6.            {
  7.                    if(!KeyInput)   //KeyInput为按键输入的IO口
  8.                     {
  9.                             CntSingleKey = 1;
  10.                             FlagKeyStatus = 1;                               
  11.                      }
  12.            }
  13.           else   //有按键按下的处理
  14.            {
  15.                    if(!KeyInput)  //一直被按着
  16.                     {
  17.                                 if(CntSingleKey < 250)   //最长时间:5S
  18.                                  {
  19.                                          CntSingleKey++;
  20.                                  }
  21.                         }
  22.                    else
  23.                     {
  24.                                 FlagKeyStatus = 0;
  25.                                if((CntSingleKey>=2)&&(CntSingleKey<25))     //介于  40ms至 500 之间,就会认为是 单击,可能会有正负20ms的偏差
  26.                                 {
  27.                                     FlagSingleKey = 1;  //检测到一次合法的按下事件,通过FlagSingledKey返回
  28.                                 }
  29.                         }
  30.            }
  31. }
复制代码


这段代码是运行在那个超小容量的MCU上面,RAM只有64byte,因此对RAM的 使用必是精确的到比特位的程度 ,当然我想如果像是ARM这类的大容量 的MCU,随便写都没问题。
特点:占用RAM比较小,只需要一个位变量和一个unsigned char的 变量。当然如果 MCU不支持 位变量的 ,就要两个unsigned char的变量了
          非阻塞的执行过程,支持防抖和按键松手检测。

出0入0汤圆

发表于 2019-5-19 17:28:13 来自手机 | 显示全部楼层
矩阵键盘适用么?

出0入0汤圆

 楼主| 发表于 2019-5-19 18:24:19 | 显示全部楼层
本帖最后由 cnxh 于 2019-5-19 18:25 编辑

unsigned int SaveData = 0xffff;//这句初始化一下,不初始化上电相当于按钮已按下
这个一位数据对应一个端口

出0入8汤圆

发表于 2019-5-20 07:40:54 来自手机 | 显示全部楼层
if(Time != 0)这一行就暴露了水平啊。就这样就敢拿出来分享,脸红不?

出0入0汤圆

 楼主| 发表于 2019-5-20 07:45:30 | 显示全部楼层
本帖最后由 cnxh 于 2019-5-20 07:54 编辑
icoyool 发表于 2019-5-20 07:40
if(Time != 0)这一行就暴露了水平啊。就这样就敢拿出来分享,脸红不?


不好意思,水平不够,只是想让初学者参考下,怎么啦,那里不对劲吗,Time 是定时器到位标志的备份
while(1)
{
        关定时器中断语句        
        if(SysTick_Int != 0)
        {
            SysTick_Int = 0;  
            TimeOver = 1;
        }
        开定时器中断语句
        KeyRead(TimeOver);
        //
        其它操作
        //
        TimeOver = 0;//清除到位备份
}
//定时器中断处理:
void SysTick_Handler(void) //中断函数
{
    SysTick_Int = 1;        //系统时钟中断到标志
}

出0入0汤圆

 楼主| 发表于 2019-5-20 07:47:59 | 显示全部楼层
genhao2 发表于 2019-5-19 17:28
矩阵键盘适用么?

这句里的Value |= GPIO_ReadInputData(GPIOC);从直接端口读出,GPIO_ReadInputData(GPIOC);换成从你的矩阵读出不就可以了

出0入0汤圆

发表于 2019-5-20 14:42:18 | 显示全部楼层
cnxh 发表于 2019-5-20 07:45
不好意思,水平不够,只是想让初学者参考下,怎么啦,那里不对劲吗,Time 是定时器到位标志的备份
while(1)
{

我也喜欢这样写,我感觉很爽就行。

出0入0汤圆

发表于 2019-5-20 14:54:01 | 显示全部楼层
retention 发表于 2019-5-19 15:07
我发一个应用也很久的检测独立按键的程序,是单击短按的,欢迎探讨

只耗费一个位变量和一个unsigned char ...

这个逻辑容易理解些,不错。

出0入0汤圆

发表于 2019-5-20 15:18:41 | 显示全部楼层
我对新型的按键扫描程序,仅三行程序的改进
添加去抖动
对单个按键操作,不使用定时器


sbit Key = P1.0;

u8 Keyscan(void)
{
        u8 ReadKey;
        u8 i = 0;
       
        static bit Key_Trge = 0;
        static bit ContKey = 0;
        static u16 LoopCnt_Key = 0;

        LoopCnt_Key ++;

        if(LoopCnt_Key >= 10000)
        {
                LoopCnt_Key = 0;
               
                //按键算法的精髓在于==响应且只响应一次按键操作,并具有抗干扰(再一次确认)。
                //此算法是第二次读按键仍然有效才响应按键操作
                ReadKey = Key ^ 1;        //当前I/O状态(按下为“真”)
                if(Key_Trge && ReadKey)
                {
                        i |= 0x01;
                        // 或直接响应按键操作
                }
                Key_Trge = ReadKey & (ReadKey ^ ContKey);
                                //如果 当前状态为“真”,且当和“上次状态”不一致,则Trg为“真”
                                //即:如果当前检测到按键按下且上次未按下,则是一次有效的触发;
                                //如果连续按下,则只视为一次有效触发。
                                //这里的ContKey_RUN表示为“上次状态”。
                ContKey = ReadKey;        //保存当前状态
        }
        return i;
}

出0入14汤圆

发表于 2019-5-20 17:53:34 | 显示全部楼层
个人喜欢就好....

反正我不喜欢....

===

单纯为了几行来搞...没意义,可读性不高

我按键都是单独开个文件处理的....就算是一个高低电平检测都有十几行....
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

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

GMT+8, 2024-4-24 11:57

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

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