这里假定单片机是时钟频率为12MHz,则一个机器周期为:1us.
参考了 51单片机 Keil C 延时程序的简单研究后,我们可知道, 在Keil C中获得最为准确的延时函数将是







执行DJNZ指令需要2个机器周期,RET指令同样需要2个机器周期,根据输入t,在不计算调用delay()所需时间的情况下,具体时间延时如下:
t | Delay Time (us) |
1 | 2×1+2 =4 |
2 | 2×2+2=6 |
N | 2×N+2=2(N+1) |
当在main函数中调用delay(1)时, 进行反汇编如下:

调用delay()时,多执行了两条指令,其中MOV R, #data需要1个机器周期,LJMP需要2个机器周期,即调用delay()需要3us.
Keil C仿真截图与计算过程:


加上调用时间,准确的计算时间延时与Keil C仿真对比如下:(可见,仿真结果和计算结果是很接近的)
t | Delay Time (us) | 仿真11.0592Mhz时钟(us) |
1 | 3+2×1+2 =7 | 7.7(实际) | 7.60 |
2 | 3+2×2+2=9 | 9.9 | 9.76 |
N | 3+2×N+2=2N+5 | (2N+5)*1.1 | / |
3 | 11 | 12.1 | 11.94 |
15 | 35 | 38.5 | 37.98 |
100 | 205 | 225.5 | 222.44 |
255 | 515 | 566.5 | 558.81 |
也就是说,这个延时函数的精度为2us,最小的时间延时为7us,最大的时间延时为3+255×2+2=515us.
实际中使用11.0592MHz的时钟,这个延时函数的精度将为2.2us,最小时间延时为7.7us, 最大时间延时为566.5us.
这个时间延时函数,对于与DS18B20进行单总线通信,已经足够准确了。
现在,我们将时钟换成11.0592MHz这个实际用到的频率,每个机器周期约为1.1us.
现在让我们来分析一下这个之前用过的延时函数:

