关于单片机延时程序的具体分析
前面我们介绍了延时程序,但这还不完善,因为,我们只知道DJNZ R6,D2这句话会被执行62500次,但是执行这么多次需要多长时间呢?是否满足我们的要求呢?我们还不知道,所以下面要来解决这个问题。
关于单片机延时程序的具体分析
先提一个问题:我们学校里什么是最重要的。(铃声)校长可以出差,老师可以休息,但学校一日无铃声必定大乱。整个学校就是在铃声的统一指挥下,步调一致,统一协调地工作着。这个铃是按一定的时间安排来响的,我们可以称之为“时序��时间的顺序”。一个由人组成的单位尚且要有一定的时序,计算机当然更要有严格的时序。事实上,计算机更象一个大钟,什么时候分针动,什么时候秒针动,什么时候时针动,都有严格的规定,一点也不能乱。计算机要完成的事更复杂,所以它的时序也更复杂。
我们已知,计算机工作时,是一条一条地从ROM中取指令,然后一步一步地执行,我们规定:计算机访问一次存储器的时间,称之为一个机器周期。这是一个时间基准,好象我们人用“秒”作为我们的时间基准一样,为什么不干脆用“秒”,多好,很习惯,学下去我们就会知道用“秒”反而不习惯。
一个机器周期包括12个时钟周期。下面让我们算一下一个机器周期是多长时间吧。设一个单片机工作于12M晶振,它的时钟周期是1/12(微秒)。它的一个机器周期是12*(1/12)也就是1微秒。(请计算一个工作于6M晶振的单片机,它的机器周期是多少)。
MCS-51单片机的所有指令中,有一些完成得比较快,只要一个机器周期就行了,有一些完成得比较慢,得要2个机器周期,还有两条指令要4个机器周期才行。这也不难再解,不是吗?我让你扫地的执行要完成总得比要你完成擦黑板的指令时间要长。为了衡量指令执行时间的长短,又引入一个新的概念:指令周期。所谓指令周期就是指执行一条指令的时间。INTEL对每一条指令都给出了它的指令周期数,这些数据,大部分不需要我们去记忆,但是有一些指令是需要记住的,如DJNZ指令是双周期指令。
下面让我们来计算刚才的延时。首先必须要知道晶振的频率,我们设所用晶振为12M,则一个机器周期就是1微秒。而DJNZ指令是双周期指令,所以执行一次要2个微秒。一共执行62500次,正好125000微秒,也就是125毫秒。
自学单片机第二十二篇:延时消抖
按键的延时消抖是初学单片机的必经之路,因为只要是机械开关所传递的信号,都会存在波动,有时这些波动是"致命"的,所以消除其影响就是一门手艺了。硬件消抖有其优点,同样的也有不方便的地方,开发成本高,操作难度大,可移植性差。软件消抖就相对较好些,新手即可操作,延时消抖,并非消抖的最终最优方法,但好在简单易懂,我们先认识消抖的方法和目的。
按键在按下和抬起时,都会出现短暂的抖动,称之为前沿抖动和后沿抖动,他们持续的时间大致在5-10毫秒,键稳定时间会在100毫秒以上,就人的操作速度来看,键稳定的时间不会低于100毫秒,因为,1秒十次的操作,估计手都受不了。除非科幻世界或武侠世界的人。
既然抖动时间基本不变,那么,我们就有这样一种方法,当按键出现第一个电位变化,假设是高电位转变成低电位,那么我们就延时一段时间,设置10毫秒,10毫秒以后,我们再次判断此时的电位状态,是否是低电位,如果是低电位,那么就认为按键按下了,如果是高电位,就认为按键是抖动。从低电位变成高电位也是一样。
我们就是用延时来,把抖动的时间空过去了,这样就不用担心抖动产生的电位频繁变化了。接下来,我们看下程序如何写。
按流程来,基本上就能写出来,程序分为两大块,一个是主函数,处理开关状态,一个是延时函数。
我们先定义一个开关,然后我又声明了一个位变量,其实这个位变量在这里可以不用,不过习惯如此,对采集来的数据我习惯让其保存在特定的变量中,这样方便后期使用,以防自己改变变量值,造成端口的电位随之改变。
主函数中,先把开关采集端口置1,这是读取数据的前提条件,然后把需要采集的io的状态转移给中间变量,接着判断此时中间变量是否为零,也就是按键是否按下,如果没有按下,那就跳出,继续赋值,接着判断,直到判断为零,进入语句中,先延时一段时间,让抖动空过去,延时结束,再判断一次,由于此时程序还没走出去,所以中间变量的值也没有实时切换,我们此时要判断按键实时状态是否为零,就需要判断端口的实际值,当key10为零,就说明按键确实处于按下状态,这就可以执行,移位指令。
需要说明,如果使用函数,在调用时,只需写出函数名即可。但是在程序最开始位置,需要声明函数,声明时,要写全,尤其是返回值的类型和变量名,不能省略。可以把函数直接复制到前方,然后加一个冒号即可。
程序看完,我们仿真一下测试下程序是否执行。
这是之前我们使用的仿真电路,直接使用就好。我没有改变工程文件,所以无需重新导入可执行文件,程序会直接读取我保存好的新的可执行文件,文件名没有改变。
这是软件的初始状态,所有端口都是高电位,我们按下P10.
按键随着按下,可以稳定的响应,我们再通过实际电路测试一下。
测试发现,我按下按键,还没松手,就已经流水般的熄灭了5个灯了,什么情况?
我们可以看程序的这里
keybuff=key10; //赋值
if(keybuff==0) //判断开关是否按下
{
delay(50); //延时一段时间
if(key10==0) //再次判断开关是否按下
{
P3=P3>>1; //P3左移一位
}
}
从这一段可以看出,只要我能满足keybuff为零,key10为零,那么程序就会在延时结束再次进入程序,如此循环,就造成了,按键按下,P3被连续执行动作。我们怎么才能让这种情况不发生呢?这就需要我们不仅检测按键按下,还需要检测按键弹起,只有按键弹起我们才允许它执行下一步,这样就能按下一次,抬起手,才会停止,保证了操作的准确。
执行流程如下:
判断按键按下》按键按下》延时》判断按键按下》按键按下》执行动作》判断按键抬起》按键抬起》结束。
我们再次测试,此时发现,按下后,不松开,按键不再连续动作,但是松开按键后,原本熄灭的小灯又点亮了,我们梳理程序,可以发现,是不存在错误的,流程也没有问题。其实这就涉及我们的硬件了,我们使用软件仿真时,这些问题都是没有的,但硬件跟仿真的区别就在这里,在单片机中,如果我们没有规定执行下一步的位置,单片机就会在流程走完后,随机进入我们无法控制的流程,这在专业中称之为跑飞。为了防止跑飞,我们一般会在结束添加循环语句,让程序停止在我们设定的位置,这样就不会有问题了。
此处我们需要连续监测按键状态,所以就让程序不断的循环判断按键即可。
再次测试,一切就按照程序执行了,动作也正常了。
这就是为什么我们之前的测试程序,都会在主函数中添加循环的作用。通过这个示例,也是告诉大家,仿真只是学习的方法,最终目的还是要在实际的硬件上进行。不然你永远不知道自己的程序能不能完成真正的功能,设计不能光纸上谈兵哦。
相关问答
delay 延时 函数 计算 公式?DelayMS(300)表示希望系统delay300毫秒,系统有自己的RTC,根据硬件的晶振(Hz)可以计算出一次振荡大约多少耗时,这样就能大约算出1ms需要多少次振荡;简单比喻...
52 单片机延时 咋写?52单片机延时可以使用循环计数的方式实现。具体步骤如下:1.首先,明确延时的时间要求,例如延时100毫秒。2.接下来,根据单片机的主频确定每个机器周期的时间...
单片机 delay函数延迟时间 计算 ,delay(80);为什么是600us左右?只有汇编语言才能得到精确的时间。C编译成汇编时,不同的编译器,不同的编译策略都会使最终的程序不一样。如果短时间的延时,可以利用_nop_()来控制,如果是长...
单片机 延迟1秒怎么设置?单片机延迟1秒可以设置定时器,在定时器中断函数里进行计数,具体实现取决于单片机型号和使用的开发环境。因为单片机需要精确计时,通过定时器和中断可以实现更...
单片机 1秒钟定时汇编语言怎么编?可以有两种方法,设晶振为12M,则第一种方法:用延时的方法实现DELAY:MOVR3,#10;延时子程序,延时1秒D1:MOVR4,#200D2:MOVR5,#250D3:DJ...
用汇编怎么写51 单片机 的 延时程序 ?DEL1S:MOVR7,#10D1:MOVR6,#200D2:MOVR5,#250DJNZR5,$DJNZR6,D2DJNZR7,D1RET说明:1、如果不使用R5、R6、R7...
单片机 中R0,R1,R2,R5,R6,R7是怎样用的?是怎样 计算 时钟周期和 延时程序 的时间的?R0,R1,R2,R5,R6,R71.是通用寄存器,存取数据使用;2.R0,R1用于间接寻址,指定内外0-255存储单元,如MOVA,@R0,MOVX@R1;延时时间按照指令周期计算,每个...R...
单片机 c语言带参数 延时 函数可自定义延迟时间?是的,表示的是延时多少个时钟周期是的,表示的是延时多少个时钟周期
单片机 汇编语言流水灯 程序延时 0.5秒,一共四个灯循环?4只LED为共阳极连接,即单片机输出端为低电平时即可点亮LED。;用最直接的方式实现流水灯ORG0000HSTART:MOVP1,#01111111B;最下面的LED点亮LCALLDE.....
下列51 单片机延时程序 中的#250,这个250是肿么来的?哪位给详...下列51单片机延时程序中的#250,这个250是肿么来的?哪位给详细解释下?显卡小影霸讨论回答(3)DELAY:MOVR7,#250;D1:MOVR6,#250;D2:DJNZR6...