如何计算51单片机延时程序中的延时时间

        最近在上单片机原理及应用课程,做实验的时候遇到了软件延时程序如何计算延时时间的问题,经过一阵摸索终于领悟到其中奥秘……耶(比耶)。 延时函数是使用STC-ISP生成的,晶振为12MHz,指令集是STC-Y1(即89系列),使用do while()循环实现软件精确延时。下面讲解一下其中的延时时间是如何计算的。 

1. 首先我们先设置断点是程序运行到进入delay_10ms()函数前,可以在图1右下角看到此时程序运行时间为0.00040800sec,此时我们看向反汇编窗口(Disassembly)。请注意圈出来的“LCALL delay_10ms”汇编指令,程序运行到代码“ int a=100 ”并完成赋值后往下运行遇到delay_10ms(),子程序调用指令LCALL 完成对delay_10ms()的调用,该指令消耗24个时钟周期,即 t1=2us。

 

图1

2. 接着点击调试中的单步执行按钮,使程序转到delay_10ms()中,图2可以看到,首先执行“ MOV R7,#0x14”(即 i=20),接着执行“MOV R6,#0x71”,查STC-ISP指令表可知将立即数赋值给寄存器指令“MOV Rn #data”消耗12个时钟周期,故上述两部共消耗 t2=2us。

 图2

3. i,j赋值完再接着往下是执行do{}里面的内容“while(–j)”,“DJNZ  R6 , C:005D”指令的意思是寄存器R6里面的内容减1不为0则转移到“C:005D”处,即继续执行j自减。DJNZ指令消耗24个时钟周期,一共执行113次,即113 X 2us = 226us 。

4. 当j从113自减到0后,不满足DJNZ条件,则程序继续往下执行“ while(–i)”,即判断do while()的条件。该代码对应汇编指令为“ DJNZ  R7 , C:005D”,即i=20,自减1为19,不为0则转移到C:005D,继续执行j自减。注意,接下来的步骤很容易算错,很多人可能误以为j会再次从113开始自减,但实际不是的,前面存放 j=113 的寄存器R6从113自减到0后,此时再次自减 将从256开始,因为寄存器值从0开始减1后将会变成11111111,即256。这样,整个循环时间就很容易得出来了:t3 = 113 X 1 X 2us + 256 X 19 X 2us + 20 X 2us = 9954us

5. delay_10ms()程序结束后往下是 子程序返回指令RET,该指令功能是返回到子程序调用指令下一指令处,即返回进delay_ms()前的地方。该指令消耗24个时钟周期,故 t4 = 2us。

综上:可得delay_10ms()执行时间,t = t1 + t2 + t3 + t4 = 2 + 2 + 9954 + 2 = 10000us = 10ms。

验证:分别在进delay_10ms() 和 执行完delay_10ms()后设置断点调试,如图3,可得时间 :

t = 0.01040800sec – 0.00040800sec = 0.01000000sec,即10ms。

 图3

(第一次写文章,写的不好请多多谅解哈)

物联沃分享整理
物联沃-IOTWORD物联网 » 如何计算51单片机延时程序中的延时时间

发表评论