IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 嵌入式 -> 单片机按键程序--单击,双击,长按,组合长按 -> 正文阅读

[嵌入式]单片机按键程序--单击,双击,长按,组合长按

此按键程序也是自己在一个网站上看到的,发现对小白来说还是比较好理解的,废话后面再说,先上代码

#define KEY_FILTER_TIME ?25 ? ? //按键滤波的“稳定时间”25ms
#define KEY_INTERVAL_TIME ?250 ?//连续两次单击之间的最大有效时间250ms
#define KEY_LONG_TIME ?500 ? ? ?//按键的“长按”兼“滤波”的“稳定时间”500ms


volatile unsigned char vGu8CombinationKeySec=0; ?//组合按键的触发序号

volatile unsigned char vGu8_SingleKey1Sec=0; ?//单击按键1的触发序号
volatile unsigned char vGu8_DoubleKey1Sec=0; ?//双击按键1的触发序号

volatile unsigned char vGu8_SingleKey2Sec=0; ?//单击按键2的触发序号
volatile unsigned char vGu8_DoubleKey2Sec=0; ?//双击按键2的触发序号


void KeyScan(void) ?//此函数放在定时中断里每1ms扫描一次
{
? ?static unsigned char Su8CombinationKeyLock; ?//组合按键的自锁
? ?static unsigned int ?Su16CombinationKeyCnt; ?//组合按键的计时器
? ?
/****************************************************************/ ??
? ?static unsigned char Su8_Key1Lock1; ? ? ? ?
? ?static unsigned int ?Su16_Key1Cnt1; ?
? ?static unsigned char Su8_Key1ShortFlag = 0; ?//按键“短按”触发的标志 ?
? ?
? ?static unsigned char Su8_DoubleKey1Lock1; ? ? ? ?
? ?static unsigned int ?Su16_DoubleKey1Cnt1;?
? ?static unsigned char Su8_Key1TouchCnt1; ? ? ? //1号按键的次数记录
? ?static unsigned int ?Su16_Key1IntervalCnt1; ? //1号按键的间隔时间计数器
/********************************************************************/
? ?static unsigned char Su8_Key2Lock2; ? ? ? ?
? ?static unsigned int ?Su16_Key2Cnt2; ?
? ?static unsigned char Su8_Key2ShortFlag = 0; ?//按键“短按”触发的标志 ?
? ?
? ?static unsigned char Su8_DoubleKey2Lock2; ? ? ? ?
? ?static unsigned int ?Su16_DoubleKey2Cnt2;?
? ?static unsigned char Su8_Key2TouchCnt2; ? ? ? //1号按键的次数记录
? ?static unsigned int ?Su16_Key2IntervalCnt2; ? //1号按键的间隔时间计数器
?/***********************************************************************/

? ?//K1按键与K2按键的组合触发
? ?if(0!=key1||0!=key2)//两个按键只要有一个按键没有按下,处于“非组合按键”的状态。
? ?{
? ? ? Su8CombinationKeyLock=0; //组合按键解锁
? ? ? Su16CombinationKeyCnt=0; ?//组合按键去抖动延时计数器清零。 ? ? ?
? ?}
? ?else if(0==Su8CombinationKeyLock)//两个按键被同时按下。
? ?{
? ? ? Su16CombinationKeyCnt++; //累加定时中断次数
? ? ? if(Su16CombinationKeyCnt>=KEY_FILTER_TIME) //滤波的“稳定时间”KEY_FILTER_TIME。
? ? ? {
? ? ? ? ?Su8CombinationKeyLock=1; ?//组合按键的自锁,避免一直触发
? ? ? ? ?vGu8CombinationKeySec=1; ? //触发K1与K2的组合键操作
? ? ? }
? ?}
/******************************************************************/
//按键1
? if(0 != key1)?? ??? ??? ??? ?//1按键没有按下,及时清零一些标志。
? ?{
? ? ? Su8_Key1Lock1=0; //按键解锁
? ? ? Su16_Key1Cnt1=0; ?//去抖动延时计数器清零
? ? ??
? ? ? Su8_DoubleKey1Lock1=0;
? ? ? Su16_DoubleKey1Cnt1=0;
?//长短按 ? ?
? ? ? if(1==Su8_Key1ShortFlag) ?//松手的时候,如果“短按”标志有效就触发一次“短按”
? ? ? {
?? ??? ?Su8_Key1ShortFlag=0; ? ? //先清零“短按”标志避免一直触发。
?? ??? ?vGu8_SingleKey1Sec=1; ? ?//触发“短按”
?? ? ?}?
//双击?? ? ?
?? ? ?if(Su8_Key1TouchCnt1>=1) //之前已经有按键触发过一次,再来一次就构成双击
? ? ? ?{
? ? ? ? ? ? Su16_Key1IntervalCnt1++; //按键间隔的时间计数器累加
? ? ? ? ? ?if(Su16_Key1IntervalCnt1>=KEY_INTERVAL_TIME) //达到最大允许的间隔时间
? ? ? ? ? ?{
??? ??? ??? ??? ?Su16_Key1IntervalCnt1 = 0; //时间计数器清零
? ? ? ? ? ? ? ? Su8_Key1TouchCnt1 = 0; ? ? //清零按键的按下的次数
? ? ? ? ? ?}
? ? ? ?}
? ?}
??
? //双击
? ? ? else if(0==Su8_DoubleKey1Lock1)//有按键按下,且是第一次被按下。
? ?{
? ? ? Su16_DoubleKey1Cnt1++; //累加定时中断次数
? ? ? if(Su16_DoubleKey1Cnt1>=KEY_FILTER_TIME) //滤波的“稳定时间”KEY_FILTER_TIME,长度是25ms。
? ? ? {
? ? ? ? ?Su8_DoubleKey1Lock1=1; ?//按键的自锁,避免一直触发
? ? ? ? ?Su16_DoubleKey1Cnt1=0; ? //按键有效间隔的时间计数器清零
? ? ? ? ?Su8_Key1TouchCnt1++; ? ? ? //记录当前单击的次数
? ? ? ? ?if(Su8_Key1TouchCnt1>=2) ?//连续按了两次以上
? ? ? ? ?{
? ? ? ? ? ? ? Su8_Key1TouchCnt1=0; ? ?//统计按键次数清零
?? ??? ??? ? ?vGu8_DoubleKey1Sec=1; ? //双击任务
? ? ? ? ?}
? ? ? }
? ?} ?
//长短按 ??
? ?? ?else if(0==Su8_Key1Lock1)//按键1被按下
? ?{
? ? ? Su16_Key1Cnt1++; //累加定时中断次数

? ? ? if(Su16_Key1Cnt1>=KEY_FILTER_TIME) //“短按”兼“滤波”的“稳定时间”KEY_SHORT_TIME
? ? ? {
? ? ? ? ? ? Su8_Key1ShortFlag=1; ? ?//“短按”标志有效,待松手时触发。
? ? ? }


? ? ? if(Su16_Key1Cnt1>=KEY_LONG_TIME) //“长按”兼“滤波”的“稳定时间”KEY_LONG_TIME
? ? ? {
? ? ? ? ? ? Su8_Key1Lock1=1; ? ? ?//此时“长按”触发才“自锁”
?? ??? ??? ?Su8_Key1ShortFlag=0; ?//既然此时“长按”有效,那么就要废除潜在的“短按”。
? ? ? ? ? ? vGu8_SingleKey1Sec=2; //触发“长按”
? ? ? }
? ?}
? /***************************************************************/
??
? /******************************************************************/
//按键2
? if(0 != key2)?? ??? ??? ??? ?//1按键没有按下,及时清零一些标志。
? ?{
? ? ? Su8_Key2Lock2=0; //按键解锁
? ? ? Su16_Key2Cnt2=0; ?//去抖动延时计数器清零
? ? ??
? ? ? Su8_DoubleKey2Lock2=0;
? ? ? Su16_DoubleKey2Cnt2=0;
?//长短按 ? ?
? ? ? if(1==Su8_Key2ShortFlag) ?//松手的时候,如果“短按”标志有效就触发一次“短按”
? ? ? {
?? ??? ?Su8_Key2ShortFlag=0; ? ? //先清零“短按”标志避免一直触发。
?? ??? ?vGu8_SingleKey2Sec=1; ? ?//触发“短按”
?? ? ?}?
//双击?? ? ?
?? ? ?if(Su8_Key2TouchCnt2>=1) //之前已经有按键触发过一次,再来一次就构成双击
? ? ? ?{
? ? ? ? ? ? Su16_Key2IntervalCnt2++; //按键间隔的时间计数器累加
? ? ? ? ? ?if(Su16_Key2IntervalCnt2>=KEY_INTERVAL_TIME) //达到最大允许的间隔时间
? ? ? ? ? ?{
??? ??? ??? ??? ?Su16_Key2IntervalCnt2 = 0; //时间计数器清零
? ? ? ? ? ? ? ? Su8_Key2TouchCnt2 = 0; ? ? //清零按键的按下的次数
? ? ? ? ? ?}
? ? ? ?}
? ?}
??
? //双击
? ? ? else if(0==Su8_DoubleKey2Lock2)//有按键按下,且是第一次被按下。
? ?{
? ? ? Su16_DoubleKey2Cnt2++; //累加定时中断次数
? ? ? if(Su16_DoubleKey2Cnt2>=KEY_FILTER_TIME) //滤波的“稳定时间”KEY_FILTER_TIME,长度是25ms。
? ? ? {
? ? ? ? ?Su8_DoubleKey2Lock2=1; ?//按键的自锁,避免一直触发
? ? ? ? ?Su16_DoubleKey2Cnt2=0; ? //按键有效间隔的时间计数器清零
? ? ? ? ?Su8_Key2TouchCnt2++; ? ? ? //记录当前单击的次数
? ? ? ? ?if(Su8_Key2TouchCnt2>=2) ?//连续按了两次以上
? ? ? ? ?{
? ? ? ? ? ? ? Su8_Key2TouchCnt2=0; ? ?//统计按键次数清零
?? ??? ??? ? ?vGu8_DoubleKey2Sec=1; ? //双击任务
? ? ? ? ?}
? ? ? }
? ?} ?
//长短按 ??
? ?? ?else if(0==Su8_Key2Lock2)//按键1被按下
? ?{
? ? ? Su16_Key2Cnt2++; //累加定时中断次数

? ? ? if(Su16_Key2Cnt2>=KEY_FILTER_TIME) //“短按”兼“滤波”的“稳定时间”KEY_SHORT_TIME
? ? ? {
? ? ? ? ? ? Su8_Key2ShortFlag=1; ? ?//“短按”标志有效,待松手时触发。
? ? ? }


? ? ? if(Su16_Key2Cnt2>=KEY_LONG_TIME) //“长按”兼“滤波”的“稳定时间”KEY_LONG_TIME
? ? ? {
? ? ? ? ? ? Su8_Key2Lock2=1; ? ? ?//此时“长按”触发才“自锁”
?? ??? ??? ?Su8_Key2ShortFlag=0; ?//既然此时“长按”有效,那么就要废除潜在的“短按”。
? ? ? ? ? ? vGu8_SingleKey2Sec=2; //触发“长按”
? ? ? }
? ?}
? /***************************************************************/

}


void CombinationKeyTask(void) ? ?//组合按键任务函数,放在主函数内
{
?? ?if(0==vGu8CombinationKeySec)
?? ?{
?? ??? ?return; //按键的触发序号是0意味着无按键触发,直接退出当前函数,不执行此函数下面的代码
?? ?}

?? ?switch(vGu8CombinationKeySec) //根据不同的按键触发序号执行对应的代码
?? ?{
?? ? ? case 1:? ?
?? ??? ??? ??? ?vGu8CombinationKeySec=0; ?//响应按键服务处理程序后,按键编号必须清零,避免一致触发
?? ??? ??? ?break;
?? ?}

}


void SingleKey1Task(void) ? ?//按键1任务函数
{
?? ?if(0==vGu8_SingleKey1Sec)
?? ?{
?? ??? ?return; ?? ??? ??? ?
?? ?}
?? ?
?? ?switch(vGu8_SingleKey1Sec) ?? ??? ??? ??? ?//1为按键1短按,2为按键1长按
?? ?{
?? ? ? case 1: ?
?? ? ? ?? ??? ??? ?vGu8_SingleKey1Sec=0;
?? ? ? ?? ??? ?break;
?? ? ? case 2:??
?? ? ? ?? ??? ??? ?vGu8_SingleKey1Sec=0;
?? ? ? ?? ??? ?break;?? ?
?? ?}
}

void DoubleKey1Task(void) ? ?//按键1双击任务函数
{
?? ?if(0==vGu8_DoubleKey1Sec)
?? ?{
?? ??? ?return; ?? ??? ??? ?
?? ?}
?? ?
?? ?switch(vGu8_DoubleKey1Sec) ?? ??? ??? ??? ?
?? ?{
?? ? ? case 1: ?
?? ? ? ?? ??? ??? ?vGu8_DoubleKey1Sec=0;
?? ? ? ?? ??? ?break;
?? ?}
}


void SingleKey2Task(void) ? ?//按键2任务函数
{
?? ?if(0==vGu8_SingleKey2Sec)
?? ?{
?? ??? ?return; ?? ??? ??? ?
?? ?}
?? ?
?? ?switch(vGu8_SingleKey2Sec) ?? ??? ??? ??? ?//1为按键2短按,2为按键2长按
?? ?{
?? ? ? case 1: ?
?? ? ? ?? ??? ??? ?vGu8_SingleKey2Sec=0;
?? ? ? ?? ??? ?break;
?? ? ? case 2:?
?? ? ? ?? ??? ??? ?vGu8_SingleKey2Sec=0;
?? ? ? ?? ??? ?break;?? ?
?? ?}
}

void DoubleKey2Task(void) ? ?//按键2双击任务函数
{
?? ?if(0==vGu8_DoubleKey2Sec)
?? ?{
?? ??? ?return; ?? ??? ??? ?
?? ?}
?? ?
?? ?switch(vGu8_DoubleKey2Sec) ?? ??? ??? ??? ?
?? ?{
?? ? ? case 1: ?
?? ? ? ?? ??? ??? ?vGu8_DoubleKey2Sec=0;
?? ? ? ?? ??? ?break;
?? ?}
}

keyscan()函数放定时器中断服务函数里(我设置的定时器是1ms), 其他的放在主循环即可。

文章记录自己学习单片机的过程,记录一些自己所见识到的比较好用的程序,也算是一个总结,方便今后遇到相同的问题可以快速解决,今年3月中旬开始接触C语言,稀里糊涂学了一个月,然后开始学习51单片机,接着6月份正式去一个小公司上班,自己还是小小小白,如有错误的地方还请多多指点,感谢!

程序比较臃肿,如果四个,八个按键相同的功能时候按照这样写那也太多了,其实两个按键很多功能都重复的,该怎样优化呢,搞完之后再想这个问题,想法是有,但是用代码实现以目前自己的水平还是很难实现的。

第一次写这样的文章,谢谢谢谢!!

  嵌入式 最新文章
基于高精度单片机开发红外测温仪方案
89C51单片机与DAC0832
基于51单片机宠物自动投料喂食器控制系统仿
《痞子衡嵌入式半月刊》 第 68 期
多思计组实验实验七 简单模型机实验
CSC7720
启明智显分享| ESP32学习笔记参考--PWM(脉冲
STM32初探
STM32 总结
【STM32】CubeMX例程四---定时器中断(附工
上一篇文章      下一篇文章      查看所有文章
加:2021-11-20 18:33:24  更:2021-11-20 18:33:48 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2025年1日历 -2025/1/8 4:09:41-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码