(1)按键与蜂鸣器的非阻塞驱动
消抖的两种境界:第一种判断两次电平状态,中间加入“固定延时时间”,不足之处是“固定时间”靠经验值,软件抗干扰能力也弱了很多,“密码等级”不够高,第二种是“清零式滤波”。

#include "reg52.h"
#define KEY_VOICE_TIME 50//按键触发后发出的声音长度
#define KEY_FILTER_TIME 25//按键滤波的“稳定时间”25ms
sbit beep=P2^3;
sbit KEY_INPUT1=P3^4;
sbit KEY_INPUT2=P3^5;//按键识别输入口
volatile unsigned char vGu8BeepTimerFlag=0;
volatile unsigned int vGu16BeepTimerCnt=0;
volatile unsigned char vGu8KeySec=0;//按键的触发序号
void SystemInitial()
{TMOD=0x01;TH0=0xfc;TL0=0x66;EA=1;ET0=1;TR0=1;
}
void Delay(unsigned long u32DelayTime)
{for(;u32DelayTime>0;u32DelayTime--);
}
void PeripheralInitial()
{}
void BeepOpen()
{beep=0;
}
void BeepClose()
{beep=1;
}
void VoiceScan()//蜂鸣器的非阻塞驱动."驱动层"的驱动函数,放在定时中断函数里每1ms扫描一次,保证声音长度的一致性
{static unsigned char Su8Lock=0;if(1==vGu8BeepTimerFlag && vGu16BeepTimerCnt>0){if(0==Su8Lock){Su8Lock=1;//触发声音后自锁起来,避免BeepOpen()被重复扫描影响执行效率,发声时只执行一次BeepOpen()函数即可BeepOpen();//蜂鸣器发声,封装成函数为了代码的移植性}else//借用else结构实现先发声下一次中断再开始计时{vGu16BeepTimerCnt--;if(0==vGu16BeepTimerCnt){Su8Lock=0;//关闭声音后及时解锁为下一次触发做准备BeepClose();}}}
}
void KeyScan()//非阻塞,"清零式滤波"
{static unsigned char Su8KeyLock1;//1号按键的自锁static unsigned int Su16KeyCnt1;//1号按键的计时器static unsigned char Su8KeyLock2;//2号按键的自锁static unsigned int Su16KeyCnt2;//2号按键的计时器if(0!=KEY_INPUT1)//IO口是高电平,没有按键按下,”去抖动延时计数器“一直被清零,如果受到外界或抖动干扰就可以去除瞬间的杂波干扰{Su8KeyLock1=0;//按键解锁Su16KeyCnt1=0;//”去抖动延时计数器“,按键去抖动的重要语句,在抖动过程中一旦有高电平立刻置0直到稳定}else if(0 == Su8KeyLock1)//说明按键被按下,else设计很巧妙相当于KEY_INPUT1==0{Su16KeyCnt1++;//累加的过程就是在滤波,若在累加过程中受到干扰IO口触发高电平,这时马上将Su16KeyCnt1置0,即去除瞬间杂波if(Su16KeyCnt1>=KEY_FILTER_TIME)//滤波的“稳定时间”{Su8KeyLock1=1;//按键自锁标志位,一旦触发按键标志位置1,防止按键按键按住不松手时不断触发按键vGu8KeySec=1;//触发1号键}}if(0!=KEY_INPUT2){Su8KeyLock2=0;Su16KeyCnt2=0;}else if(0 == Su8KeyLock2){Su16KeyCnt2++;if(Su16KeyCnt2>=KEY_FILTER_TIME){Su8KeyLock2=1;vGu8KeySec=2;//触发2号键}}
}
void KeyTask()
{if(0==vGu8KeySec){return;//序号为0无按键触发,退出当前函数.因为当按键多达几十个时就能避免主函数每次进入KeyTask函数时进入switch多次判断,可能会更高效}switch(vGu8KeySec){case 1:vGu8BeepTimerFlag=0;vGu16BeepTimerCnt=KEY_VOICE_TIME;//"应用层"只需赋值,就发出固定时间长度的声音vGu8BeepTimerFlag=1;vGu8KeySec=0;//响应按键服务程序后,按键编号清零避免一直触发break;case 2:vGu8BeepTimerFlag=0;vGu16BeepTimerCnt=KEY_VOICE_TIME;vGu8BeepTimerFlag=1;vGu8KeySec=0;break;}
}
void main()
{SystemInitial();Delay(10000);PeripheralInitial();while(1){KeyTask();}
}
void T0_time() interrupt 1
{VoiceScan();KeyScan();//因为KeyScan是特殊函数放在中断函数里,涉及到IO口输入信号的滤波,滤波就涉及到时间的及时性和均匀性,放在中断中更能保证时间的一致性TH0=0xfc;//如蜂鸣器驱动,动态数码管驱动,按键扫描驱动TL0=0x66;
}

(2)独立按键的单击和双击

#include "reg52.h"
#define KEY_VOICE_TIME 50//按键触发后发出的声音长度
#define KEY_FILTER_TIME 25//按键滤波的“稳定时间”25ms
#define KEY_INTERVAL_TIME 400//连续两次单击之间的最大有效时间
sbit beep=P2^3;//蜂鸣器
sbit P1_4=P1^4;//LED
sbit KEY_INPUT1=P3^4;//按键识别输入口
volatile unsigned char vGu8BeepTimerFlag=0;
volatile unsigned int vGu16BeepTimerCnt=0;
unsigned char Gu8LedStatus=0;//LED灯的状态,0代表灭,1代表亮
volatile unsigned char vGu8SingleKeySec=0;//单击按键的触发序号
volatile unsigned char vGu8DoubleKeySec=0;//双击按键的触发序号
void SystemInitial()
{TMOD=0x01;TH0=0xfc;TL0=0x66;EA=1;ET0=1;TR0=1;
}
void Delay(unsigned long u32DelayTime)
{for(;u32DelayTime>0;u32DelayTime--);
}
void LedOpen()
{P1_4=0;
}
void LedClose()
{P1_4=1;
}
void PeripheralInitial()
{//led初始化没有放在SystemInitial中是因为led显示内容对上电瞬间要求不高,如果是控制继电器则应该放在SystemInitial中if(0 == Gu8LedStatus){LedClose();}else{LedOpen();}
}
void BeepOpen()
{beep=0;
}
void BeepClose()
{beep=1;
}
void VoiceScan()//蜂鸣器的非阻塞驱动."驱动层"的驱动函数,放在定时中断函数里每1ms扫描一次,保证声音长度的一致性
{static unsigned char Su8Lock=0;if(1==vGu8BeepTimerFlag && vGu16BeepTimerCnt>0){if(0==Su8Lock){Su8Lock=1;//触发声音后自锁起来,避免BeepOpen()被重复扫描影响执行效率,发声时只执行一次BeepOpen()函数即可BeepOpen();//蜂鸣器发声,封装成函数为了代码的移植性}else//借用else结构实现先发声下一次中断再开始计时{vGu16BeepTimerCnt--;if(0==vGu16BeepTimerCnt){Su8Lock=0;//关闭声音后及时解锁为下一次触发做准备BeepClose();}}}
}
void KeyScan()//非阻塞,"清零式滤波"
{static unsigned char Su8KeyLock1;//1号按键的自锁static unsigned int Su16KeyCnt1;//1号按键的计时器static unsigned char Su8KeyTouchCnt1;//按键次数记录static unsigned int Su16KeyIntervalCnt1;//按键时间间隔计数器if(0!=KEY_INPUT1)//IO口是高电平,没有按键按下,”去抖动延时计数器“一直被清零,如果受到外界或抖动干扰就可以去除瞬间的杂波干扰{Su8KeyLock1=0;//按键解锁Su16KeyCnt1=0;//”去抖动延时计数器“,按键去抖动的重要语句,在抖动过程中一旦有高电平立刻置0直到稳定if(Su8KeyTouchCnt1>=1)//当按键触发一次后启动间隔时间计数器{Su16KeyIntervalCnt1++;if(Su16KeyIntervalCnt1>=KEY_INTERVAL_TIME){Su16KeyIntervalCnt1=0;Su8KeyTouchCnt1=0;//间隔时间到达将按下的次数清零}}}else if(0 == Su8KeyLock1)//说明按键被按下,else设计很巧妙相当于KEY_INPUT1==0{Su16KeyCnt1++;//累加的过程就是在滤波,若在累加过程中受到干扰IO口触发高电平,这时马上将Su16KeyCnt1置0,即去除瞬间杂波if(Su16KeyCnt1>=KEY_FILTER_TIME)//滤波的“稳定时间”{Su8KeyLock1=1;//按键自锁标志位,一旦触发按键标志位置1,防止按键按键按住不松手时不断触发按键Su16KeyIntervalCnt1=0;//按键按下一次有效间隔时间就清零Su8KeyTouchCnt1++;//记录按下次数if(1==Su8KeyTouchCnt1){vGu8SingleKeySec=1;//单击触发}else if(Su8KeyTouchCnt1>=2){Su8KeyTouchCnt1=0;//按下次数清零vGu8SingleKeySec=1;//单击任务vGu8DoubleKeySec=1;//双击触发}}}
}
void SingleKeyTask()
{if(0==vGu8SingleKeySec){return;//序号为0无按键触发,退出当前函数.因为当按键多达几十个时就能避免主函数每次进入KeyTask函数时进入switch多次判断,可能会更高效}switch(vGu8SingleKeySec){case 1:if(0==Gu8LedStatus){Gu8LedStatus=1;LedOpen();}else{Gu8LedStatus=0;LedClose();}vGu8SingleKeySec=0;//响应按键服务程序后按键编号清零避免一直触发break;}
}
void DoubleKeyTask()
{if(0==vGu8DoubleKeySec){return;//序号为0无按键触发,退出当前函数.因为当按键多达几十个时就能避免主函数每次进入KeyTask函数时进入switch多次判断,可能会更高效}switch(vGu8DoubleKeySec){case 1:vGu8BeepTimerFlag=0;vGu16BeepTimerCnt=KEY_VOICE_TIME;//"应用层"只需赋值,就发出固定时间长度的声音vGu8BeepTimerFlag=1;vGu8DoubleKeySec=0;//响应按键服务程序后,按键编号清零避免一直触发break;}
}
void main()
{SystemInitial();Delay(10000);PeripheralInitial();while(1){SingleKeyTask();DoubleKeyTask();}
}
void T0_time() interrupt 1
{VoiceScan();KeyScan();//因为KeyScan是特殊函数放在中断函数里,涉及到IO口输入信号的滤波,滤波就涉及到时间的及时性和均匀性,放在中断中更能保证时间的一致性TH0=0xfc;//如蜂鸣器驱动,动态数码管驱动,按键扫描驱动TL0=0x66;
}

【独立按键鼠标式的单击与双击】相关推荐

  1. Unity3D New Input System 鼠标左键单击、双击、长按配置及实现接口多态用法(一)

    前言 如果有更好的写法或是代码有什么错误等等,还请大佬教教我. 一.New Input System配置 下载安装哪些就自己搜下怎么整吧,我这就不写了,直接写怎么配置. 首先右键->创建-> ...

  2. STC15单片机-按键检测单击、双击和长按(状态机)

    按键检测(状态机) 传统的按键检测 在单片机的应用中,利用按键实现与用户的交互功能是相当常见的,同时按键的检测也是很讲究的,众所周知,在有键按下后,数据线上的信号出现一段时间的抖动,然后为低,当按键释 ...

  3. 按键功能拓展--单击、双击、长按、组合按等

    按键功能拓展--单击.双击.长按等 key.c key.h 将无自锁功能的按键通过对其单击,双击,长按等状态,进行分配相应的功能,扩展按键功能,调用相关函数即可. key.c #include &qu ...

  4. 光电鼠标单击变双击了怎么办?

    1 换个 现在那东西又不值什么钱 2.有人 拆开微动开关,用小刀刮了两下,就好了 3. 在系统设置那里可以设置的~~ 开始→设置→控制面板→鼠标... 原因: 鼠标长时间使用后,由于触点的氧化,造成触 ...

  5. STM32独立按键实现单击双击长按功能

    目录 前言 一.按键功能定义 二.使用步骤 1.按键初始化 2.按键扫描函数(重点) 总结 前言 在使用STM32或其他单片机开发项目时,经常需要用到独立按键进行控制. 通常一个独立按键需要使用一个I ...

  6. 【按键】[独立按键] - 1: 单击,双击,三击以及N击

    此按键程序的实现的功能是单个独立按键的[单击],[长按],[双击],[三击]以及[多击].本文分为三个部分, 第一个部分是说[单击],[长按]的程序: 第二部分是讲[双击]: 第三部分是讲[三击],[ ...

  7. 独立按键之长按、短按、单击、双击

    目录 一.长按与短按 二.单击与双击 一.长按与短按 在按键按下的时候,即key_down下降沿开始计时.给定一个计时时间,如果在这个计时时间之内检测到了key_up上升沿,即按键松开,则为短按.如果 ...

  8. 修复鼠标单击变双击的问题

    鼠标单击变双击的问题很恼人,很多人都会觉得鼠标完蛋了,该换了. 其实这个问题很简单,就是鼠标左键的轻触开关触点不够清洁了(在电脑里设置XXX功能是没有用的哦),但是这个开关十分精密,打开后很容易损坏, ...

  9. Windows将鼠标单击转换为双击的原理

    对于这个问题,我还是建议你先看看MSDN技术文档中关于鼠标点击方面的内容,因为这些内容是我们开展研究的起点.我也假定你基本了解鼠标的单击转换为双击的基本工作原理. 在阅读了相关的MSDN文档之后,下面 ...

最新文章

  1. Docker(三):Docker 镜像使用
  2. 边缘计算不再“边缘”
  3. jquery 验证控件
  4. 深入云原生 AI:基于 Alluxio 数据缓存的大规模深度学习训练性能优化
  5. 【转载】Hook钩子C#实例
  6. 后端学习 - JavaWeb
  7. 三星Galaxy S22售价曝光:国行可能4999元起
  8. [JavaScript]Call和Apply方法
  9. Improving Opencv9 Eroding and Dilating 和对opencv窗体上有控制按钮的理解
  10. 安装linux下显卡驱动
  11. android的绝对布局,Android布局之绝对布局AbsoluteLayout详解
  12. 关于嵌入式的学习和职业发展
  13. “风味人间”与计算机程序设计艺术《禅与计算机程序设计艺术》 / 陈光剑
  14. 创建计算机桌面快捷方式图标异常,桌面图标显示异常怎么解决
  15. javax.mail.MessagingException: Could not connect to SMTP host: smtp.163.com, port: 465;
  16. Excel:一步搞定平均分 妙用TRIMMEAN函数(转)
  17. Java 交互小实例:(ATM机模拟、饮料自助机模拟)
  18. 如何在PCB中放置禁止触摸标志
  19. 事务处理 :本地 、全局、分布式
  20. 基于JAVAHTML5运河古城网站计算机毕业设计源码+数据库+lw文档+系统+部署

热门文章

  1. excel 添加垂直竖向直线
  2. 谷歌:加入账号其他设备登陆通知功能
  3. GHM:Gradient Harmonized Single-stage Detector
  4. 【DONET学习笔记】C#与VB.NET除法运算的区别
  5. python的or的用法_python中or和and的用法
  6. STM32固件库常见命名方式
  7. openstack-mitaka(二) 基于vmware的搭建
  8. Unity 碰撞体 composite
  9. EasyExcel导入和导出excel数据表格用法示例
  10. JSP-----------简易购物车代码