编程语言及工具
实现延时通常有两种方法:一种是硬件延时,要用到定时器/计数器,这种方法可以提高CPU的工作效率,也能做到精确延时;另一种是软件延时,这种方法主要采用循环体进行。 今天主要介绍软件延时以及单片机精确毫秒延时函数。
在电子技术中,脉冲信号是一个按一定电压幅度,一定时间间隔连续发出的脉冲信号。脉冲信号之间的时间间隔称为周期;而将在单位时间(如1秒)内所产生的脉冲个数称为频率。频率是描述周期性循环信号(包括脉冲信号)在单位时间内所出现的脉冲数量多少的计量名称;频率的标准计量单位是Hz(赫)。电脑中的系统时钟就是一个典型的频率相当精确和稳定的脉冲信号发生器。
指令周期:CPU执行一条指令所需要的时间称为指令周期,它是以机器周期为单位的,指令不同,所需的机器周期也不同。对于一些简单的的单字节指令,在取指令周期中,指令取出到指令寄存器后,立即译码执行,不再需要其它的机器周期。对于一些比较复杂的指令,例如转移指令、乘法指令,则需要两个或者两个以上的机器周期。通常含一个机器周期的指令称为单周期指令,包含两个机器周期的指令称为双周期指令。
时钟周期:也称为振荡周期,一个时钟周期 = 晶振的倒数。对于单片机时钟周期,时钟周期是单片机的基本时间单位,两个振荡周期(时钟周期)组成一个状态周期。
机器周期:单片机的基本操作周期,在一个操作周期内,单片机完成一项基本操作,如取指令、存储器读/写等。
机器周期=6个状态周期=12个时钟周期。
51单片机的指令有单字节、双字节和三字节的,它们的指令周期不尽相同,一个单周期指令包含一个机器周期,即12个时钟周期,所以一条单周期指令被执行所占时间为12*(1/ 晶振频率)= x μs。常用单片机的晶振为11.0592MHz,12MHz,24MHz。其中11.0592MHz的晶振更容易产生各种标准的波特率,后两种的一个机器周期分别为1 μs和2 μs,便于精确延时。
对于需要精确延时的应用场合,需要精确知道延时函数的具体延时时间。以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,可见第一个函数的延时时间更精确一些。
而且延时时间越长,误差就越大。
全部0条评论
快来发表一下你的评论吧 !