论文部分内容阅读
摘要: 在单片机控制应用中,经常会遇到需要短时间延时的情况,有时还需要很高的精度。然而每次延时都使用定时器/计数器是没有必要的也是不现实的,利用软件延时程序来完成一些需要延时的部分势在必行。从研究软件延时程序模式出发,指出计算整个延时时间的具体方法,并在此基础上归纳一种设计精确软件延时的数学算法。
关键词: 单片机;软件延时;数学算法
中图分类号:NT 文献标识码:A 文章编号:1671-7597(2011)0310081-02
1 软件延时的基本原理
单片机在进行控制时,CPU过一段时间再去作某件事情,称之为延时。延时分为硬件延时和软件延时。硬件延时是指使用定时/计数器来实现延时,这种方法不占用CPU的工作时间。软件延时是利用程序中的指令在被执行时要花费一定的机器周期来实现的,占用CPU的工作时间。软件延时主要与两个因素有关,一是所用的晶振,二是延时程序的循环次数。单片机所用的晶振一经确定之后,延时时间就被指令的循环次数所唯一确定了,如单片机的晶振频率为6MHz,则一个机器周期为2μs。下面根据指令循环的次数的不同,先来介绍软件延时时长的计算方法(设晶振频率为12MHz)。
2 软件延时时长的计算方法
软件延时常用如表1的汇编指令。
1)单循环延时程序
DEL:MOV R0,#X;1T
DEL1:DJNZ R0,DEL1;2XT
RET;2T
延时时间:t=1+2X+2=2X+3=2R0+3
因为X的取值范围是[0,255],X=0时延时时间最长。所以延时时间t的取值范围是[5,515]μs。
2)二重循环程序
DEL:MOV R1,#Y ;1T
DEL1:MOV R0,#X ;1YT
DEL2:DJNZ R0,DEL2;2XYT
DJNZ R1,DEL1;2YT
RET;2T
延时时间:t=1+1Y+2XY+2Y+2
=2XY+3Y+3=2R0R1+3R1+3
因为X、Y的取值范围均为[0,255],X=Y=0时延时时间最长。所以延时时间t的取值范围是[8,131843]μs。
3)三重循环程序
DEL:MOV R2,#Z ;1T
DEL1:MOV R1,#Y ;1ZT
DEL2:MOV R0,#X ;1YZT
DEL3:DJNZ R0,DEL3;2XYZT
DJNZ R1,DEL2;2YZT
DJNZ R2,DEL1;2ZT
RET;2T
延时时间:
t=1+1Z+1YZ+2XYZ+2YZ+2Z+2
=2XYZ+3YZ+3Z+3
=2R0R1R2+3R1R2+3R2+3
同理,延时时间t的取值范围是[11,33751811]μs。
综上分析,由数学归纳法可得出N(N一般不大于8)重循环的延时时间计算公式:
3 C语言中延时程序的设计方法
在用C语言进行编程时涉及到的软件延时程序,其设计方法与汇编语言的设计方法本质相同。例如,在C语言的一个实例程序中用for语句编写了一个延时子程序(该程序要求延时100ms)。
delay(void)
{ unsigned char i,j;
for(i=250;i>=1;i--)
for(j=200;j>=1;j--)
{}
}
利用keil c的反汇编功能,通过调用disassembly window命令查看到的汇编程序如下。
C:0X0060 7F7D MOV R7,#0XFA
C:0X0062 7F32 MOV R6,#0XC8
C:0X0064 DEFE DJNZ R6,C:0064
C:0X0066 DFFA DJNZ R7,C:0062
C:0X0068 RET
带入所得公式计算结果是100753μs,利用keil c的测试工具得出的延时时间为100755μs,误差是由调用指令引起,后有详细分析。可以得出结论,此处C语言中的for语句不仅与汇编语言中的DJNZ命令起到的作用类似且计算延时的方法也完全相同。即上面得出的公式同样适用于计算用C语言编写的延时程序。下面考虑一个相反的问题,也是本文着重要讨论的。
4 软件延时程序的设计算法
在实际的编程过程中,人们往往想得到一个规定了延时长度的延时子程序,即在已知延时时间的前提下设计循环次数。设计延时程序时应注意使循环的重数尽量少,以减少寄存器的使用量,同时也使程序更加简单,出错的可能性随之降低。其次尽量不使用寄存器R0、R1,因为它们经常用在间接寻址及需要传送外部数据的地方。延时程序具体的编写步骤如下:
1)明确晶振频率,定出延时时间所需的最小循环数;
2)将内层循环设为最大值,即内层循环的寄存器值取0;
3)根据公式确定出不大于所要的延时时间的最外层循环的寄存器的取值;
4)用所要得的延时时间减去上述步骤得出的延时时间,差值作为第二个所要的延时时间,重复步骤1)的做法,直至差值缩小至10μs以内;
5)最后用添加NOP指令的方式来得到精确的延时时间。
例如设计一个延时时间为1s的延时程序。首先1s所属的最小循环为三重循环,将内部寄存器的值设置为0,其次根据公式算出不大于1s的外层循环的最大取值为7,此时得到的延时时间为922904μs,与1s相减余数为77096μs。而77096μs属于的最小循环为二重,当外重循环取149时,得到的延时时间为76738μs,与77096相减余数为358μs。358μs通过一次循环程序配合NOP指令就可以得到。注意到三重循环与二重循环计算公式中占两个机器周期的RET指令已不存在,要用NOP指令补充。因此可得到延时时间为1s的精确程序。
DEL: MOV R5,#7
DEL1:MOV R6,#0
DEL2:MOV R7,#0
DEL3:DJNZ R7,DEL3
DJNZ R6,DEL2
DJNZ R5,DEL1
MOV R6,#149
DEL4:MOV R7,#0
DEL5:DJNZ R7,DEL5
DJNZ R6,DEL4
MOV R7,#177
DEL6:DJNZ R7,DEL6
NOP
NOP
NOP
NOP
NOP
RET
利用keil c的测试工具,在延时程序的开始与结尾设置两个断点,两个断点处的时间差值为1.00000200s。以上程序中2μs的误差是由于没有考虑调用延时程序的指令所占用的机器周期,如ACALL、LCALL指令,将这些指令考虑进去后减去两个NOP指令,这样就得到了精确的1s延时程序。这种方法对于用C语言来设计的延时程序同样适用,下面是利用此法并考虑了调用指令的C语言延时程序。
delay(void)
{ unsigned char i,j,k;
for(k=7;k>=1;k--)
for(j=255;j>=1;j--)
for(i=255;i>=1;i--)
{ }
for(j=164;j>=1;j--)
for(i=255;i>=1;i--)
{}
for(i=66;i>=1;i--)
{}
_NOP_();
_NOP_();
_NOP_();
}
5 总结
本文通过对软件延时程序计算方法的公式化推导,总结了一种精确设计软件延时的数学算法,为分析和设计程序提供了一种新的方法和技巧。无论是对设计精度要求较高的程序还是对设计精度要求一般的程序都应当有使程序更加精确的好习惯,这样不仅可以提高程序的精确度,还可减少程序出错的几率。希望本文在实际问题解决的过程中对大家有所帮助。
参考文献:
[1]余锡存、曹国华,单片机原理及接口技术(第二版)[M].西安:西安电子科技大学出版社,2007.
[2]沈舷,延时程序延时时间的计算[J].电工技术与自动化,2005,(5):154-157.
[3]王超峰,单片机延时程序时间长度的记忆方法[J].单片机与嵌入式系统应用,2002,(7):77-78.
[4]彭志刚,51系列单片机延时程序运行时间的计算[J].仪器仪表用户,2008,(5):102-103.
[5]文桦,彭彦华.单片机应用系统定时时间的误差分析[J].天中学刊,2006,(5):38-39.
[6]admin.C语言编程细节总结[EB].IT达人网,2009-7-15.
作者简介:
韩薇薇(1985-),女,南京理工大学在职硕士研究生,扬州高等职业技术学校电子工程系,助教,主要研究方向:应用电子技术。
关键词: 单片机;软件延时;数学算法
中图分类号:NT 文献标识码:A 文章编号:1671-7597(2011)0310081-02
1 软件延时的基本原理
单片机在进行控制时,CPU过一段时间再去作某件事情,称之为延时。延时分为硬件延时和软件延时。硬件延时是指使用定时/计数器来实现延时,这种方法不占用CPU的工作时间。软件延时是利用程序中的指令在被执行时要花费一定的机器周期来实现的,占用CPU的工作时间。软件延时主要与两个因素有关,一是所用的晶振,二是延时程序的循环次数。单片机所用的晶振一经确定之后,延时时间就被指令的循环次数所唯一确定了,如单片机的晶振频率为6MHz,则一个机器周期为2μs。下面根据指令循环的次数的不同,先来介绍软件延时时长的计算方法(设晶振频率为12MHz)。
2 软件延时时长的计算方法
软件延时常用如表1的汇编指令。
1)单循环延时程序
DEL:MOV R0,#X;1T
DEL1:DJNZ R0,DEL1;2XT
RET;2T
延时时间:t=1+2X+2=2X+3=2R0+3
因为X的取值范围是[0,255],X=0时延时时间最长。所以延时时间t的取值范围是[5,515]μs。
2)二重循环程序
DEL:MOV R1,#Y ;1T
DEL1:MOV R0,#X ;1YT
DEL2:DJNZ R0,DEL2;2XYT
DJNZ R1,DEL1;2YT
RET;2T
延时时间:t=1+1Y+2XY+2Y+2
=2XY+3Y+3=2R0R1+3R1+3
因为X、Y的取值范围均为[0,255],X=Y=0时延时时间最长。所以延时时间t的取值范围是[8,131843]μs。
3)三重循环程序
DEL:MOV R2,#Z ;1T
DEL1:MOV R1,#Y ;1ZT
DEL2:MOV R0,#X ;1YZT
DEL3:DJNZ R0,DEL3;2XYZT
DJNZ R1,DEL2;2YZT
DJNZ R2,DEL1;2ZT
RET;2T
延时时间:
t=1+1Z+1YZ+2XYZ+2YZ+2Z+2
=2XYZ+3YZ+3Z+3
=2R0R1R2+3R1R2+3R2+3
同理,延时时间t的取值范围是[11,33751811]μs。
综上分析,由数学归纳法可得出N(N一般不大于8)重循环的延时时间计算公式:
3 C语言中延时程序的设计方法
在用C语言进行编程时涉及到的软件延时程序,其设计方法与汇编语言的设计方法本质相同。例如,在C语言的一个实例程序中用for语句编写了一个延时子程序(该程序要求延时100ms)。
delay(void)
{ unsigned char i,j;
for(i=250;i>=1;i--)
for(j=200;j>=1;j--)
{}
}
利用keil c的反汇编功能,通过调用disassembly window命令查看到的汇编程序如下。
C:0X0060 7F7D MOV R7,#0XFA
C:0X0062 7F32 MOV R6,#0XC8
C:0X0064 DEFE DJNZ R6,C:0064
C:0X0066 DFFA DJNZ R7,C:0062
C:0X0068 RET
带入所得公式计算结果是100753μs,利用keil c的测试工具得出的延时时间为100755μs,误差是由调用指令引起,后有详细分析。可以得出结论,此处C语言中的for语句不仅与汇编语言中的DJNZ命令起到的作用类似且计算延时的方法也完全相同。即上面得出的公式同样适用于计算用C语言编写的延时程序。下面考虑一个相反的问题,也是本文着重要讨论的。
4 软件延时程序的设计算法
在实际的编程过程中,人们往往想得到一个规定了延时长度的延时子程序,即在已知延时时间的前提下设计循环次数。设计延时程序时应注意使循环的重数尽量少,以减少寄存器的使用量,同时也使程序更加简单,出错的可能性随之降低。其次尽量不使用寄存器R0、R1,因为它们经常用在间接寻址及需要传送外部数据的地方。延时程序具体的编写步骤如下:
1)明确晶振频率,定出延时时间所需的最小循环数;
2)将内层循环设为最大值,即内层循环的寄存器值取0;
3)根据公式确定出不大于所要的延时时间的最外层循环的寄存器的取值;
4)用所要得的延时时间减去上述步骤得出的延时时间,差值作为第二个所要的延时时间,重复步骤1)的做法,直至差值缩小至10μs以内;
5)最后用添加NOP指令的方式来得到精确的延时时间。
例如设计一个延时时间为1s的延时程序。首先1s所属的最小循环为三重循环,将内部寄存器的值设置为0,其次根据公式算出不大于1s的外层循环的最大取值为7,此时得到的延时时间为922904μs,与1s相减余数为77096μs。而77096μs属于的最小循环为二重,当外重循环取149时,得到的延时时间为76738μs,与77096相减余数为358μs。358μs通过一次循环程序配合NOP指令就可以得到。注意到三重循环与二重循环计算公式中占两个机器周期的RET指令已不存在,要用NOP指令补充。因此可得到延时时间为1s的精确程序。
DEL: MOV R5,#7
DEL1:MOV R6,#0
DEL2:MOV R7,#0
DEL3:DJNZ R7,DEL3
DJNZ R6,DEL2
DJNZ R5,DEL1
MOV R6,#149
DEL4:MOV R7,#0
DEL5:DJNZ R7,DEL5
DJNZ R6,DEL4
MOV R7,#177
DEL6:DJNZ R7,DEL6
NOP
NOP
NOP
NOP
NOP
RET
利用keil c的测试工具,在延时程序的开始与结尾设置两个断点,两个断点处的时间差值为1.00000200s。以上程序中2μs的误差是由于没有考虑调用延时程序的指令所占用的机器周期,如ACALL、LCALL指令,将这些指令考虑进去后减去两个NOP指令,这样就得到了精确的1s延时程序。这种方法对于用C语言来设计的延时程序同样适用,下面是利用此法并考虑了调用指令的C语言延时程序。
delay(void)
{ unsigned char i,j,k;
for(k=7;k>=1;k--)
for(j=255;j>=1;j--)
for(i=255;i>=1;i--)
{ }
for(j=164;j>=1;j--)
for(i=255;i>=1;i--)
{}
for(i=66;i>=1;i--)
{}
_NOP_();
_NOP_();
_NOP_();
}
5 总结
本文通过对软件延时程序计算方法的公式化推导,总结了一种精确设计软件延时的数学算法,为分析和设计程序提供了一种新的方法和技巧。无论是对设计精度要求较高的程序还是对设计精度要求一般的程序都应当有使程序更加精确的好习惯,这样不仅可以提高程序的精确度,还可减少程序出错的几率。希望本文在实际问题解决的过程中对大家有所帮助。
参考文献:
[1]余锡存、曹国华,单片机原理及接口技术(第二版)[M].西安:西安电子科技大学出版社,2007.
[2]沈舷,延时程序延时时间的计算[J].电工技术与自动化,2005,(5):154-157.
[3]王超峰,单片机延时程序时间长度的记忆方法[J].单片机与嵌入式系统应用,2002,(7):77-78.
[4]彭志刚,51系列单片机延时程序运行时间的计算[J].仪器仪表用户,2008,(5):102-103.
[5]文桦,彭彦华.单片机应用系统定时时间的误差分析[J].天中学刊,2006,(5):38-39.
[6]admin.C语言编程细节总结[EB].IT达人网,2009-7-15.
作者简介:
韩薇薇(1985-),女,南京理工大学在职硕士研究生,扬州高等职业技术学校电子工程系,助教,主要研究方向:应用电子技术。