C语言 按键抬起有效 代码,最好的按键扫描和消抖方法,适用于复合、长按、按下或抬起响应按键...

刚参加工作的时候,看了一些同事采用的按键扫描和消抖方法,对比学校里和网上查到的按键处理,发现觉得不尽善尽美,有以下几点:

1. 消抖复杂,效率低。有人直接在电平判断后使用delay()函数,进行消抖,耽误时间;有人在按键电平中断中进行消抖和处理,导致其他的服务反应慢,不适合做实时系统;

2. 许多功能在不同界面下是不同的,把按键处理在中断进行,导致分支很多,业务流不清晰。

3. 特殊功能按键的处理麻烦。在需要长按作为特殊按键、复合按键响应、复合按键长按响应的时候,需要增加很多的标志位,反复使用if..else判断,流程看起来很乱。

4. 跟硬件设计或业务关联很深,不便于移植和修改,导致每个项目都要更改一次。

想了很久之后,我结合PC的键盘处理方法,编写了自己的按键函数,经过几次修改,定了下来。这十多年来,无论更换单片机,还是采用端口/扫描方式,还是采用前后台或操作系统,都一直在用,方便移植,也比较清晰。

/****/

它主要有几个特点:

按键扫描和取值分开。

在中断中,每隔10ms调用keyScan()进行按键扫描,多次扫描进行消抖,获得的按键值不返回,作为消息放到全局变量中;

在业务层需要判断的地方使用getKeyValue()获取当前的键值,进行处理。

每一个按键,都有单独的标志位和计时变量。

消抖计时:

每调用一次10ms中断,如果按键按下,gucKeyOkTimer(以OK按键为例)增加;

gucKeyOkTimer超过消抖的阀值(我一般10次,即100ms),则确认有按键了。

任何一次扫描到按键没有按下,gucKeyOkTimer清零,重新开始;

标志位:

如果按下的电平时间超过阈值,一直按着,会有gfOkPressing的标志,表明按键一直有效中;

如果按下过一次,需要响应,会有gfOkNeedAck,这个标志只置位一次;

复合按键的响应:

因为每个按键,都有自己的标志位和计时变量。复合按键的判断,使用多

  • 1
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是一个基于STC89C52单片机的按键数码管程序,其中包含高位灭0的实现代码: ``` #include <reg52.h> //头文件 sbit KEY1 = P1^0; //定义按键1,连接到P1.0 sbit KEY2 = P1^1; //定义按键2,连接到P1.1 sbit KEY3 = P1^2; //定义按键3,连接到P1.2 sbit DIO = P2^0; //定义DIO数据线,连接到P2.0 sbit CLK = P2^1; //定义CLK时钟线,连接到P2.1 sbit CS = P2^2; //定义CS片选线,连接到P2.2 unsigned char code numTable[] = { //数码管显示的数字编码 0x3f, //0 0x06, //1 0x5b, //2 0x4f, //3 0x66, //4 0x6d, //5 0x7d, //6 0x07, //7 0x7f, //8 0x6f //9 }; void delay(unsigned int i) //延时函数 { while(i--); } void writeByte(unsigned char dat) //向数码管写入一个字节的数据 { unsigned char i; for(i=0; i<8; i++) { DIO = dat & 0x01; //将最低位写入DIO线 dat >>= 1; //将数据右移一位 CLK = 1; //置位时钟线 delay(1); //延时一会 CLK = 0; //清零时钟线 } } void writeNum(unsigned char num) //向数码管写入一个数字 { CS = 0; //选中数码管 writeByte(0x44); //写入控制字节,选择自动地址递增模式 CS = 1; //取选中数码管 CS = 0; //选中数码管 writeByte(0xc0); //写入地址字节,选择第一位数码管 writeByte(numTable[num]); //写入数字的编码 CS = 1; //取选中数码管 } void main() { unsigned char num = 0; while(1) { if(KEY1 == 0) //按键1按下 { num++; //数字自增1 if(num > 9) //如果数字大于9,则重置为0 { num = 0; } while(!KEY1); //等待按键1释放 } if(KEY2 == 0) //按键2按下 { num = 0; //数字重置为0 while(!KEY2); //等待按键2释放 } if(KEY3 == 0) //按键3按下 { break; //退出程序 } writeNum(num); //向数码管写入数字 if(num == 0) //如果数字为0,则灭掉高位 { P2 &= ~(1 << 2); //将P2.2引脚输出低电平 } else { P2 |= (1 << 2); //将P2.2引脚输出高电平 } } } ``` 在上述代码中,实现高位灭0的关键代码为: ``` if(num == 0) //如果数字为0,则灭掉高位 { P2 &= ~(1 << 2); //将P2.2引脚输出低电平 } else { P2 |= (1 << 2); //将P2.2引脚输出高电平 } ``` 其中,P2.2对应的是单片机的第2个引脚,用于控制数码管高位的亮灭状态。如果要实现高位灭0,则需要将该引脚输出低电平,从而灭掉高位的灯珠。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值