单片机c语言中的精确延时程序,单片机精确毫秒延时函数

对于需要精确延时的应用场合,需要精确知道延时函数的具体延时时间。以C语言编写的单片机延时函数网上有两个不同的版本(都说是延时n毫秒),分别如下:

void delay(uint x) //延时X毫秒

{

uint y,z;

for(z=x;z>0;z--)

for(y=110;y>0;y--);

}

void delay_ms(uint n)   //延时n毫秒

{

uchar i;

while(n--)

{

for(i=0;i<120;i++);

}

}

上述两个函数的实现方法是一样的,只是给的时间常数不同,一个是110,另一个是120。近来工作因为对时间的精度要求很高,就特地验证了下这两个函数运行时所用的时间。 主程序为:

void main(void)

{

delay(1);

}

反汇编之后(推荐用C51智能反编译器,不过要手工加上ORG地址和END结束符):

标号                   指令                                    地址        机器码        机器周期

ORG 0000H

Q0000:             LJMP Q0021                        ;0000   02 00 21

;==========================================================================

ORG   0003H

Q0003:             SETB C                                ;0003   D3                       1

MOV   A,R7                                  ;0004   EF                        1

SUBB A,#00H                            ;0005   94 00                   1

MOV   A,R6                                 ;0007   EE                        1

SUBB A,#00H                             ;0008   94 00                    1

JC    Q0020                                 ;000A   40 14                    2

MOV   R5,#6EH                             ;000C   7D 6E                 1

MOV   R4,#00H                            ;000E   7C 00                   1

Q0010:          MOV   A,R5                            ;0010   ED                            1

DEC   R5                                    ;0011   1D                           1

JNZ   Q0015                                ;0012   70 01                      2

DEC   R4                                    ;0014   1C                          1

Q0015:             MOV   A,R5                          ;0015   ED                          1

ORL   A,R4                                ;0016   4C                           1

JNZ   Q0010                              ;0017   70 F7                          2

MOV   A,R7                               ;0019   EF                              1

DEC   R7                                  ;001A   1F                              1

JNZ   Q0003                             ;001B   70 E6                          2

DEC   R6                                  ;001D   1E                               1

SJMP Q0003                            ;001E   80 E3                          2

Q0020:             RET                                     ;0020   22                                 2

;====================RESET 00-7F AND SET SP=07H============================

ORG   0021H

Q0021:             MOV   R0,#7FH                         ;0021   78 7F

CLR   A                                       ;0023   E4

Q0024:             MOV   @R0,A                           ;0024   F6

DJNZ R0,Q0024                       ;0025   D8 FD

MOV   SP,#07H                        ;0027   75 81 07

LJMP Q002D                            ;002A   02 00 2D

;====================MAIN PROGRAM==========================================

ORG   002DH

Q002D:             MOV   R7,#01H                         ;002D   7F 01             1

MOV   R6,#00H                        ;002F   7E 00               1

LJMP Q0003                             ;0031   02 00 03          2

;==========================================================================

END

单步执行可以跟踪程序的运行,给个最终的结果就是总的执行机器周期数为 :

第一个函数:4+9+8*110+4+9=906

第二个函数:4+9+8*120+4+9=986

如果单片机的晶振是12M,则一个机器周期的时间为12/(12*10e6)=1us

可见第二个程序更接近1ms(0.986us)的时间,第一个是0.906us

当晶振是11.05926M时,第一个延时函数的精确延时时间是983us,第二个是1069.8us,可见第一个函数的延时时间更精确一些。

而且延时时间越长,误差就越大。