STC单片机C语言精确延时值的计算

合集下载

如何用C语言写精确的延时程序

如何用C语言写精确的延时程序

如何用C语言写精确的延时程序/s/blog_7ceb2d560102v0ds.html2014假设一个延时函数如下:void delay(){uint i;for(i=0;i<20000;i++);}我们怎么来算呢,先将20000转成16进制,得到4E20,然后将高字节4E乘以6得到468D,再将468+2=470,然后将470D*20HEX (即32D)=15040;所心这个延时函数总共要执行15040个周期,假设所用的晶振为12MHZ,则该段函数总延时:15.04ms。

有了这个公式我们如果想要设定指定的延时长度就可以用它的己知公式确定。

即:总时间=[(6*i值的高8位)+2]*i的低8位。

例如:设要延时125ms。

我们将低字节先赋值200D*(即:C8),然后再算高低节的定值,由式中可知125ms=200*((i值的高字节*6)+2),又可推算出(高低节*6)+2的总延迟时间应等于625us,将625/6=104.1666,取整数得到104,将104转成16进制得到68H,再将高字节和低字节组合起来即得到了定值,即:68C8HEX,代入函数即如下:void delay(){uint i;for(i=0;i<0x68C8;i++);}如果写直进行就要将68C8转成10进制,即:26824,代入后得到:void delay(){uint i;for(i=0;i<0x26824;i++);在c语言中嵌入一段汇编的延时程序呀,你自己看看书,很简单的用在单片机里的可以C和汇编混合使用,因为用汇编编写延时要准确些,所以你不妨写一个汇编程序,然后再调用它好了,要用C来编精确的延时确实是比较难的哦.呵呵谁说C语言不能精确延时,用51单片机的定时/计数器一或者用定时/计数器2的工作方式2,自动再装入8位计数器,就可以精确延时,别说1MS了就是100um也能精确做到。

其实很简单,采用定时器,将需要定时时间算好后写入单片机中断程序中即可,这种方法可以实现精确定时,最终的误差仅由晶振来确定了。

STC12延时函数的探究

STC12延时函数的探究

STC12延时函数的探究
这种写法是C中嵌套了汇编。

精确延时时间
=2*t*T+5*T,T为一个机器周期。

对于8051,
如果t=1,那么这个函数执行应该是7us。

如果是STC12,那么这个延时函数的延时应该是:若t=1,精确延时
=2*1*1/12+5*1/12=(7/12)us啊。

昨天也查了STC12手册手册上对时钟写的很笼统,其中一句话是:与8051指令执行时间对比,一共有12个指令,一个时钟就可以执行完成,工作在相同频率下运行速度
提高8~12倍
难道这里应该是(7/8)us?而不是(7/12)us?
这个是uint型函数时间是近似的
那么可以用延时时间=8*t*T
应该是8*1*(1/12)=8/12
根据程序分析猜想t=1时这个延时函数应该为1us最为合理。

用示波器测试过执行一个delay(5000)大约5.8ms。

51执行一个delay(5000)大约40064us
嗯,用示波器测得那个IO口的频率变化为85.47HZ,那
么一个delay(5000)就是(1/85.47)/2*1000=5850us
这里的t设的uint型,有误差,加上 LED=1;LED=0;执行也会消耗时间结果存在误差。

最后总结得出这条延时语句在51上执行一次大约花7us,在12上花1us。

示波器测试通过!和我计算符合。

STC指令延时精确计算

STC指令延时精确计算

STC 单片机指令精确延时分析guoguo适用单片机:STC-1T ,晶振12MHz例1:Delayus( ) —— 延时能力2~256usC51代码:/*****延时us***************************************** 功能:延时i+1 us ,包含调用时间* 参数:无* 描述:适用于STC1T 单片机,晶振12MHz* 时钟周期0.08333us ,机器周期0.125us* 特别说明:编译器优化等级设为0,i 的有效范围1~255* 作者:张国营* 日期:2013-10-12*****************************************************/void delay10us(void) //包含调用时间,误差 0us{uchar i=9;do{_nop_();_nop_();_nop_();i--;}while(i);} 编译后的汇编代码:Keil 编译器优化等级0时钟周期Code 地址 机器码 汇编指令 备注 6 LCALL addr16 无参数调用 2 C:0x0C29 753709 MOV 0x37,#0x09 初始化局部变量 1 C:0x0C2C 00 NOP循环1us 1 C:0x0C2D 00 NOP1 C:0x0C2E 00 NOP 4 C:0x0C2F 1537 DEC 0x372 C:0x0C31 E537 MOV A,0x373 C:0x0C33 70F7 JNZ C:0C2C4 C:0x0C35 22 RET 返回计算公式,T=[(6+2)+ i *(3+4+2+3)+ 4 ] / 12= (12+12 * i)/12 =1+i 单位us 局部变量n=9时,延时10us ;n=99时,延时100us例2:Delayms( )——延时能力1~255ms ,误差约为 +1.25usC51代码:/*******************延时ms************************************* * 适用于STC1T 单片机,晶振12MHz ,时钟周期0.08333us ,机器周期0.125us * 延时能力:n = 1~255 ms ,误差为 +1.25 us* 特别说明:编译器优化等级设为0*******************************************************************/ void delayms(uchar n) //精确延时,包含调用时间,{uchar i,j;//---------循环体精确延时n ms-------------------do{ //约延时[(i+1)*j+1]*n us _nop_();j = 9;do{ //约延时 (i+1)*j us _nop_();i = 110;do{ //精确延时 i us _nop_();_nop_();_nop_();i--;}while(i);j--;}while(j);n--;}while(n);}编译后的汇编代码:Keil 编译器优化等级0时钟周期Code 地址 机器码 汇编指令 备注 2 C:0x0BB7 7F32 MOV R7,#0x32 含参数调用 6 C:0x0BB9 120BFB LCALL delayms(C:0BDB)3 C:0x0BDB 8F2F MOV 0x2F,R7 传递参数1 C:0x0C04 00 NOP n 循环:1us2 C:0x0C05 753109 MOV 0x31,#0x091 C:0x0C08 00 NOP j 循环:1us2 C:0x0C09 75306E MOV 0x30,#0x6E1 C:0x0C0C 00 NOPi 循环:1 us 1 C:0x0C0D 00 NOP1 C:0x0C0E 00 NOP 4 C:0x0C0F 1530 DEC 0x302 C:0x0C11 E530 MOV A,0x303 C:0x0C13 70F7 JNZ C:0C0C4 C:0x0C15 1531 DEC 0x31j 循环:1us2 C:0x0C17 E531 MOV A,0x313 C:0x0C19 70ED JNZ C:0C084 C:0x0C1B 152F DEC 0x2Fn 循环:1us2 C:0x0C1D E52F MOV A,0x2F3 C:0x0C1F 70E3 JNZ C:0C044 C:0x0C21 22 RET 返回计算公式,T= {15+n * [ j *(i * 12+12)+ 12 ] }/ 12=15/12+n*[ j*(i+1)+1],单位us 将i=110,j=9代入上式得:T=1000 * n+1.25宁夏成泰电子科技有限公司 * 研发部张国营。

单片机中延时时间怎样计算

单片机中延时时间怎样计算

单片机中延时时间怎样计算
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 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
二. 200ms 延时子程序
程序:。

单片机延时计算公式

单片机延时计算公式

单片机延时计算公式单片机是一种应用广泛的微型计算机系统,它被广泛应用于嵌入式系统、电子设备等领域。

在单片机的编程过程中,经常需要进行延时操作,以控制系统的运行速度或实现特定的功能。

为了准确地控制延时时间,需要使用延时计算公式。

延时时间与单片机的时钟频率有关,通常以秒、毫秒、微秒等单位来表示。

在单片机中,时钟频率是一个基本参数,它决定了单片机每秒钟所执行的指令数。

延时计算公式可以通过时钟频率和所需延时时间来计算出延时所需的指令数。

延时计算公式的一般形式如下:延时指令数 = 延时时间× 时钟频率其中,延时指令数表示需要延时的指令数目,延时时间表示所需延时的时间,时钟频率表示单片机的时钟频率。

在实际应用中,延时时间一般以毫秒或微秒为单位。

为了方便计算,可以将延时时间转换为秒,再根据单片机的时钟频率进行计算。

假设延时时间为T秒,时钟频率为f Hz,则延时指令数可以表示为:延时指令数= T × f延时指令数一般为整数,表示需要延时的指令数目。

在单片机编程中,可以通过循环执行空操作指令或者通过定时器来实现延时操作。

通过控制循环次数或者定时器的设置,可以实现精确的延时时间。

需要注意的是,延时计算公式中的时钟频率必须与实际使用的时钟频率相一致。

在单片机编程中,时钟频率一般通过设置寄存器来进行配置。

如果延时计算公式中的时钟频率与实际使用的时钟频率不一致,将会导致延时时间的不准确。

延时计算公式在单片机编程中具有重要的作用。

通过合理地计算延时指令数,可以实现精确的延时操作,从而实现系统的稳定运行和功能的正常实现。

在实际应用中,需要根据具体的需求和系统的要求,选择合适的延时时间和时钟频率,以确保系统的性能和功能的准确性。

总结起来,单片机延时计算公式是一种根据延时时间和时钟频率来计算延时指令数的方法。

通过合理地计算延时指令数,可以实现精确的延时操作,保证系统的稳定运行和功能的正常实现。

在单片机编程中,合理地应用延时计算公式,可以提高系统的性能和功能的准确性。

单片机C语言延时程序计算

单片机C语言延时程序计算

2 软件延时与时间计算
在很多情况下,定时器/计数器经常被用作其他用途,这时候就只能用软件方法延时。下面介绍几种软件延时的方法。
2.1 短暂延时
可以在C文件中通过使用带_NOP_( )语句的函数实现,定义一系列不同的延
单片机系统一般常选用11.059 2 MHz、12 MHz或6 MHz晶振。第一种更容易产生各种标准的波特率,后两种的一个机器周期分别为1 μs和2 μs,便于精确延时。本程序中假设使用频率为12 MHz的晶振。最长的延时时间可达216=65 536 μs。若定时器工作在方式2,则可实现极短时间的精确延时;如使用其他定时方式,则要考虑重装定时初值的时间(重装定时器初值占用2个机器周期)。
80us 1 1 48 0
90us 1 1 55 +0.5
}
延时时间 a的值 b的值 c的值 延时误差(us)
10us 1 1 1 -0.5
1ms 1 3 219 -1.5
2ms 2 3 220 +3
900us
9 1 63 -1.5
60us 1 1 35 +0.5
70us 1 1 42 +1
在实际应用中,定时常采用中断方式,如进行适当的循环可实现几秒甚至更长时间的延时。使用定时器/计数器延时从程序的执行效率和稳定性两方面考虑都是最佳的方案。但应该注意,C51编写的中断服务程序编译后会自动加上PUSH ACC、PUSH PSW、POP PSW和POP ACC语句,执行时占用了4个机器周期;如程序中还有计数值加1语句,则又会占用1个机器周期。这些语句所消耗的时间在计算定时初值时要考虑进去,从初值中减去以达到最小误差的目的。
300us 3 1 63 +1.5

STC单片机C语言精确延时值的计算

STC单片机C语言精确延时值的计算

单片机C语言精确延时值的计算编者:有梦人生2009年09月12日请读者尊重版权不明之处联系长江单片QQ群:57638937关于单片机C语言的精确延时,网上很多都是大约给出延时值没有准确那值是多少,也就没有达到精确高的要求,而本函数克服了以上缺点,能够精确计数出要延时值且精确达到1us,本举例所用CPU为STC12C5412AD系列单片机12M的外部晶振,只要修改一下参数值其它系例单片机也通用,适用范围宽。

共有三条延时函数说明如下:函数调用分两级:一级是小于10US的延时,二级是大于10US的延时//=====================小于10US的【用1US级延时】=========================for(i=X;i>0;i--)延时时间=(3+5*X)/12 提示(单位us, X不能大于255)如延时1.9Us: for(i=4;i>0;i--);反汇编如下图://================大于10US<小于21.9955Ms的可用【10US级延时函数】===========void Delay10us(uchar Ms){uchar data i;for(;Ms>0;Ms--)for(i=26;i>0;i--);}i=[(延时值-1.75)*12/Ms=15]如想延时60US则i=[(60-1.75)*12/6-15]/4=25.375≈26; 修改i的值=26,再调用上面的【10US级延时函数】Delay10us(6); 则就精确延时60US;如果想延时64US可以用这二种函数组合来用: Delay10us(6); for(i=9;i>X;i--) 共延时64US//=================对于大于20Ms的可用中断来实现程序运行比较好===============中断用定时器0, 1Ms中断:void timer0(void) interrupt 1{TL0=(0xffff-1000+3)%0x100;TH0=(0xffff-1000+3)/0x100; //每1毫秒if(DelayMs_1>0)DelayMs_1--; //大于20Ms延时程序}函数调用void DelayMs(uint a)//延时a×1(ms)的时间。

单片机C语言延时计算

单片机C语言延时计算

单片机C语言延时计算单片机是一种集成电路芯片,内部集成了微处理器、存储器、输入输出接口等主要部件。

C语言是常用的单片机编程语言,可以通过编写C程序来实现单片机的控制和功能。

在单片机编程中,延时是一种常用的操作,用于控制程序执行过程中的时间间隔。

延时的实现方法有多种,可以使用循环遍历、定时器、外部中断等方式。

在循环遍历的延时方法中,可以通过设定一个循环次数来实现延时。

具体的延时时间与循环的次数成正比关系。

例如,在一个8位单片机中,循环一次大约需要4个机器周期,因此可以通过适当设置循环次数来达到需要的延时时间。

但是,使用循环遍历的延时方法会占用CPU资源,可能会影响其他任务的执行。

另一种常用的延时方法是使用定时器。

单片机内部通常集成了一个或多个定时器,可以通过设置定时器的初值和工作模式来实现精确的延时。

例如,可以通过设置定时器的计数值和工作频率来计算出延时的时间。

在定时器工作期间,单片机可以继续执行其他任务,不会占用过多的CPU资源。

除了循环遍历和定时器方法外,还可以使用外部中断的方式来实现延时。

具体的实现方法是通过外部信号触发中断,并在中断处理程序中实现延时功能。

这种方法可以根据外部信号的频率和工作模式来调整延时时间。

在单片机编程中,为了提高代码的可读性和可重用性,可以将延时操作封装成函数。

例如,可以定义一个名为delay的函数,函数的参数为延时的时间(单位为毫秒),函数内部通过循环遍历、定时器或外部中断的方式实现延时。

延时的时间计算可以考虑单片机的工作频率、机器周期以及延时的时间要求。

单片机的工作频率可以由时钟源来决定,一般可以通过设置分频系数来调整。

机器周期是单片机执行一条指令所需的时间,通过单片机的数据手册可以查到相关的数据。

根据单片机的工作频率和机器周期,可以计算出所需的循环次数或定时器计数值。

在使用延时功能时需要注意延时时间的准确性和可调性。

准确性是指延时的实际时间与预期时间之间的误差,通过调整循环次数或定时器计数值可以实现较高的准确性。

STC12单片机精确定时

STC12单片机精确定时

STC12C5A60S2单片机软件延时分类全部都是本人通过示波器反复测量得到1~255倍内精确延时。

误差绝对不会超过5%。

仅限STC12系列的单片机,如需传统51单片机软件延时,请自己计算。

本延时仅限运用在stc12系列单片机上,仅限11.0592mhz。

100us以上的延时可以根据晶振的倍数扩大或缩小循环倍数,以得到相应的延时。

100us以下需改动需要重新测算。

void delay1s(unsigned char n){unsigned char i,j,k;for(;n>0;n--)for(i=83;i>0;i--)for(j=202;j>0;j--)for(k=162;k>0;k--);}void delay500ms(unsigned char n){unsigned char i,j,k;for(;n>0;n--)for(i=83;i>0;i--)for(j=202;j>0;j--)for(k=81;k>0;k--);}void delay100ms(unsigned char n){unsigned char i,j,k;for(;n>0;n--)for(i=83;i>0;i--)for(j=40;j>0;j--)for(k=82;k>0;k--);}void delay10ms(unsigned char n){unsigned char i,k;for(;n>0;n--)for(i=169;i>0;i--)for(k=162;k>0;k--);}void delay1ms(unsigned char n) {unsigned char i,k;for(;n>0;n--)for(i=167;i>0;i--)for(k=15;k>0;k--);}void delay140us(unsigned char n) {unsigned char i,k;for(;n>0;n--)for(i=17;i>0;i--)for(k=21;k>0;k--);}void delay100us(unsigned char n) {unsigned char i,k;for(;n>0;n--)for(i=17;i>0;i--)for(k=15;k>0;k--);}void delay10us(){unsigned char i;for(i=23;i>0;i--);}void delay5us(){unsigned char i;for(i=9;i>0;i--);}#define delay1us(); {_nop_();_nop_();_nop_();_nop_();};。

单片机 延时 计算

单片机 延时 计算

单片机延时计算
在单片机编程中,延时是一种常用的控制方法。

延时的基本原理是利用单片机内部的计时器来实现时间的计算。

以下是一个简单的延时计算程序的中文代码:
1. 定义延时时间
首先需要定义需要延时的时间,例如下面的代码定义了一个需要延时10毫秒的时间:
unsigned int delay_time = 10;
2. 计算延时时间
接下来需要编写延时计算的函数,在这个函数中需要使用单片机内部的计时器来实现时间的计算。

以51单片机为例,我们可以使用定时器和定时器中断来实现延时计算。

具体代码如下:
void delay(unsigned int time) // time为需要延时的时间(单位:毫秒)
{
unsigned char i, j;
while (time--)
{
i = 10;
j = 120;
do
{
while (--j);
} while (--i);
}
}
3. 调用延时函数
最后,在需要进行延时的地方调用延时函数即可,例如下面的代
码在执行delay函数后会延时10毫秒:
delay(delay_time);
以上就是一个简单的中文延时计算程序,希望能对你有所帮助。

c语言延时程序的计算方法经典

c语言延时程序的计算方法经典
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秒
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)
{
TMOD=0x01; /*定时器0工作在模式1下(16位计数器)*/
TH0=0xf4;
TL0=0x48;
TR0=1; /*启动定时器*/
while(TF0==0);
TR0=0;
}
}
1s延时子程序(12MHZ)
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--);
}
200ms延时子程序(12MHZ)
void delay200ms(void)

用单片机C语言精确延时(定时)的方法

用单片机C语言精确延时(定时)的方法

用单片机C语言精确延时(定时)的方法用单片机C语言精确延时(定时)的方法C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。

那么用单片机C语言精确延时(定时)的方法都是怎样的呢?以下仅供参考!由于单片机C语言下利用软件延时不容易做到精确的定时,所以很多人在编写延时子程序的时候不能好好的把握延时的具体时间。

C 语言下,延时程序主要有以下几种:一:void delay(unsigned char k){unsigned char i,k; //定义变量for(i=0;i<k;i++); //for循环语句}该程序在Keil环境下,会先将C语言转化成汇编语言,那么我们就可以根据汇编语言来计算出精确的`时间,转化具体步骤如下:CLR A ;指令1MOV R7,A ;指令2LOOP:INC R7 ;指令3CJNE R7,k,LOOP ;指令4这里,指令1,指令2和指令3各消耗1个机器周期,指令4消耗两个机器周期(可查文末附录表),而在12M的晶振下一个机器周期是1us,在这个过程中,指令1和指令2分别执行1次,即消耗1+1us,而指令3和指令4分别执行了k次,那么这样加起来,这个延时子程序所消耗的具体时间就是t=1+1+(1+2)*k=3k+2us。

呵呵,这样说来,如果我们定义的k为100的话,这个延时子程序的精确时间就是302us。

二:void delay(unsigned char i){while(--i){;}}同样的道理,将其反汇编,可以看到,只有一条语句:DJNZ i,$;该语句消耗2us,一共执行i次,所以总共消耗时间t=i*2us。

三:下面的将形参换为整形int,这样的话,反汇编所执行的语句完全不同,用个具体的数字做例子:void delay(){unsigned int i=10000;while(--i);}反汇编后:4: unsigned int i=10000;C:0x0003 7F10 MOV R7,#0x10C:0x0005 7E27 MOV R6,#0x275: while(--i)6: ;C:0x0007 EF MOV A,R7C:0x0008 1F DEC R7C:0x0009 7001 JNZ C:000CC:0x000B 1E DEC R6C:0x000C 14 DEC AC:0x000D 4E ORL A,R6C:0x000E 70F7 JNZ C:0007具体计算如下1.R7经过10H(16)次循环减为0:t1=10H*(1+1+2+1+1+2)2.R6经过27H*256次循环减为0:t2=27H*256*(1+1+2+1+1+2)+27H*13.最后R7的是变为255,因此还要多出255次的循环:t3=255*(1+1+2+1+1+2)4.加上之前消耗的2us,总消耗时间:T=2+10H*(1+1+2+1+1+2)+27H*256*(1+1+2+1+1+2)+27H*1+255*(1+1+2+1+1+2)=2+16*7+39*256*7+39*1+255*7=71826us大约为72ms吧如果定义一个unsigned int i,那么延时计算公式为T=2+(i%256)*7+(i/256)*256*7+i/256+255*7关于其他类型的延时程序都可以按照这个方法对时间进行较为精确的计算。

单片机C语言的延时计算

单片机C语言的延时计算

标准的C语言中没有空语句。

但在单片机的C语言编程中,经常需要用几个空指令产生短延时的效果。

这在汇编语言中很容易实现,写几个nop就行了。

在keil C51中,直接调用库函数:#include<intrins.h> // 声明了void _nop_(void);_nop_(); // 产生一条NOP指令作用:对于延时很短的,要求在us级的,采用“_nop_”函数,这个函数相当汇编NOP 指令,延时几微秒。

NOP指令为单周期指令,可由晶振频率算出延时时间,对于12M晶振,延时1uS。

对于延时比较长的,要求在大于10us,采用C51中的循环语句来实现。

在选择C51中循环语句时,要注意以下几个问题第一、定义的C51中循环变量,尽量采用无符号字符型变量。

第二、在FOR循环语句中,尽量采用变量减减来做循环。

第三、在do…while,while语句中,循环体内变量也采用减减方法。

这因为在C51编译器中,对不同的循环方法,采用不同的指令来完成的。

下面举例说明:unsigned char I;for(i=0;i<255;i++);unsigned char I;for(i=255;i>0;i--);其中,第二个循环语句C51编译后,就用DJNZ指令来完成,相当于如下指令:MOV09H,#0FFHLOOP:DJNZ09H,LOOP指令相当简洁,也很好计算精确的延时时间。

同样对do…while,while循环语句中,也是如此例:unsigned char n;n=255;do{n--}while(n);或n=255;while(n){n--};这两个循环语句经过C51编译之后,形成DJNZ来完成的方法,故其精确时间的计算也很方便。

其三:对于要求精确延时时间更长,这时就要采用循环嵌套的方法来实现,因此,循环嵌套的方法常用于达到ms级的延时。

对于循环语句同样可以采用for,do…while,while结构来完成,每个循环体内的变量仍然采用无符号字符变量。

C语言精确延时方法

C语言精确延时方法

C语言精确延时方法有些特殊的应用会用到比较精确的延时(比如DS18B20等),而C不像汇编,延时精准度不好算。

本人经过反复调试,对照KEIL编译后的汇编源文件,得出了以下几条精确延时的语句(绝对精确!本人已通过实际测试),今天贴上来,希望对需要的朋友有所帮助。

sbit LED = P1^0; // 定义一个管脚(延时测试用)unsigned int i = 3; // 注意i,j的数据类型,unsigned char j = 3; // 不同的数据类型延时有很大不同//-----------------各种精确延时语句-----------------------------------while( (i--)!=1 ); // 延时10*i个机器周期i = 10; while( --i ); // 延时8*i+2个机器周期i = 10; while( i-- ); // 延时(i+1)*9+2个机器周期j = 5; while( --j ); // 延时2*j+1个机器周期j = 5; while( j-- ); // 延时(j+1)*6+1个机器周期i = 5;while( --i ) // 延时i*10+2个机器周期,在i*10+2个机器周期if( LED==0 ) break; // 内检测到LED管脚为低电平时跳出延时i = 5;while( LED ) // 每隔10个机器周期检测一次LED管脚状态,当LEDif( (--i)==0 ) break;// 为低时或者到了10*i+2个机器周期时跳出延时//--------------------------------------------------------------------例如18b20的复位函数(12M晶振)://************************************************************* **********// 函数功能:18B20复位// 入口参数:无// 出口参数:unsigned char x: 0:成功 1:失败//************************************************************* **********unsigned char ow_reset(void){unsigned char x=0; // 12M晶振 1个机器周期为1usDQ = 1; // DQ复位j = 10; while(--j);// 稍做延时(延时10*2+1=21个机器周期,21us)DQ = 0; // 单片机将DQ拉低j = 85; while(j--);// 精确延时(大于480us) 85*6+1=511usDQ = 1; // 拉高总线j = 10; while(j--);// 精确延时10*6+1=61usx = DQ; // 稍做延时后,return x; // 如果x=0则初始化成功 x=1则初始化失败j = 25; while(j--);// 精确延时25*6+1=151us}//************************************************************* ********************再如红外解码程序:(先说传统红外解码的弊端:程序中用了while(IR_IO);while(!IR_IO);这样的死循环,如果管脚一直处于一种状态,就会一直执行while,造成“死机”现象。

关于单片机C语言的精确延时

关于单片机C语言的精确延时
一、函数调用分两级:一级是小于10US的延时,二级是大于10US的延时 //====================小于10US的【用1US级延时】==================== //----------微秒级延时--------for(i=X;i>0;i--) 延时时间=(3+5*X)/12 提示(单位us, X不能大于255)
for(i = 0; i < 600; i++); } } /********************************************************************************************
/******************************************************************************************** void main (void){ //主程序 while(1){
LED = ~LED; //取LED相反状态 DELAY_MS(1000); //修改这里的数值看看会有什么变化 }
} /******************************************************************************************** - 应用实例
可将其模板下载到本地硬盘,在编写新程序的时候复制、粘贴到工程当 中,然后根据情况写入具体内容。
- 使用说明
data unsigned char cou = 0; // 定义软计数器,放在程序最前面的寄存 器定义部分
/********************************************************************************************

STC准确延时

STC准确延时

作者:韩超QQ:404526890 如文章有误请联系作者更正,共同交流学习Void main(void){delay_us(200); // STC具体执行时间}C:0x0019 7FC8 MOV R7,#P5(0xC8)//将延时值写入R7寄存器C:0x001B 12000F LCALL delay_us(C:000F)//跳转到延时函数void delay_us(unsigned char Nus){for(;Nus>0;Nus--);}C:0x000F EF MOV A,R7 //将延时值放入累加器AC:0x0010 D3 SETB C //进位标志置1C:0x0011 9400 SUBB A,#0x00 //累加器A减借位标志C再减0C:0x0013 4003 JC C:0018 //进位标志置位则跳转C:0x0015 1F DEC R7 //R7减1C:0x0016 80F7 SJMP delay_us(C:000F)//无条件跳转至延时函数备注:以上单位为时钟周期,即晶振频率的倒数Delay(0);详细执行时间如下时间=MOV1+LCALL +MOV2+SETB+SUBB +JC+RETSTC90(6T):60个时钟周期STC12(1T):19个时钟周期STC15(1T)17个时钟周期Delay(1);详细执行时间如下时间=MOV1+LCALL +MOV2+SETB+SUBB +JC+DEC+SJMP+MOV2+SETB+SUBB +JC+RET Delay(2);详细执行时间如下时间=MOV1+LCALL +MOV2+SETB+SUBB +JC+DEC+SJMP+MOV2+SETB+SUBB +JC+DEC+SJMP +MOV2+SETB+SUBB +JC+RETDelay(N);详细执行时间如下(N>1)时间=MOV1+LCALL +MOV2+SETB+SUBB +JC+RET+(MOV2+SETB+SUBB +JC+DEC+SJMP)*N STC90(6T):60+ 48*N个时钟周期STC12(1T):19+ 13*N个时钟周期STC15(1T)17+12*N个时钟周期STC (12T) 120+96*N个时钟周期void main (void){ while(1){ delay_us(200); } }C:0x0020 7FC8 MOV R7,#P5(0xC8) //将延时低八位送入R7C:0x0022 7E00 MOV R6,#0x00 //将延时高八位送入R7C:0x0024 120003 LCALL delay_us(C:0003)//跳转至延时函数void delay_us(unsigned int Nus){ for(;Nus>0;Nus--); }C:0x0003 D3 SETB C //进位标志置1C:0x0004 EF MOV A,R7 //将延时低八位送入累加器AC:0x0005 9400 SUBB A,#0x00//累加器A减借位标志C再减0C:0x0007 EE MOV A,R6 //将延时高八位送入累加器AC:0x0008 9400 SUBB A,#0x00//累加器A减借位标志C再减0C:0x000A 4007 JC C:0013 //进位标志置位则跳转C:0x000C EF MOV A,R7//将延时低八位送入累加器AC:0x000D 1F DEC R7 //R7减1C:0x000E 70F3 JNZ delay_us(C:0003)//累加器A非零跳转至(延时函数头部)C:0x0010 1E DEC R6//R6减1C:0x0011 80F0 SJMP delay_us(C:0003)//无条件跳转至延时函数C:0x0013 22 RET //延时子程序返回长延时Delay(N);详细执行时间如下(N>1)STC90(6T):78+ 66*N+(N-255)*18个时钟周期STC12(1T):24+ 17*N+(N-255)*6个时钟周期STC15(1T)22+17*N+(N-255)*5个时钟周期STC (12T) 156+132*N+(N-255)*36个时钟周期。

单片机精确延时计算和中断定时

单片机精确延时计算和中断定时

单片机精确延时计算和中断定时单片机精确延时计算和定时中断一.延时1. 10ms延时程序(for循环嵌套)*************************************************************** ****** 文件名称:void delay_10ms()功能:10ms延时参数:单片机晶振12MHz*************************************************************** ****** void delay_10ms(){unsigned int i, j;for(i=0;i<10;i++){for(j=0;j<124;j++);}}i 和j 定义为int整型时,for循环执行时间为8个机器周期,当i 和j 定义为char 字符型时,for 循环执行时间3个机器周期。

“;”一个机器周期,每次调用for循环2个机器周期。

则执行本段延时程序是内循环时间t1=8*124+3个机器周期,其中“8”执行for循环指令时间;“124”为for循环次数;“3”为每次调用for循环指令的时间。

外循环t2=t1*10+8*10+3其中“10”为for循环次数;“8”为一次for循环指令调用和执行时间;“10”为调用for循环次数,3为调用for循环指令时间。

所以本程序延时t=((8*124)+3)*10+8*10+3=10033=10.033ms≈10ms。

注意:变量为整型时,每次调用for循环需要3个机器周期的调用时间,执行for循环判断需要8个机器周期的执行时间;字符型变量时,每次调用for循环需要2个机器周期的调用时间,执行for循环判断需要3个机器周期的执行时间。

程序运行到第一个断点所用时间0.00038900s,运行到第二个断点所用时间为0.01042800s,则执行delay_10ms()函数所用时间为0.010428-0.000389=0.010039s= 10.039ms≈10ms。

  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

单片机C语言精确延时值的计算
编者:有梦人生2009年09月12日请读者尊重版权
不明之处联系长江单片QQ群:57638937
关于单片机C语言的精确延时,网上很多都是大约给出延时值没有准确那值是多少,也就没有达到精确高的要求,而本函数克服了以上缺点,能够精确计数出要延时值且精确达到1us,本举例所用CPU为STC12C5412AD系列单片机12M的外部晶振,只要修改一下参数值其它系例单片机也通用,适用范围宽。

共有三条延时函数说明如下:
函数调用分两级:一级是小于10US的延时,二级是大于10US的延时
//=====================小于10US的【用1US级延时】=========================
for(i=X;i>0;i--)延时时间=(3+5*X)/12 提示(单位us, X不能大于255)
如延时1.9Us: for(i=4;i>0;i--);
反汇编如下图:
//================大于10US<小于21.9955Ms的可用【10US级延时函数】===========
void Delay10us(uchar Ms)
{
uchar data i;
for(;Ms>0;Ms--)
for(i=26;i>0;i--);
}
i=[(延时值-1.75)*12/Ms=15]
如想延时60US则i=[(60-1.75)*12/6-15]/4=25.375≈26; 修改i的值=26,再调用上面的【10US级延时函数】Delay10us(6); 则就精确延时60US;
如果想延时64US可以用这二种函数组合来用: Delay10us(6); for(i=9;i>X;i--) 共延时64US
//=================对于大于20Ms的可用中断来实现程序运行比较好===============
中断用定时器0, 1Ms中断:
void timer0(void) interrupt 1
{
TL0=(0xffff-1000+3)%0x100;TH0=(0xffff-1000+3)/0x100; //每1毫秒
if(DelayMs_1>0)DelayMs_1--; //大于20Ms延时程序
}
函数调用
void DelayMs(uint a)//延时a×1(ms)的时间。

{
DelayMs_1=a;
while(DelayMs_1);
}
如果延时50Ms则函数值为DelayMs(5)
//+++++++++++++++++++++++++公式推算++++++++++++++++++++++++++++
级延时C语言反汇编如下图
//====================STC单片机用到的延时指令的时间====================
指今时间(1us)
MOV Rn direct 4
MOV Rn #data 2
Lcall addr16 6
MOV A Rn 1
SETB C 1
SUBB A #data 2
JC rel 3
MOV Rn #data 2
DJNZ Rn rel 4
Dec Rn 3
SJMP rel 3
RET 4
//--------------
JNZ 3
XRL 2
SUBB 3
使用Delay10us(uchar Ms)最多能延时21995.5us;
其中循环外函数调用与返回用的时间=(6+4)进入+退出(1+1+2+3+,4)=10+11=21/12=1.75us;
循环循环内函数时间= Ms*(1+1+2+3,+2+4*I+3+3)/12=Ms*(15+4*I)/12 ;
所以如果延时60us时用【10US级延时函数】:
60us=循环外时间+循环内时间=1.75us+Ms*(15+4*I)/12; 其中Ms=6;
即i=[(60-1.75)*12/6-15]/4=25.375≈25;
把26代进公式得出实际延时时间=Ms*(15+4*I)/12 us+1.75us= 6*(15+4*25)/12us +1.75us=59.25us;
本算法中的12是用到12M晶振。

相关文档
最新文档