参考了51单片机 Keil C 延时程序的简单研究,自己也亲身测试和计算了一些已有的延时函数。
这里假定单片机是时钟频率为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) |
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 |
它的反汇编代码如下:
分析: T表示一个机器周期(调用时间相对于这个ms级的延时来说,可忽略不计)
对于delayMs(1), 执行到第7行就跳到21行, 共需时12T, 即13.2us
对于delayMs(2), 需时9T+13T+124×10T+7T+12T = 9T+13T+1240T+7T+12T =1281T =1409.1us.
对于delayMs(3), 需时9T×(3-1)+(13T+124×10T+7T)×(3-1)+12T
=1269T×(3-1)+12T=2550T=2805us.
对于delayMs(N),N>1, 需时1269T×(N-1)+12T = 1269NT-1257T=(1395.9N-1382.7)us.
利用Keil C仿真delayMs(1) = 0.00166558s = 1.67ms 截图如下:
由分析可知具体的计算延时时间与Keil C仿真延时对比如下:
i | Time Delay | 仿真延时 |
1 | 13.2us | 1.67ms |
2 | 1409.1us | 3.31ms |
3 | 2805us | 4.96ms |
N | (1395.9N-1382.7)us | |
10 | 12.6ms | 16.50ms |
20 | 26.5ms | 32.98ms |
30 | 40.5ms | 49.46ms |
50 | 68.4ms | 82.43ms |
100 | 138.2ms | 164.84ms |
200 | 277.8ms | 329.56ms |
500 | 696.6ms | 824.13ms |
1000 | 1394.5ms | 1648.54ms |
1500 | 2092.5ms | 2472.34ms |
2000 | 2790.4ms | 3296.47ms |
5 | 5.6ms | 8.26ms |
73 | 100.5ms | 120.34ms |
720 | 1003.7ms = 1s | 1186.74ms |
计算delayMs(10)得到延时时间为:12576.3us约等于12.6ms,接近我们认为的10ms。
计算结果和仿真结果只要delayMs(1)有很大出入, 其它都接近, 在接受范围内.
经过以上分析,可见用C语言来做延时并不是不太准确,只是不容易做到非常准确而已,若有一句语句变了,延时时间很可能会不同,因为编译程序生成的汇编指令很可能不同。
用户1467105 2008-12-26 19:36
用户518079 2008-12-26 15:02