




版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
精品文档-下载后可编辑单片机如何设计防抖动程序(源代码),单片机高阻态怎样克服?-设计应用
单片机按键去抖动程序_单片机按键消抖程序汇编
通常按键所用的开关都是机械弹性开关,当机械触点断开、闭合时,由于机械触点的弹性作用,一个按键开关在闭合时不会马上就稳定的接通,在断开时也不会一下子彻底断开,而是在闭合和断开的瞬间伴随了一连串的抖动,如图8-10所示。
图8-10按键抖动状态图
按键稳定闭合时间长短是由操作人员决定的,通常都会在100ms以上,刻意快速按的话能达到40-50ms左右,很难再低了。抖动时间是由按键的机械特性决定的,一般都会在10ms以内,为了确保程序对按键的闭合或者断开只响应,必须进行按键的消抖处理。当检测到按键状态变化时,不是立即去响应动作,而是先等待闭合或断开稳定后再进行处理。按键消抖可分为硬件消抖和软件消抖。
硬件消抖就是在按键上并联一个电容,如图8-11所示,利用电容的充放电特性来对抖动过程中产生的电压毛刺进行平滑处理,从而实现消抖。但实际应用中,这种方式的效果往往不是很好,而且还增加了成本和电路复杂度,所以实际中使用的并不多。
图8-11硬件电容消抖
在绝大多数情况下,我们是用软件即程序来实现消抖的。简单的消抖原理,就是当检测到按键状态变化后,先等待一个10ms左右的延时时间,让抖动消失后再进行按键状态检测,如果与刚才检测到的状态相同,就可以确认按键已经稳定的动作了。将上一个的程序稍加改动,得到新的带消抖功能的程序如下。
#include
sbitADDR0=P1^0;
sbitADDR1=P1^1;
sbitADDR2=P1^2;
sbitADDR3=P1^3;
sbitENLED=P1^4;
sbitKEY1=P2^4;
sbitKEY2=P2^5;
sbitKEY3=P2^6;
sbitKEY4=P2^7;
unsignedcharcodeLedChar[]={//数码管显示字符转换表
0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E
};
voiddelay();
voidmain(){
bitkeybuf=1;//按键值暂存,临时保存按键的扫描值
bitbackup=1;//按键值备份,保存前的扫描值
unsignedcharcnt=0;//按键计数,记录按键按下的次数
ENLED=0;//选择数码管DS1进行显示
ADDR3=1;
ADDR2=0;
ADDR1=0;
ADDR0=0;
P2=0xF7;//P2.3置0,即KeyOut1输出低电平
P0=LedChar[cnt];//显示按键次数初值
while(1){
keybuf=KEY4;//把当前扫描值暂存
if(keybuf!=backup){//当前值与前次值不相等说明此时按键有动作
delay();//延时大约10ms
if(keybuf==KEY4){//判断扫描值有没有发生改变,即按键抖动
if(backup==0){//如果前次值为0,则说明当前是弹起动作
cnt++;//按键次数+1
//只用1个数码管显示,所以加到10就清零重新开始
if(cnt》=10){
cnt=0;
}
P0=LedChar[cnt];//计数值显示到数码管上
}
backup=keybuf;//更新备份为当前值,以备进行下次比较
}
}
}
}
/*软件延时函数,延时约10ms*/
voiddelay(){
unsignedinti=1000;
while(i--);
}大家把这个程序到板子上再进行试验试试,按一下按键而数字加了多次的问题是不是就这样解决了?把问题解决掉的感觉是不是很爽呢?
这个程序用了一个简单的算法实现了按键的消抖。作为这种很简单的演示程序,我们可以这样来写,但是实际做项目开发的时候,程序量往往很大,各种状态值也很多,while(1)这个主循环要不停的扫描各种状态值是否有发生变化,及时的进行任务调度,如果程序中间加了这种delay延时操作后,很可能某一事件发生了,但是我们程序还在进行delay延时操作中,当这个事件发生完了,程序还在delay操作中,当我们delay完事再去检查的时候,已经晚了,已经检测不到那个事件了。为了避免这种情况的发生,我们要尽量缩短while(1)循环所用的时间,而需要进行长时间延时的操作,必须想其它的办法来处理。
那么消抖操作所需要的延时该怎么处理呢?其实除了这种简单的延时,我们还有更优异的方法来处理按键抖动问题。举个例子:我们启用一个定时中断,每2ms进中断,扫描按键状态并且存储起来,连续扫描8次后,看看这连续8次的按键状态是否是一致的。8次按键的时间大概是16ms,这16ms内如果按键状态一直保持一致,那就可以确定现在按键处于稳定的阶段,而非处于抖动的阶段,如图8-12。
图8-12按键连续扫描判断
假如左边时间是起始0时刻,每经过2ms左移,每移动,判断当前连续的8次按键状态是不是全1或者全0,如果是全1则判定为弹起,如果是全0则判定为按下,如果0和1交错,就认为是抖动,不做任何判定。想一下,这样是不是比简单的延时更加可靠?
利用这种方法,就可以避免通过延时消抖占用单片机执行时间,而是转化成了一种按键状态判定而非按键过程判定,我们只对当前按键的连续16ms的8次状态进行判断,而不再关心它在这16ms内都做了什么事情,那么下面就按照这种思路用程序实现出来,同样只以K4为例。
#include
sbitADDR0=P1^0;
sbitADDR1=P1^1;
sbitADDR2=P1^2;
sbitADDR3=P1^3;
sbitENLED=P1^4;
sbitKEY1=P2^4;
sbitKEY2=P2^5;
sbitKEY3=P2^6;
sbitKEY4=P2^7;
unsignedcharcodeLedChar[]={//数码管显示字符转换表
0xC0,0xF9,0xA4,0xB0,0x99,0x92,0x82,0xF8,
0x80,0x90,0x88,0x83,0xC6,0xA1,0x86,0x8E
};
bitKeySta=1;//当前按键状态
voidmain(){
bitbackup=1;//按键值备份,保存前的扫描值
unsignedcharcnt=0;//按键计数,记录按键按下的次数
EA=1;//使能总中断
ENLED=0;//选择数码管DS1进行显示
ADDR3=1;
ADDR2=0;
ADDR1=0;
ADDR0=0;
TMOD=0x01;//设置T0为模式1
TH0=0xF8;//为T0赋初值0xF8CD,定时2ms
TL0=0xCD;
ET0=1;//使能T0中断
TR0=1;//启动T0
P2=0xF7;//P2.3置0,即KeyOut1输出低电平
P0=LedChar[cnt];//显示按键次数初值
while(1){
if(KeySta!=backup){//当前值与前次值不相等说明此时按键有动作
if(backup==0){//如果前次值为0,则说明当前是弹起动作
cnt++;//按键次数+1
if(cnt》=10){//只用1个数码管显示,所以加到10就清零重新开始
cnt=0;
}
P0=LedChar[cnt];//计数值显示到数码管上
}
//更新备份为当前值,以备进行下次比较
backup=KeySta;
}
}
}
/*T0中断服务函数,用于按键状态的扫描并消抖*/
voidInterruptTImer0()interrupt1{
//扫描缓冲区,保存一段时间内的扫描值
staTIcunsignedcharkeybuf=0xFF;
TH0=0xF8;//重新加载初值
TL0=0xCD;
//缓冲区左移一位,并将当前扫描值移入位
这个算法是我们在实际工程中经常使用按键所总结的一个比较好的方法,介绍给大家,今后都可以用这种方法消抖了。当然,按键消抖也还有其它的方法,程序实现更是多种多样,大家也可以再多考虑下其它的算法,拓展下思路。
单片机高阻态是什么意思
在一个系统中或在一个整体中,我们往往定义了一些参考点,就像我们常常说的海平面,在单片中也是如此,我们无论说是高电平还是低电平都是相对来说的。
在51单片机,没有连接上拉电阻的P0口相比有上拉电阻的P1口在I/O口引脚和电源之间相连是通过一对推挽状态的FET来实现的,51具体结构如下图。
51结构图
组成推挽结构,从理论上讲是可以通过调配管子的参数轻松实现输出大电流,提高带载能力,两个管子根据通断状态有四种不同的组合,上下管导通相当于把电源短路了,这种情况下在实际电路中不能出现,从逻辑电路上来讲,上管开-下管关开时IO与VCC直接相连,IO输出低电平0,这种结构下如果没有外接上拉电阻,输出0就是开漏状态(低阻态),因为I/O引脚是通过一个管子接地的,并不是使用导线直接连接,而一般的MOS在导通状态也会有mΩ极的导通电阻。
排阻
无论是低阻态还是高阻态都是相对来说的,把下管子置于截止状态就可以把GND和I/O口隔离达到开路的状态,这时候推挽一对管子是截止状态,忽略读取逻辑的话I/O口引脚相当于与单片机内部电路开路,考虑到实际MOS截止时会有少许漏电流,就称作“高阻态”
由于管子PN节带来的结电容的影响,有的资料也会称作“浮空”,通过I/O口给电容充电需要一定的时间,那么IO引脚处的对地的真实电压和水面浮标随波飘动类似了,电压的大小不仅与外界输入有关还和时间有关,在高频情况下这种现象是不能忽略的。
单片机程序死机,跑飞了可以从以下几个方面查找原因:
1、意外中断。是否打开了某个中断,但是没有响应和清除中端标志,导致程序一直进入中断,造成死机假象;
2、中断变量处理不妥。若定义某些会在中断中修改的全局变量,这时要注意两个问题:首先为了防止编译器优化中断变量,要在这些变量定义时前加volaTIle,其次在主循环中读取中断变量前应该首先关闭全局中断,防止读到一半被中断给修改了,读完之后再打开全局中断;否则出现造成数据乱套。
3、地址溢出,常见错误为指针操作错误。我要着重说的是数组下标使用循环函数中循环变量,如果循环变量没控制好则会出现数组下标越界,意外修改系统的寄存器造成死机,这种情况下如果死机说明运气好,否则后面不知道发生什么头疼的事。
4、无条件的死循环;比如使用wh
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 科技产品如何通过社交媒体提升用户粘性
- 构建多元文化背景下的全球老年大学网络
- 2025年湖北云学名校联盟高三年级2月联考语文试卷
- 科技发展趋势下的管理决策方法
- 施工中标合同范本
- 2025-2030年中国甲醇制芳烃行业发展状况及营销战略研究报告
- 订婚押金合同范本
- 2025-2030年中国汽车钎焊铝合金散热器市场现状分析规划研究报告
- 2025-2030年中国汽车点火线圈市场运行态势及投资发展前景调研报告
- 2025-2030年中国汽车摩擦材料行业运行状况及发展前景分析报告
- 青春期的妇科知识讲座
- JTT589-2004 水泥混凝土路面嵌缝密封材料
- 《社区康复》课件-第三章 社区康复的实施
- 中职生心理健康教育全套教学课件
- JC-T 2704-2022 聚酯纤维装饰吸声板
- WTE朗文英语2B 单词卡片
- 初三物理复习计划详细计划
- 汽车悬架概述
- 心房颤动的教学查房课件
- 重大紧急情况的报告模板
- 二人合伙开宠物店协议书(5篇)
评论
0/150
提交评论