51单片机精确延时程序大集合
基于51单片机的精确延时(微秒级)
声明:*此文章是基于51单片机的微秒级延时函数,采用12MHz晶振。
*此文章共包含4个方面,分别是延时1us,5us,10us和任意微秒。
前三个方面是作者学习过程中从书本或网络上面总结的,并非本人所作。
但是延时任意微秒函数乃作者原创且亲测无误。
欢迎转载。
*此篇文章是作者为方便初学者使用而写的,水平有限,有误之处还望大家多多指正。
*作者:Qtel*2012.4.14*QQ:97642651----------------------------------------------------------------------------------------------------------------------序:对于某些对时间精度要求较高的程序,用c写延时显得有些力不从心,故需用到汇编程序。
本人通过测试,总结了51的精确延时函数(在c语言中嵌入汇编)分享给大家。
至于如何在c 中嵌入汇编大家可以去网上查查,这方面的资料很多,且很简单。
以12MHz晶振为例,12MHz 晶振的机器周期为1us,所以,执行一条单周期指令所用时间就是1us,如NOP指令。
下面具体阐述一下。
----------------------------------------------------------------------------------------------------------------------1.若要延时1us,则可以调用_nop_();函数,此函数是一个c函数,其相当于一个NOP指令,使用时必须包含头文件“intrins.h”。
例如:#include<intrins.h>#include<reg52.h>void main(void){P1=0x0;_nop_();//延时1usP1=0xff;}----------------------------------------------------------------------------------------------------------------------2.延时5us,则可以写一个delay_5us()函数:delay_5us(){#pragma asmnop#pragma endasm}这就是一个延时5us的函数,只需要在需要延时5us时调用此函数即可。
51单片机汇编延时程序算法详解
51 单片机汇编延时程序算法详解
51 单片机汇编延时程序算法详解
将以12MHZ 晶振为例,详细讲解MCS-51 单片机中汇编程序延时的精确
算法。
指令周期、机器周期与时钟周期
指令周期:CPU 执行一条指令所需要的时间称为指令周期,它是以机器周期为单位的,指令不同,所需的机器周期也不同。
时钟周期:也称为振荡周期,一个时钟周期=晶振的倒数。
MCS-51 单片机的一个机器周期=6 个状态周期=12 个时钟周期。
MCS-51 单片机的指令有单字节、双字节和三字节的,它们的指令周期不
尽相同,一个单周期指令包含一个机器周期,即12 个时钟周期,所以一条单周期指令被执行所占时间为12*(1/12000000)=1μs。
扩展阅读:单片机有
哪些延时方法详细介绍
程序分析
例1 50ms 延时子程序:。
51单片机延时程序
void delay1s(void)
{
unsigned char h,i,j,k;
for(h=5;h>0;h--)
for(i=4;i>0;i--)
for(j=116;j>0;j--)
for(k=214;k>0;k--);
//
void delay(uint t)
{
for (;t>0;t--);
}
1ms延时子程序(12MHZ)
void delay1ms(uint p)//12mhz
{ uchar i,j;
for(i=0;i<p;i++)
{
for(j=0;j<124;j++)
{;}
在实际应用中,定时常采用中断方式,如进行适当的循环可实现几秒甚至更长时间的延时。使用定时器/计数器延时从程序的执行效率和稳定性两方面考虑都是最佳的方案。但应该注意,C51编写的中断服务程序编译后会自动加上PUSH ACC、PUSH PSW、POP PSW和POP ACC语句,执行时占用了4个机器周期;如程序中还有计数值加1语句,则又会占用1个机器周期。这些语句所消耗的时间在计算定时初值时要考虑进去,从初值中减去以达到最小误差的目的。
}
void Delay10us( ) //12mhz
{
_NOP_( );
_NOP_( );
_NOP_( );
_NOP_( );
_NOP_( );
_NOP_( );
}
/*****************11us延时函数*************************/
Keil C51精确延时程序(C语言)
Keil C51精确延时程序程序说明如下:振荡频率:12MHz机器周期=12/振荡频率=12/12000000=1us#include <reg52.h>void delay1(unsigned char i){ while(--i);}说明:delay1程序为:延时时间=(2*i+2)*机器周期。
i=1~255。
void delay2(unsigned char i){ while(i--);}说明:delay2程序为:延时时间=(6*i+2)*机器周期。
i=1~255。
void main (void){unsigned char m;delay1(10); //赋值并调延时程序delay1说明:本句为赋值并调用Delayus1:延时时间=(1+2)*机器周期。
全部延时时间为:延时时间=(1+2+2*i+2)*机器周期。
i=1~255。
本例:延时时间=(1+2+2*10+2)*1us=25usdelay2(10); //赋值并调延时程序delay2说明:本句为赋值并调用Delayus2:延时时间=(1+2)*机器周期。
全部延时时间为:延时时间=(1+2+6*i+2)*机器周期。
i=1~255。
本例:延时时间=(1+2+6*10+2)*1us=65usm=10; //赋值,m=1~255while(--m) ; //计算,延时时间=2*m*机器周期说明:本两句为赋值并计算。
全部延时时间为:延时时间=(1+2*m)*机器周期。
m=1~255。
本例:延时时间=(1+2*10)*1us=25uswhile(1);}。
51单片机延时时间计算和延时程序设计
一、关于单片机周期的几个概念●时钟周期时钟周期也称为振荡周期,定义为时钟脉冲的倒数(可以这样来理解,时钟周期就是单片机外接晶振的倒数,例如12MHz的晶振,它的时间周期就是1/12 us),是计算机中最基本的、最小的时间单位。
在一个时钟周期内,CPU仅完成一个最基本的动作。
●机器周期完成一个基本操作所需要的时间称为机器周期。
以51为例,晶振12M,时钟周期(晶振周期)就是(1/12)μs,一个机器周期包执行一条指令所需要的时间,一般由若干个机器周期组成。
指令不同,所需的机器周期也不同。
对于一些简单的的单字节指令,在取指令周期中,指令取出到指令寄存器后,立即译码执行,不再需要其它的机器周期。
对于一些比较复杂的指令,例如转移指令、乘法指令,则需要两个或者两个以上的机器周期。
1.指令含义DJNZ:减1条件转移指令这是一组把减1与条件转移两种功能结合在一起的指令,共2条。
DJNZ Rn,rel ;Rn←(Rn)-1;若(Rn)=0,则PC←(PC)+2 ;顺序执行;若(Rn)≠0,则PC←(PC)+2+rel,转移到rel所在位置DJNZ direct,rel ;direct←(direct)-1;若(direct)= 0,则PC←(PC)+3;顺序执行;若(direct)≠0,则PC←(PC)+3+rel,转移到rel 所在位置2.DJNZ Rn,rel指令详解例:MOV R7,#5DEL:DJNZ R7,DEL; rel在本例中指标号DEL1.单层循环由上例可知,当Rn赋值为几,循环就执行几次,上例执行5次,因此本例执行的机器周期个数=1(MOV R7,#5)+2(DJNZ R7,DEL)×5=11,以12MHz的晶振为例,执行时间(延时时间)=机器周期个数×1μs=11μs,当设定立即数为0时,循环程序最多执行256次,即延时时间最多256μs。
2.双层循环1)格式:DELL:MOV R7,#bbDELL1:MOV R6,#aaDELL2:DJNZ R6,DELL2; rel在本句中指标号DELL2DJNZ R7,DELL1; rel在本句中指标号DELL1注意:循环的格式,写错很容易变成死循环,格式中的Rn和标号可随意指定。
51单片机延时程序
51单片机延时程序51单片机延时程序应用单片机的时候,经常会遇到需要短时间延时的情况。
需要的延时时间很短,一般都是几十到几百微妙(us)。
有时候还需要很高的精度,比如用单片机驱动DS18B20的时候,误差容许的范围在十几us 以内,不然很容易出错。
这种情况下,用计时器往往有点小题大做。
而在极端的情况下,计时器甚至已经全部派上了别的用途。
这时就需要我们另想别的办法了。
以前用汇编语言写单片机程序的时候,这个问题还是相对容易解决的。
比如用的是12MHz晶振的51,打算延时20us,只要用下面的代码,就可以满足一般的需要:mov r0, #09hloop: djnz r0, loop51 单片机的指令周期是晶振频率的1/12,也就是1us一个周期。
mov r0, #09h需要2个极其周期,djnz也需要2个极其周期。
那么存在r0里的数就是(20-2)/2。
用这种方法,可以非常方便的实现256us 以下时间的延时。
如果需要更长时间,可以使用两层嵌套。
而且精度可以达到2us,一般来说,这已经足够了。
现在,应用更广泛的毫无疑问是Keil的C编译器。
相对汇编来说,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 # 200000 ?C0007:0000 EF MOV A,R70001 6003 JZ ?C00100003 1F DEC R70004 80FA SJMP ?C0007; SOURCE LINE # 210006 ?C0010:0006 22 RET; FUNCTION _delay2 (END)真是不看不知道~~~一看才知道这个延时程序是多么的不准点~~~光看主要的那四条语句,就需要6个机器周期。
51单片机延时函数
C程序中可使用不同类型的变量来进行延时设计。
经实验测试,使用unsigned char类型具有比unsigned int更优化的代码,在使用时应该使用unsigned char作为延时变量。
以某晶振为12MHz 的单片机为例,晶振为12MHz即一个机器周期为1us。
一. 500ms延时子程序程序:void delay500ms(void){unsigned char i,j,k;for(i=15;i>0;i--)for(j=202;j>0;j--)for(k=81;k>0;k--);}计算分析:程序共有三层循环一层循环n:R5*2 = 81*2 = 162us DJNZ 2us二层循环m:R6*(n+3) = 202*165 = 33330us DJNZ2us + 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二. 200ms延时子程序程序:{unsigned char i,j,k;for(i=5;i>0;i--)for(j=132;j>0;j --)for(k=150;k>0;k --);}三. 10ms延时子程序程序:{unsigned char i,j,k;for(i=5;i>0;i--)for(j=4;j>0;j--)for(k=248;k>0;k --);}四. 1s延时子程序程序:void delay1s(void){unsigned char h,i,j,k;for(h=5;h>0;h--)for(i=4;i>0;i--)for(j=116;j>0;j --)for(k=214;k>0;k --);}关于单片机C语言的精确延时,网上很多都是大约给出延时值没有准确那值是多少,也就没有达到精确高的要求,而本函数克服了以上缺点,能够精确计数出要延时值且精确达到1us,本举例所用CPU为STC12C5412系列12倍速的单片机,只要修改一下参数值其它系例单片机也通用,适用范围宽。
Keil-C51--精确延时--程序执行时间
Keil C51 精确延时程序执行时间引言单片机因具有体积小、功能强、成本低以及便于实现分布式控制而有非常广泛的应用领域[1]。
单片机开发者在编制各种应用程序时经常会遇到实现精确延时的问题,比如按键去抖、数据传输等操作都要在程序中插入一段或几段延时,时间从几十微秒到几秒。
有时还要求有很高的精度,如使用单总线芯片 DS18B20时,允许误差范围在十几微秒以内[2],否则,芯片无法工作。
用51汇编语言写程序时,这种问题很容易得到解决,而目前开发嵌入式系统软件的主流工具为C语言,用C51写延时程序时需要一些技巧[3]。
因此,在多年单片机开发经验的基础上,介绍几种实用的编制精确延时程序和计算程序执行时间的方法。
实现延时通常有两种方法:一种是硬件延时,要用到定时器/计数器,这种方法可以提高CPU的工作效率,也能做到精确延时;另一种是软件延时,这种方法主要采用循环体进行。
1 使用定时器/计数器实现精确延时单片机系统一般常选用11.059 2 MHz、12 MHz或6 MHz晶振。
第一种更容易产生各种标准的波特率,后两种的一个机器周期分别为1 μs和2 μs,便于精确延时。
本程序中假设使用频率为12 MHz的晶振。
最长的延时时间可达216=65 536 μs。
若定时器工作在方式2,则可实现极短时间的精确延时;如使用其他定时方式,则要考虑重装定时初值的时间(重装定时器初值占用2个机器周期)。
在实际应用中,定时常采用中断方式,如进行适当的循环可实现几秒甚至更长时间的延时。
使用定时器/计数器延时从程序的执行效率和稳定性两方面考虑都是最佳的方案。
但应该注意,C51编写的中断服务程序编译后会自动加上PUSH ACC、PUSH PSW、POP PSW和POP ACC语句,执行时占用了4个机器周期;如程序中还有计数值加1语句,则又会占用1个机器周期。
这些语句所消耗的时间在计算定时初值时要考虑进去,从初值中减去以达到最小误差的目的。
51单片机精确延时程序大集合
51单片机精确延时程序大集合51单片机精确延时程序大集合以下程序说是精确延时,实际上都不对。
调用一次差个几微秒、几百微秒,一天下来差好几分钟。
加我的QQ群有精确版本哦,不同频率的晶振都适用。
群:383977592008-04-24 12:10:26,在论坛上看到不少不错的延时程序,整理如下共同分享:精确延时计算公式:延时时间=[(2*第一层循环+3)*第二层循环+3]*第三层循环+5;延时5秒左右DELAY5S:PUSH 04H;2个机器周期PUSH 05H;2个机器周期PUSH 06H;2个机器周期MOV R4,#50;1个机器周期DELAY5S_0:MOV R5,#200;1个机器周期DELAY5S_1:MOV R6,#245;1个机器周期DJNZ R6,$;2×245=490个机器周期DJNZ R5,DELAY5S_1;这条2个机器周期,这层循环包含R5×(490+1)+2×R5=98600个机器周期DJNZ R4,DELAY5S_0;这条2个机器周期,这层循环包含R4×(98600+1)+2×R4=4930150个机器周期POP 06H;2个机器周期POP 05H;2个机器周期POP 04H;2个机器周期RET;2个机器周期;(共2+2+2+1+4930150+2+2+2+2=4930165个机器周期);513微秒延时程序DELAY: MOV R2,#0FEH;1个机器周期JUZINAIYOU: DJNZ R2,JUZINAIYOU;2×R21即2×245RET;2个机器周期;(实际上是493个机器周期);10毫秒延时程序DL10MS: MOV R3,#14HDL10MS1:LCALL DELAYDJNZ R3,DL10MS1RET;(缺DELAY);0.1s延时程序12MHzDELAY: MOV R6,#250DL1: MOV R7,#200DL2: DJNZ R6,DL2DJNZ R7,DL1RET;延时1046549微秒(12MHz);具体的计算公式是:;((((r7*2+1)+2)*r6+1)+2)*r5+1+4 = ((r7*2+3)*r6+3)*r5+5 DEL : MOV R5,#08HDEL1: MOV R6,#0FFHDEL2: MOV R7,#0FFHDJNZ R7,$DJNZ R6,DEL2DJNZ R5,DEL1RET;1秒延时子程序是以12MHz晶振DELAY:MOV R1,#50del0: mov r2,#91del1: mov r3,#100djnz r3,$djnz r2,del1djnz r1,del0Ret;1秒延时子程序是以12MHz晶振为例算指令周期耗时KK: MOV R5,#10 ;1指令周期×1K1: MOV R6,#0FFH ;1指令周期×10K2: MOV R7,#80H ;1指令周期256×10=2560K3: NOP ;1指令周期;128*256*10=327680DJNZ R7,K3 ;2指令周期2*128*256*10=655360DJNZ R6,K2 ;2指令周期2*256*10=5120DJNZ R5,K1 ;2指令周期2*10=20RET;2指令周期;21+10+2560+327680+655360+5120+20+2=990753 ;约等于1秒=1000000微秒;这个算下来也只有0.998抄T_0: MOV R7,#10;D1: MOV R6,#200;D2: MOV R5,#248;DJNZ R5,$DJNZ R6,D2;DJNZ R7,D1;RET;这样算下来应该是1.000011秒T_0: MOV R7,#10;D1: MOV R6,#200;D2: NOPMOV R5,#248;DJNZ R5,$DJNZ R6,D2;DJNZ R7,D1;RETDELAY_2S: ;10MS(11.0592mhz) MOV R3,#200JMP DELAY10MSDELAY_100MS: ;100MS(11.0592mhz) MOV R3,#10JMP DELAY10MSDELAY_10MS:MOV R3,#1DELAY10MS: ;去抖动10MS(11.0592mhz)MOV R4,#20DELAY10MSA:MOV R5,#247DJNZ R5,$DJNZ R4,DELAY10MSADJNZ R3,DELAY10MSRETDELAY_500MS: ;500MSMOV R2,#208JMP DELAY_MSDELAY_175MS: ;175MSMOV R2,#73JMP DELAY_MSdelaY_120MS: ;120MSMOV R2,#50JMP DELAY_MSdelay_60ms: ;60msMOV R2,#25JMP DELAY_MSdelay_30ms: ;30msMOV R2,#12JMP DELAY_MSDELAY_5MS: ;5MSMOV R2,#2;=================================== DELAY_MS:CALL DELAY2400DJNZ R2,DELAY_MSRET;=================================== DELAY2400: ;10x244+4=2447 /1.024=2390 MOV R0,#244 ;1 DELAY24001:MUL AB ;4MUL AB ;4DJNZ R0,DELAY24001 ;2RETDELAY: ;延时子程序(1秒)MOV R0,#0AHDELAY1: MOV R1,#00HJUZINAIYOU: MOV R2,#0B2HDJNZ R2,$DJNZ R1,JUZINAIYOUDJNZ R0,DELAY1RETMOV R2,#10 ;延时1秒LCALL DELAYMOV R2,#50 ;延时5秒LCALL DELAYDELAY: ;延时子程序PUSH R2PUSH R1PUSH R0DELAY1: MOV R1,#00HJUZINAIYOU: MOV R0,#0B2HDJNZ R0,$DJNZ R1,JUZINAIYOU ;延时 100 mSDJNZ R2,DELAY1POP R0POP R1POP R2RET1:DEL: MOV R7, #200DEL1: MOV R6, #123NOPDEL2: DJNZ R6, DEL2DJNZ R7, DEL1RET是50.001ms 算法是:0.001ms+200*0.001ms+200*0.001ms+200*123*0.002ms+2 00*0.002ms ;(123*2+4)*200+12: DEL: MOV R7, #200 DEL1: MOV R6, #123 DEL2:NOPDJNZ R6,DEL2DJNZ R7,DEL1RETD500MS:PUSH PSWSETB RS0MOV R7,#200D51: MOV R6,#250D52: NOPNOPNOPNOPDJNZ R6,D52DJNZ R7,D51POP PSWRETDELAY: ;延时1毫秒PUSH PSW SETB RS0MOV R7,#50D1: MOV R6,#10D2: DJNZ R6,$DJNZ R7,D1POP PSWRETORG 0LJMP MAINORG 000BHLJMP CTC0MAIN: MOV SP, #50HCLR EAMOV TMOD, #01HMOV TH0,#3CHMOV TL0,#0B0HMOV R4, #10SETB ET0SETB EASETB TR0SJMP $ ;CTC0: MOV TH0, #3CHMOV TL0, #0B0HDJNZ R4, LPCPL P1.0MOV R4, #10LP: RETIEND; 定时器中断延时TMOD=0x01; /*定时器0工作在模式1下(16位计数器)*/TH0=0xfd;TL0=0x83;TR0=1; /*启动定时器*/TF0==0;TR0=0;等待中断;100ms定时,11.0592晶振他定时准确啊又不影响程序运行2008-06-10 13:50:46 来源:来于网络,服务大家作者:未知【大中小】点击:9 次下面几个是单片机的延时程序(包括asm和C程序,都是我在学单片机的过程中用到的),在单片机延时程序中应考虑所使用的晶振的频率,在51系列的单片机中我们常用的是11.0592MHz和12.0000MHz的晶振,而在AVR单片机上常用的有8.000MHz和4.000MH的晶振所以在网上查找程序时如果涉及到精确延时则应该注意晶振的频率是多大。
基于51单片机的精确延时(微秒级)
声明:*此文章是基于51单片机的微秒级延时函数,采用12MHz晶振。
*此文章共包含4个方面,分别是延时1us,5us,10us和任意微秒。
前三个方面是作者学习过程中从书本或网络上面总结的,并非本人所作。
但是延时任意微秒函数乃作者原创且亲测无误。
欢迎转载。
*此篇文章是作者为方便初学者使用而写的,水平有限,有误之处还望大家多多指正。
*作者:Qtel*2012.4.14*QQ:97642651----------------------------------------------------------------------------------------------------------------------序:对于某些对时间精度要求较高的程序,用c写延时显得有些力不从心,故需用到汇编程序。
本人通过测试,总结了51的精确延时函数(在c语言中嵌入汇编)分享给大家。
至于如何在c 中嵌入汇编大家可以去网上查查,这方面的资料很多,且很简单。
以12MHz晶振为例,12MHz 晶振的机器周期为1us,所以,执行一条单周期指令所用时间就是1us,如NOP指令。
下面具体阐述一下。
----------------------------------------------------------------------------------------------------------------------1.若要延时1us,则可以调用_nop_();函数,此函数是一个c函数,其相当于一个NOP指令,使用时必须包含头文件“intrins.h”。
例如:#include<intrins.h>#include<reg52.h>void main(void){P1=0x0;_nop_();//延时1usP1=0xff;}----------------------------------------------------------------------------------------------------------------------2.延时5us,则可以写一个delay_5us()函数:delay_5us(){#pragma asmnop#pragma endasm}这就是一个延时5us的函数,只需要在需要延时5us时调用此函数即可。
51单片机延时程序算法详解
51单片机汇编延时程序算法详解将以12MHZ晶振为例,详细讲解MCS-51单片机中汇编程序延时的精确算法。
指令周期、机器周期与时钟周期指令周期:CPU执行一条指令所需要的时间称为指令周期,它是以机器周期为单位的,指令不同,所需的机器周期也不同。
时钟周期:也称为振荡周期,一个时钟周期=晶振的倒数。
MCS-51单片机的一个机器周期=6个状态周期=12个时钟周期。
MCS-51单片机的指令有单字节、双字节和三字节的,它们的指令周期不尽相同,一个单周期指令包含一个机器周期,即12个时钟周期,所以一条单周期指令被执行所占时间为12*(1/12000000)=1μs。
程序分析例1 50ms 延时子程序:DEL:MOV R7,#200 ①DEL1:MOV R6,#125 ②DEL2:DJNZ R6,DEL2 ③DJNZ R7,DEL1 ④RET ⑤精确延时时间为:1+(1*200)+(2*125*200)+(2*200)+2=(2*125+3)*200+3 ⑥=50603μs≈50ms由⑥整理出公式(只限上述写法)延时时间=(2*内循环+3)*外循环+3 ⑦详解:DEL这个子程序共有五条指令,现在分别就每一条指令被执行的次数和所耗时间进行分析。
第一句:MOV R7,#200 在整个子程序中只被执行一次,且为单周期指令,所以耗时1μs 第二句:MOV R6,#125 从②看到④只要R7-1不为0,就会返回到这句,共执行了R7次,共耗时200μs第三句:DJNZ R6,DEL2 只要R6-1不为0,就反复执行此句(内循环R6次),又受外循环R7控制,所以共执行R6*R7次,因是双周期指令,所以耗时2*R6*R7μs。
例2 1秒延时子程序:DEL:MOV R7,#10 ①DEL1:MOV R6,#200 ②DEL2:MOV R5,#248 ③DJNZ R5,$ ④DJNZ R6,DEL2 ⑤DJNZ R7,DEL1 ⑥RET ⑦对每条指令进行计算得出精确延时时间为:1+(1*10)+(1*200*10)+(2*248*200*10)+(2*200*10)+(2*10)+2 =[(2*248+3)*200+3]*10+3 ⑧=998033μs≈1s由⑧整理得:延时时间=[(2*第一层循环+3)*第二层循环+3]*第三层循环+3 ⑨此式适用三层循环以内的程序,也验证了例1中式⑦(第三层循环相当于1)的成立。
Keil C51程序设计中几种精确延时方法 精确延时
Keil C51程序设计中几种精确延时方法2008-04-03 08:48实现延时通常有两种方法:一种是硬件延时,要用到定时器/计数器,这种方法可以提高CPU的工作效率,也能做到精确延时;另一种是软件延时,这种方法主要采用循环体进行。
1 使用定时器/计数器实现精确延时单片机系统一般常选用11.059 2 MHz、12 MHz或6 MHz晶振。
第一种更容易产生各种标准的波特率,后两种的一个机器周期分别为1 μs和2 μs,便于精确延时。
本程序中假设使用频率为12 MHz的晶振。
最长的延时时间可达216=65 536 μs。
若定时器工作在方式2,则可实现极短时间的精确延时;如使用其他定时方式,则要考虑重装定时初值的时间(重装定时器初值占用2个机器周期)。
在实际应用中,定时常采用中断方式,如进行适当的循环可实现几秒甚至更长时间的延时。
使用定时器/计数器延时从程序的执行效率和稳定性两方面考虑都是最佳的方案。
但应该注意,C51编写的中断服务程序编译后会自动加上PUSH ACC、PUSH PSW、POP PSW和POP ACC语句,执行时占用了4个机器周期;如程序中还有计数值加1语句,则又会占用1个机器周期。
这些语句所消耗的时间在计算定时初值时要考虑进去,从初值中减去以达到最小误差的目的。
2 软件延时与时间计算在很多情况下,定时器/计数器经常被用作其他用途,这时候就只能用软件方法延时。
下面介绍几种软件延时的方法。
2.1 短暂延时可以在C文件中通过使用带_NOP_( )语句的函数实现,定义一系列不同的延时函数,如Delay10us( )、Delay25us( )、Delay40us( )等存放在一个自定义的C文件中,需要时在主程序中直接调用。
如延时10 μs 的延时函数可编写如下:void Delay10us( ) {_NOP_( );_NOP_( );_NOP_( )_NOP_( );_NOP_( );_NOP_( );}Delay10us( )函数中共用了6个_NOP_( )语句,每个语句执行时间为1 μs。
单片机延时1ms程序
精确的C语言延时子程序表/自己测试,11.0592M晶振ms延时程序,绝对精确51单片机,需要用MS 延时程序的时候才发现网上的好多程序不好用,下面这个忘记从哪里找的,但是已经相当精确,keil亲测。
=======================================================/*--------------------ms延时函数-----------------------*/void delay_ms(unsigned int ms_number) // ms延时函数(A T89C51 @ 11.0592MHz){unsigned int i;unsigned char j;for(i=0;i<ms;i++){for(j=0;j<200;j++);for(j=0;j<102;j++);}}/--------------------------------------------------------------------用法:在参数传入时填上几就是几毫秒啦比如,想延时100ms,就把ms_number赋值为50×××××××××××××××××××××××××××××××××××××××××××××=============================================以下为原来转载的资料=============================================文章转自Proteus仿真社区作者:liaoguobao00未作验证,如有问题请和原作者联系:lsygrzzh@=============================================用C语言写出来程序非常的简练,它是一种模块化的语言,一种比汇编更高级的语言,但是就是这样一种语言也还是有它不足之处:它的延时很不好控制,我们常常很难知道一段延时程序它的精确延时到底是多少,这和汇编延时程序没法比。
Keil-C51--精确延时--程序执行时间
Keil C51 精确延时程序执行时间引言单片机因具有体积小、功能强、成本低以及便于实现分布式控制而有非常广泛的应用领域[1]。
单片机开发者在编制各种应用程序时经常会遇到实现精确延时的问题,比如按键去抖、数据传输等操作都要在程序中插入一段或几段延时,时间从几十微秒到几秒。
有时还要求有很高的精度,如使用单总线芯片 DS18B20时,允许误差范围在十几微秒以内[2],否则,芯片无法工作。
用51汇编语言写程序时,这种问题很容易得到解决,而目前开发嵌入式系统软件的主流工具为C语言,用C51写延时程序时需要一些技巧[3]。
因此,在多年单片机开发经验的基础上,介绍几种实用的编制精确延时程序和计算程序执行时间的方法。
实现延时通常有两种方法:一种是硬件延时,要用到定时器/计数器,这种方法可以提高CPU的工作效率,也能做到精确延时;另一种是软件延时,这种方法主要采用循环体进行。
1 使用定时器/计数器实现精确延时单片机系统一般常选用11.059 2 MHz、12 MHz或6 MHz晶振。
第一种更容易产生各种标准的波特率,后两种的一个机器周期分别为1 μs和2 μs,便于精确延时。
本程序中假设使用频率为12 MHz的晶振。
最长的延时时间可达216=65 536 μs。
若定时器工作在方式2,则可实现极短时间的精确延时;如使用其他定时方式,则要考虑重装定时初值的时间(重装定时器初值占用2个机器周期)。
在实际应用中,定时常采用中断方式,如进行适当的循环可实现几秒甚至更长时间的延时。
使用定时器/计数器延时从程序的执行效率和稳定性两方面考虑都是最佳的方案。
但应该注意,C51编写的中断服务程序编译后会自动加上PUSH ACC、PUSH PSW、POP PSW和POP ACC语句,执行时占用了4个机器周期;如程序中还有计数值加1语句,则又会占用1个机器周期。
这些语句所消耗的时间在计算定时初值时要考虑进去,从初值中减去以达到最小误差的目的。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
以下程序说是精确延时,实际上都不对。调用一次差个几微秒、几百微秒,一 天下来差好几分钟。加我的 QQ 群有精确版本哦,不同频率的晶振都适用。群: 38397759
2008-04-24 12:10:26,
在论坛上看到不少不错的延时程序,整理如下共同分享:
精确延时计算公式:
for(h=5;h>0;h--) for(i=4;i>0;i--) for(j=116;j>0;j--) for(k=214;k>0;k--); } 200ms 延时子程序(12MHZ) void delay200ms(void) { unsigned char i,j,k; for(i=5;i>0;i--) for(j=132;j>0;j--) for(k=150;k>0;k--); } 500ms 延时子程序程序: (12MHZ) void delay500ms(void) { unsigned char i,j,k; for(i=15;i>0;i--) for(j=202;j>0;j--) for(k=81;k>0;k--); } 下面是用了 8.0000MHZ 的晶振的几个延时程序(用定时 0 的工作模式 1): (1)延时 0.9MS void delay_0_9ms(void) { TMOD=0x01; /*定时器 0 工作在模式 1 下(16 位计数器)*/ TH0=0xfd; TL0=0xa8; TR0=1; /*启动定时器*/ while(TF0==0); TR0=0; } (2)延时 1MS void delay_1ms(void) { TMOD=0x01; /*定时器 0 工作在模式 1 下(16 位计数器)*/ TH0=0xfd; TL0=0x65; TR0=1; /*启动定时器*/ while(TF0==0); TR0=0; } (3)延时 4.5ms void delay_4_5ms(void)
;0.1s 延时程序 12MHz DELAY: MOV R6,#250 DL1: MOV R7,#200 DL2: DJNZ R6,DL2 DJNZ R7,DL1 RET
;延时 1046549 微秒(12MHz) ;具体的计算公式是: ;((((r7*2+1)+2)*r6+1)+2)*r5+1+4 = ((r7*2+3)*r6+3)*r5+5 DEL : MOV R5,#08H DEL1: MOV R6,#0FFH DEL2: MOV R7,#0FFH DJNZ R7,$ DJNZ R6,DEL2 DJNZ R5,DEL1 RET
1:DEL: MOV R7, #200 DEL1: MOV R6, #123 NOP DEL2: DJNZ R6, DEL2 DJNZ R7, DEL1 RET
是 50.001ms 算法是: 0.001ms+200*0.001ms+200*0.001ms+200*123*0.002ms+200*0.002ms
程序如下: DELAY:MOV 72H,#100 LOOP3:MOV 71H,#100 LOOP1:MOV 70H,#47 LOOP0:DJNZ 70H,LOOP0 NOP DJNZ 71H,LOOP1 MOV 70H,#46 LOOP2:DJNZ 70H,LOOP2 NOP DJNZ 72H,LOOP3 MOV 70H,#48 LOOP4:DJNZ 70H,LOOP4 定时器延时: 晶振 12MHZ,延时 1s,定时器 0 工作方式为方式 1 DELAY1:MOV R7,#0AH ;; 晶振 12MHZ,延时 0.5 秒 AJMP DELAY DELAY2:MOV R7,#14H ;; 晶振 12MHZ,延时 1 秒 DELAY:CLR EX0 MOV TMOD,#01H ;设置定时器的工作方式为方式 1 MOV TL0,#0B0H ;给定时器设置计数初始值 MOV TH0,#3CH SETB TR0 ;开启定时器 HERE:JBC TF0,NEXT1 SJMP HERE NEXT1:MOV TL0,#0B0H MOV TH0,#3CH DJNZ R7,HERE CLR TR0 ;定时器要软件清零 SETB EX0 RET C 语言延时程序: 10ms 延时子程序(12MHZ) void delay10ms(void) { unsigned char i,j,k; for(i=5;i>0;i--) for(j=4;j>0;j--) for(k=248;k>0;k--); } 1s 延时子程序(12MHZ) void delay1s(void) { unsigned char h,i,j,k;
MOV R2,#10 ;延时 1 秒 LCALL DELAY MOV R2,#50 ;延时 5 秒 LCALL DELAY DELAY: ;延时子程序 PUSH R2 PUSH R1 PUSH R0 DELAY1: MOV R1,#00H JUZINAIYOU: MOV R0,#0B2H DJNZ R0,$ DJNZ R1,JUZINAIYOU ;延时 100 mS DJNZ R2,DELAY1 POP R0 POP R1 POP R2 RET
DELAY: ;延时 1 毫秒 PUSH PSW SETB RS0 MOV R7,#50 D1: MOV R6,#10 D2: DJNZ R6,$ DJNZ R7,D1 POP PSW RET
ORG 0 LJMP MAIN
ORG 000BH LJMP CTC0 MAIN: MOV SP, #50H CLR EA MOV TMOD, #01H MOV TH0,#3CH MOV TL0,#0B0H MOV R4, #10 SETB ET0 SETB EA SETB TR0 SJMP $ ; CTC0: MOV TH0, #3CH MOV TL0, #0B0H DJNZ R4, LP CPL P1.0 MOV R4, #10 LP: RETI END
K2: MOV R7,#80H ;1 指令周期 256×10=2560 K3: NOP ;1 指令周期
;128*256*10=327680 DJNZ R7,K3 ;2 指令周期
2*128*256*10=655360 DJNZ R6,K2 ;2 指令周期
2*256*10=5120 DJNZ R5,K1 ;2 指令周期 2*10=20 RET;2 指令周期 ;21+10+2560+327680+655360+5120+20+2=990753 ;约等于 1 秒=1000000 微秒
; 定时器中断延时 TMOD=0x01; /*定时器 0 工作在模式 1 下(16 位计数器)*/ TH0=0xfd; TL0=0x83; TR0=1; /*启动定时器*/ TF0==0; TR0=0; 等待中断; 100ms 定时,11.0592 晶振 他定时准确啊又不影响程序运行
2008-06-10 13:50:46 来源:来于网络,服务大家 作者:未知 【大 中 小】 点击: 9次
;这个算下来也只有 0.998 抄 T_0: MOV R7,#10; D1: MOV R6,#200; D2: MOV R5,#248; DJNZ R5,$ DJNZ R6,D2; DJNZ R7,D1; RET
;这样算下来应该是 1.000011 秒 T_0: MOV R7,#10; D1: MOV R6,#200; D2: NOP MOV R5,#248; DJNZ R5,$ DJNZ R6,D2; DJNZ R7,D1; RET
DELAY_2S: ;10MS(11.0592mhz) MOV R3,#200 JMP DELAY10MS DELAY_100MS: ;100MS(11.0592mhz) MOV R3,#10 JMP DELAY10MS
DELAY_10MS: MOV R3,#1 DELAY10MS: ;去抖动 10MS
;(123*2+4)*200+1
2: DEL: MOV R7, #200
DEL1: MOV R6, #123
DEL2:NOP
DJNZ R6,DEL2
DJNZ R7,DEL1
RET
D500MS: PUSH PSW SETB RS0 MOV R7,#200 D51: MOV R6,#250 D52: NOP NOP NOP NOP DJNZ R6,D52 DJNZ R7,D51 POP PSW RET
延时时间=[(2*第一层循环+3)*第二层循环+3]*第三层循环+5
;延时 5 秒左右 DELAY5S:PUSH 04H;2 个机器周期 PUSH 05H;2 个机器周期 PUSH 06H;2 个机器周期 MOV R4,#50;1 个机器周期 DELAY5S_0:MOV R5,#200;1 个机器周期 DELAY5S_1:MOV R6,#245;1 个机器周期 DJNZ R6,$;2×245=490 个机器周期 DJNZ R5,DELAY5S_1;这条 2 个机器周期,这层循环包含 R5×(490+1) +2×R5=98600 个机器周期 DJNZ R4,DELAY5S_0;这条 2 个机器周期 ,这层循环包含 R4×(98600+1) +2×R4=4930150 个机器周期 POP 06H;2 个机器周期 POP 05H;2 个机器周期 POP 04H;2 个机器周期 RET;2 个机器周期 ;(共 2+2+2+1+4930150+2+2+2+2=4930165 个机器周期 )
;513 微秒延时程序 DELAY: MOV R2,#0FEH;1 个机器周期 JUZINAIYOU: DJNZ R2,JUZINAIYOU;2×R21 即 2×245 RET;2 个机器周期 ;(实际上是 493 个机器周期)