原创 用C51编写单片机延时函数

2008-12-5 22:06 7784 6 7 分类: MCU/ 嵌入式
参考了51单片机 Keil C 延时程序的简单研究,自己也亲身测试和计算了一些已有的延时函数。

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

None.gifvoid delay(unsigned char t)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    
while(--t);
ExpandedBlockEnd.gif}
反汇编代码如下:

执行DJNZ指令需要2个机器周期,RET指令同样需要2个机器周期,根据输入t,在不计算调用delay()所需时间的情况下,具体时间延时如下:

tDelay Time (us)
12×1+2 =4
22×2+2=6
N2×N+2=2(N+1)


当在main函数中调用delay(1)时, 进行反汇编如下:

调用delay()时,多执行了两条指令,其中MOV R, #data需要1个机器周期,LJMP需要2个机器周期,即调用delay()需要3us.

Keil C仿真截图与计算过程:



加上调用时间,准确的计算时间延时与Keil C仿真对比如下:(可见,仿真结果和计算结果是很接近的)

tDelay Time (us)仿真11.0592Mhz时钟(us)
13+2×1+2 =7 | 7.7(实际)7.60
23+2×2+2=9 | 9.99.76
N3+2×N+2=2N+5 | (2N+5)*1.1/
311 | 12.111.94
1535 | 38.5 37.98
100205 | 225.5222.44
255515 | 566.5558.81

也就是说,这个延时函数的精度为2us,最小的时间延时为7us,最大的时间延时为3+255×2+2=515us.  
实际中使用11.0592MHz的时钟,这个延时函数的精度将为2.2us,最小时间延时为7.7us, 最大时间延时为566.5us.
这个时间延时函数,对于与DS18B20进行单总线通信,已经足够准确了。

现在,我们将时钟换成11.0592MHz这个实际用到的频率,每个机器周期约为1.1us.
现在让我们来分析一下这个之前用过的延时函数:

None.gif//延时函数, 对于11.0592MHz时钟, 例i=10,则大概延时10ms.
None.gif
void delayMs(unsigned int i)
ExpandedBlockStart.gifContractedBlock.gif
dot.gif{
InBlock.gif    unsigned 
int j;
InBlock.gif    
while(i--)
ExpandedSubBlockStart.gifContractedSubBlock.gif    
dot.gif{
InBlock.gif        
for(j = 0; j < 125; j++);
ExpandedSubBlockEnd.gif    }

ExpandedBlockEnd.gif}

它的反汇编代码如下:

分析: T表示一个机器周期(调用时间相对于这个ms级的延时来说,可忽略不计)

 1  C:0000      MOV   A,    R7       ;1T 
 2                   DEC   R7                ;1T   低8位字节减1
 3                   MOV   R2,   0x06   ;2T
 4                   JNZ   C:0007          ;2T   若低8位字节不为0, 则跳到C:0007
 5                   DEC   R6                ;1T   低8位字节为0, 则高8位字节减1
 6 C:0007      ORL   A,   R2         ;1T
 7                   JZ      C:001D         ;2T   若高8位也减为0, 则RET
 8                   CLR   A                  ;1T   A清零
 9                   MOV   R4,   A        ;1T   R4放高位
10                   MOV   R5,   A        ;1T   R5放低位
11 C:000D      CLR   C                  ;1T   C清零
12                   MOV   A,   R5        ;1T   
13                   SUBB   A, #0x7d    ;1T   A = A-125
14                   MOV   A,   R4        ;1T   
15                   SUBB   A,  #0x00   ;1T   A 
16                   JNC  C:0000           ;2T   A为零则跳到C:0000
17                   INC   R5                 ;1T   R5增1
18                   CJNE R5,#0x00, C:001B ;2T   R5>0, 跳转到C:000D
19                   INC   R4                 ;1T
20 C:001B      SJMP      C:000D    ;2T
21 C:001D      RET

对于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仿真延时对比如下:

iTime Delay仿真延时
113.2us1.67ms
21409.1us3.31ms
32805us4.96ms
N(1395.9N-1382.7)us
1012.6ms16.50ms
2026.5ms32.98ms
3040.5ms49.46ms
5068.4ms82.43ms
100138.2ms164.84ms
200277.8ms329.56ms
500696.6ms824.13ms
10001394.5ms1648.54ms
15002092.5ms2472.34ms
20002790.4ms3296.47ms
55.6ms8.26ms
73100.5ms120.34ms
7201003.7ms = 1s1186.74ms


计算delayMs(10)得到延时时间为:12576.3us约等于12.6ms,接近我们认为的10ms。


计算结果和仿真结果只要delayMs(1)有很大出入, 其它都接近, 在接受范围内. 

经过以上分析,可见用C语言来做延时并不是不太准确,只是不容易做到非常准确而已,若有一句语句变了,延时时间很可能会不同,因为编译程序生成的汇编指令很可能不同。

文章评论1条评论)

登录后参与讨论

用户314551 2010-8-22 11:40

能加以qq吗?忘请教fpga qq1320249827
相关推荐阅读
用户106445 2011-01-05 22:17
C语言中常见的置位操作
如何对某一位置0或者置1?方法一:写成宏,方便移植#define setbit(x,y) x|=(1<<y) //将X的第Y位置1#define clrbit(x,y) x&=!(...
用户106445 2008-12-25 19:17
ST-BUS基本原理
 ST-BUS基本原理    ST-BUS(Serial Telecom BUS,串行通信总线)是卓联半导体公司根据电信应用的需要而定义的一种重要的通信设备内部总线通信协议,它可以将多路信息(包括音频...
用户106445 2008-12-25 18:58
无源晶体与有源晶振的区别、应用范围及用法
无源晶体与有源晶振的区别、应用范围及用法:1、无源晶体——无源晶体需要用DSP片内的振荡器,在datasheet上有建议的连接方法。无源晶体没有电压的问题,信号电平是可变的,也就是说是根据起振电路来决...
用户106445 2008-12-13 20:39
更改XP收藏夹的位置
用户的收藏的网址系统默认存放在C:\Documents and Settings\username \收藏夹 里。但有时因为种种原因要重做系统时,应该把这个文件复制出来,在做完系统后把这个文件夹还原回...
用户106445 2008-12-05 22:24
令人头晕的指针
某种类型名   *)另一种类型指针变量名: 这个只是转换了指针类型。 *(某种类型名*)&另一种类型指针变量名     这个将   另一种类型指针的指针(地址)   转换成了   某种类型指针...
用户106445 2008-12-05 22:22
指针不完全手册2
第二节 指针的应用<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />1、 指针与变量定...
我要评论
1
6
关闭 站长推荐上一条 /2 下一条