一、C51程序
在晶振为11.0592的情况下,如下程序能完成ms级的比较准确的延时:
1 void Delayms(unsigned int n)
2 {
3 unsigned int i,j;
4 for(j=n;j>0;j–)
5 for(i=112;i>0;i–);
6 }
用keil能够看出这个延时的时刻,咱们先延时1ms,即Delayms(1)。
进入Delayms前,sec=0.00042209s
延时后,sec=0.00142253s
能够知道Delayms(1)实践延时0.00142253s—0.00042209s=0.00100044s≈1ms
相同假如想延时15ms的话,用Delayms(15),实践延时0.01480903s≈15ms,延时仍是挺准确的。
参阅:www.jiangx.net/post/214.html
以上比方给咱们的启示是,在不确定延时程序延时多少的情况下,能够经过调试的办法检测出来。
——————————————————————————–
二、汇编程序(500ms):
C:0x0800 7F0F MOV R7,#0x0F
C:0x0802 7ECA MOV R6,#0xCA
C:0x0804 7D51 MOV R5,#0x51
C:0x0806 DDFE DJNZ R5,C:0806
C:0x0808 DEFA DJNZ R6,C:0804
C:0x080A DFF6 DJNZ R7,C:0802
C:0x080C 22 RET
核算剖析:
程序共有三层循环
一层循环n:R5*2 = 81*2 = 162us DJNZ 2us
二层循环m:R6*(n+3) = 202*165 = 33330us DJNZ 2us + R5赋值 1us = 3us
三层循环: R7*(m+3) = 15*33333 = 499995us DJNZ 2us + R6赋值 1us = 3us
循环外: 5us 子程序调用 2us + 子程序回来 2us + R7赋值 1us = 5us
延时总时刻 = 三层循环 + 循环外 = 499995+5 = 500000us =500ms
核算公式:延时时刻=[(2*R5+3)*R6+3]*R7+5
汇编指令速查表:http://www.cainiao8.com/embedded/51danpianji/danpianji03_zhiling.html
——————————————————————————–
三、延时程序剖析
用汇编言语写单片机程序的时分,这个问题仍是相对简单处理的。比方用的是12MHz晶振的51,计划延时20us,只要用下面的代码,就能够满意一般的需求:
mov r0, #09h
loop: djnz r0, loop
51单片机的机器周期是晶振频率的1/12,也便是1us一个周期。mov r0, #09h需求2个机器周期,djnz也需求2个极端周期。那么存在r0里的数便是(20-2)/2。用这种办法,能够十分便利的完成256us以下时刻的延时。假如需求更长时刻,能够运用两层嵌套。并且精度能够到达2us,一般来说,这现已足够了。
现在,使用更广泛的毫无疑问是Keil的C编译器。相对汇编来说,C固然有许多长处,比方程序易保护,便于了解,合适大的项目。但缺陷便是实时性没有确保,无法猜测代码履行的指令周期。因而在实时性要求高的场合,还需求汇编和C的联合使用。可是是不是这样一个延时程序,也需求用汇编来完成呢?为了找到这个答案,我做了一个试验。
用C言语完成延时程序,首要想到的便是C常用的循环句子。下面这段代码是我常常在网上看到的:
void delay2(unsigned char i)
{
for(; i != 0; i–);
}
究竟这段代码能到达多高的精度呢?为了直接衡量这段代码的作用,我把 Keil C 依据这段代码发生的汇编代码找了出来:
; FUNCTION _delay2 (BEGIN)
; SOURCE LINE # 18
;—- Variable i assigned to Register R7 —-
; SOURCE LINE # 19
; SOURCE LINE # 20
0000 ?C0007:
0000 EF MOV A,R7
0001 6003 JZ ?C0010
0003 1F DEC R7
0004 80FA SJMP ?C0007
; SOURCE LINE # 21
0006 ?C0010:
0006 22 RET
; FUNCTION _delay2 (END)
真是不看不知道~~~一看才知道这个延时程序是多么的不准点~~~光看首要的那四条句子,就需求6个机器周期。也便是说,它的精度顶多也便是6us罢了,这还没算上一条 lcall 和一条 ret。假如咱们把调用函数时赋的i值根延时长度列一个表的话,便是:
i delay time/us
0 6
1 12
2 18
…
假如你将程序中的(unsigned char i)改为(unsigned int i)的话汇编程序将变得愈加不合你原意。