C语言延时计算公式
C语言延时程序

C51精确延时程序一、、看了网上延时程序的帖子挺多,我也说点。
用keil调试,void yanshi( uint n ){uchar data i="0";for(i=0;i<N;I++);return;}延时时间=12*(n*12+17)/fosc用keil测时功能很容易得到这个关系,很精确,偏差不过几us.可以自己编一些延时程序,也可以很方便的得到关系式,只是系数不同.二、、//我看到的地方也是从别的地方转贴,所以我不知道原作者是谁,但相信这么成熟的东西转一下他也不会见意。
看到了个好帖,我在此在它得基础上再抛抛砖!有个好帖,从精度考虑,它得研究结果是:void delay2(unsigned char i){while(--i);}为最佳方法。
分析:假设外挂12M(之后都是在这基础上讨论)我编译了下,传了些参数,并看了汇编代码,观察记录了下面的数据:delay2(0):延时518us 518-2*256=6delay2(1):延时7us(原帖写“5us”是错的,^_^)delay2(10):延时25us 25-20=5delay2(20):延时45us 45-40=5delay2(100):延时205us 205-200=5delay2(200):延时405us 405-400=5见上可得可调度为2us,而最大误差为6us。
精度是很高了!但这个程序的最大延时是为518us 显然不能满足实际需要,因为很多时候需要延迟比较长的时间。
那么,接下来讨论将t分配为两个字节,即uint型的时候,会出现什么情况。
void delay8(uint t){while(--t);}我编译了下,传了些参数,并看了汇编代码,观察记录了下面的数据:delay8(0):延时524551us 524551-8*65536=263delay8(1):延时15usdelay8(10):延时85us 85-80=5delay8(100):延时806us 806-800=6delay8(1000):延时8009us 8009-8000=9delay8(10000):延时80045us 80045-8000=45delay8(65535):延时524542us 524542-524280=262如果把这个程序的可调度看为8us,那么最大误差为263us,但这个延时程序还是不能满足要求的,因为延时最大为524.551ms。
c语言延时函数

c语言延时函数
C语言中的延时函数是用来暂停程序执行一段时间的函数。
在嵌入式系统中,延时函数非常常见,因为它可以控制程序的执行速度,使程序按照预期的时间顺序执行。
常见的延时函数有两种实现方式:软件延时和硬件延时。
软件延时是通过循环来实现的,即在程序中使用一个循环来占用CPU的时间,从而实现延时的效果。
例如,下面是一个简单的软件延时函数:```。
void delay(unsigned int ms)。
unsigned int i, j;。
for (i = 0; i < ms; i++)。
for (j = 0; j < 1000; j++);。
}。
```这个函数的原理是在内层循环中占用CPU的时间,从而实现延时的效果。
但是,这种方式有一个缺点,就是在延时期间CPU是被占用的,不能执行其他任务。
硬件延时是通过使用定时器来实现的,即在程序中设置一个定时器,定时器到达指定时间后触发中断,从而实现延时的效果。
例如,下面是一个简单的硬件延时函数:```。
void delay(unsigned int ms)。
//设置定时器。
TMR0=0;。
16m晶振写延时

16MHz晶振写延时可以通过公式进行计算,公式为:T = 1.15/(f x 2^N),其中T为晶振频率对应的周期,f为晶振频率,N为相位常数。
根据这个公式,可以得出需要的延时时间。
一般来说,可以使用Keil或IAR等开发工具中的定时器进行延时。
在C语言中,可以使用delay()函数实现延时操作。
在编写代码时,需要根据实际情况选择合适的延时时间,并注意避免程序中出现死循环等问题。
具体步骤如下:
1. 根据晶振频率和相位常数,使用公式计算出需要的延时时间。
2. 在Keil或IAR等开发工具中,选择合适的定时器进行延时操作。
3. 在主程序中调用delay()函数实现延时操作。
4. 根据实际需要,对程序进行调试和优化,确保程序能够正常运行。
注意事项:
1. 在编写代码时,需要注意避免程序中出现死循环等问题,以免影响程序的正常运行。
2. 在使用晶振时,需要注意晶振的安装方式和连接方式是否正确,以免影响晶振的性能和稳定性。
3. 在编写代码时,需要考虑到晶振的频率误差等因素,并采取相应的措施进行处理。
总之,通过以上步骤和注意事项,可以有效地实现16MHz晶振写延时操作。
需要注意的是,在实际应用中,需要根据具体情况进行调整和优化,以确保程序的正确性和稳定性。
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。
示波器测试通过!和我计算符合。
C及汇编延时程序讲解

有个好帖,从精度考虑,它得研究结果是:void delay2(unsigned char i){while(--i);}为最佳方法。
分析:假设外挂12M(之后都是在这基础上讨论)我编译了下,传了些参数,并看了汇编代码,观察记录了下面的数据:delay2(0):延时518us 518-2*256=6delay2(1):延时7us(原帖写“5us”是错的,^_^)delay2(10):延时25us 25-20=5delay2(20):延时45us 45-40=5delay2(100):延时205us 205-200=5delay2(200):延时405us 405-400=5见上可得可调度为2us,而最大误差为6us。
精度是很高了!但这个程序的最大延时是为518us 显然不能满足实际需要,因为很多时候需要延迟比较长的时间。
那么,接下来讨论将t分配为两个字节,即uint型的时候,会出现什么情况。
void delay8(uint t){while(--t);}我编译了下,传了些参数,并看了汇编代码,观察记录了下面的数据:delay8(0):延时524551us 524551-8*65536=263delay8(1):延时15usdelay8(10):延时85us 85-80=5delay8(100):延时806us 806-800=6delay8(1000):延时8009us 8009-8000=9delay8(10000):延时80045us 80045-8000=45delay8(65535):延时524542us 524542-524280=262如果把这个程序的可调度看为8us,那么最大误差为263us,但这个延时程序还是不能满足要求的,因为延时最大为524.551ms。
那么用ulong t呢?一定很恐怖,不用看编译后的汇编代码了。
那么如何得到比较小的可调度,可调范围大,并占用比较少得RAM呢?请看下面的程序:/*--------------------------------------------------------------------程序名称:50us 延时注意事项:基于1MIPS,AT89系列对应12M晶振,W77、W78系列对应3M晶振例子提示:调用delay_50us(20),得到1ms延时全局变量:无返回:无--------------------------------------------------------------------*/void delay_50us(uint t){uchar j;for(;t>0;t--)for(j=19;j>0;j--);}我编译了下,传了些参数,并看了汇编代码,观察记录了下面的数据:delay_50us(1):延时63us 63-50=13delay_50us(10):延时513us 503-500=13delay_50us(100):延时5013us 5013-5000=13delay_50us(1000):延时50022us 50022-50000=22赫赫,延时50ms,误差仅仅22us,作为C语言已经是可以接受了。
c语言延时计算公式

c语言延时计算公式分类:Work Log| 标签:单片机应用2007-09-13 22:35 阅读(?)评论(0)今天在看单片机C编程的时候,突然想到在许多的编程中使用软件延时的方法,进行单片机的延时控制。
但是不是很清楚为会么如下的方法能够做到准确的延时。
程序如下:void delay(void){unsigned char i, j, k;for(i = 15; i > 0; i--)for(j = 202; j > 0; j--)for(k = 81; k > 0; k--);}使用Keil uVersion2进行编译产生了汇编程序看了一下,原来在循环中使用的跳转语句是DJNZ。
结合Rn及直接地址进行操作,DJNZ的指令机器周期为2us(晶振为12MHZ时)。
上面一段程序的汇编语句如下:C:0x0013 7F0F MOV R7,#0x0F ; 1us;-----------------C:0x0015 7ECA MOV R6,#0xCA ; 1us;-----------------C:0x0017 7D51 MOV R5,#0x51 ; 1usC:0x0019 DDFE DJNZ R5,C:0019 ; 2us for(k = 81; k > 0; k--) C:0x001B DEFA DJNZ R6,C:0017 ; 2us for(j = 202; j > 0; j--) ;------------------C:0x001D DFF6 DJNZ R7,C:0015 ; 2us for(i = 15; i > 0; i--)其中(;)及其后面的内容是为了方便说明加上去了。
现在我们来计算这段代码执行时所需的时间。
for(k = 81; k > 0; k--)这一个循环所需时间为:1+2×81执行完for(j = 202; j > 0; j--)这一个循环的时间为:1+(1+2×81+2)×202 执行完三个循环的总时间为:1+〔1+(1+2×81+2)×202+2〕×15最后加上调用子程序的时间2us和返回的时间2us,整个延时程序的时间就是1+〔1+(1+2×81+2)×202+2〕×15+2+2=〔3+(3+2×81)×202〕×15+5 =500000us=500ms这个值应该是一个准确的延时时间。
C-C方法求时间延迟程序设计

C-C 方法求时间延迟程序设计一、子程序设计:本程序需调用四个子函数:(1) Heaviside.m :用来求解Heaviside 函数的值;(2) Reconstitution.m :用来进行相空间重构;(3) Disjoint.m :用来将时间序列分拆为t 个不相关的时间序列;(4) Correlation_integral.m :用来计算时间序列的关联积分。
程序说明:(1) Heaviside.m :⎩⎨⎧≥<=0,10,0)(x x x θ 输入r 和d 值的,根据公式求得heaviside 函数的值sita 并输出。
(2) Reconstitution.m :根据给定的时间延迟t 和嵌入维数m 重构m 维的相空间 ττττ)1(,,2,1)],)1((),2(),(),([)(--==-+++=m N M Mi m t x t x t x t x t Y i i i i i程序输出一个M m ⨯的矩阵;(3) disjoint.m :将时间序列分成t 个不相交的时间序列,长度t N l /=},,,{},,,{},,,{3222221211t t t t t t t x x x x x x x x x ++++程序输出为一个l t ⨯的矩阵(4) Correlation_integral.m : 关联积分定义为:0,)()1(2),,,(1>--=∑≤≤≤r d r M M t r N m C Mj i ij θ 其中:j i ij X X d -=⎩⎨⎧≥<=0,10,0)(x x x θ 程序流程:1、 输入数据X :X 为根据给定的时间延迟t 和嵌入维数m 进行相空间重构后得到的M m ⨯的矩阵;2、 对相空间中所有点求距离,并保存在数组d(i,j)中;3、 调用Heaviside 函数计算所有的Heaviside 函数值并求和得到sum_h4、 计算出关联积分的值,并输出C_I 。
延时程序计算公式

CV A VR中提供了2个延时函数:The functions are:void delay_us(unsigned int n)generates a delay of n mseconds. n must be a constant expression.void delay_ms(unsigned int n)generates a delay of n milliseconds.This function automatically resets the watchdog timer every 1ms by generating the wdr instruction.其中delay_us(unsigned int n)要求n是常数,因为us要准确,使用变量的话会大大影响精度。
1us执行的指令不多。
在C程序中调用delay_us()后,你可以看生成的ASM代码,它不是使用CALL,而是用的宏,嵌入了一段代码。
当你系统时钟为1M时,调用delay_us(1)还会编译出错,因为嵌入的一段代码,已经超过了1us!而delay_ms(unsigned int n)中的N就可以是变量,它生成的汇编是采用CALL调用函数,两者不同。
另外,在delay_ms()中还清WDT(就是你使用了WDT,也能使用该函数)。
作为通用的delay_ms(),代码当然多了点。
以上可以查看CV A VR编译后产生的LST文件。
1。
没有好的汇编基础,和对A VR的彻底透彻的掌握,一般人写不出比它还要优化的通用代码。
2。
我已经说过多少遍了。
在实际的系统中尽量不要使用软件延时,浪费资源不说,系统很难做到并行处理。
因此对于10us以下的延时,考虑直接嵌入汇编的_nop_指令。
10-100us可以适当考虑使用delay_us(),而大于100us的延时,应该采用定时器中断了。
/******************************************************************/A VR单片机的指令,从执行每条指令的时钟数分:单时钟指令、双时钟指令、三时钟指令、四时钟指令4种,A VR单片机在外接8MHZ晶振时,单时钟指令:ADC为例,每us(微秒)可以执行8条,即每条指令用时0.125us。
延时计算公式

*******************************************************************************/
void delay (unsigned int n)
{
while (n--);
}
/*******************************************************************************
NOP();延时时间,这个就不用多说了吧
void delay_1us (void)
{
NOP();
}
/******************************************************************************
8M 延时计算公式 = 2.88+(n-1)*0.75 us
2M 延时计算公式 = 11.5 +(n-1)*3.0 us
1M 延时计算公式 = 23.0+(n-1)*6.0 us
*******************************************************************************/
2M 延时计算公式 = 24.5+(n-1)*3.0 us
1M 延时计算公式 = 49.0+(n-1)*6.0 us
*******************************************************************************/
void delay (unsigned int n)
void delay_us普通延时函数计算方法

void delay_us普通延时函数计算方法
普通延时函数的计算方法主要是通过循环来实现。
根据CPU的运行速
度以及循环次数,可以估算出延时的时长。
下面是一个常见的延时函
数的计算方法:
1. 获取CPU的频率(单位为Hz),例如获取方法为:SystemCoreClock。
2. 假设1秒钟有n个时钟周期,那么每个时钟周期的时间为1/n秒。
3. 根据你要延时的时间(单位为微秒),假设为t微秒,计算出需要的时钟周期数。
延时的时钟周期数 = t * (CPU频率 / 1000000)
4. 根据计算出的时钟周期数,编写相应的循环代码来实现延时。
例如,可以使用一个for循环,循环次数为延时的时钟周期数。
例如,假设CPU频率为72 MHz,要延时100微秒,那么需要的时钟
周期数为:
延时的时钟周期数 = 100 * (72000000 / 1000000) = 7200个时钟周期
那么,可以使用如下的代码来实现延时:
```c
void delay_us(uint32_t us) {
uint32_t delay_cycles = us * (SystemCoreClock / 1000000);
for (uint32_t i = 0; i < delay_cycles; i++) {
// 空循环
}
}
请注意,这只是一个简单的估算方法,并不能保证完全准确。
实际的
延时时间可能会受到其他因素的影响,例如编译器优化、中断、外设等。
要实现准确的延时,可能需要使用特定的定时器或外部晶体振荡
器来生成精确的时钟信号。
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语言延时程序的计算方法经典

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)
单片机c5延时时间怎样计算

C程序中可使用不同类型的变量来进行延时设计。
经实验测试,使用unsignedchar类型具有比unsignedint更优化的代码,在使用时应该使用unsignedchar作为延时变量。
以某晶振为12MHz的单片机为例,晶振为12MHz 即一个机器周期为1us。
一.500ms延时子程序程序:voiddelay500ms(void){unsignedchari,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=162usDJNZ2us二层循环m:R6*(n+3)=202*165=33330usDJNZ2us+R5赋值1us=3us三层循环:R7*(m+3)=15*33333=499995usDJNZ2us+R6赋值1us=3us循环外:5us子程序调用2us+子程序返回2us+R7赋值1us=5us延时总时间=三层循环+循环外=499995+5=500000us=500ms计算公式:延时时间=[(2*R5+3)*R6+3]*R7+5二.200ms延时子程序程序:voiddelay200ms(void){unsignedchari,j,k;for(i=5;i>0;i--)for(j=132;j>0;j--)for(k=150;k>0;k--);}三.10ms延时子程序程序:voiddelay10ms(void){unsignedchari,j,k;for(i=5;i>0;i--)for(j=4;j>0;j--)for(k=248;k>0;k--);}四.1s延时子程序程序:voiddelay1s(void){unsignedcharh,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--); }参考链接:摘要实际的单片机应用系统开发过程中,由于程序功能的需要,经常编写各种延时程序,延时时间从数微秒到数秒不等,对于许多C51开发者特别是初学者编制非常精确的延时程序有一定难度。
用单片机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语言是一种广泛应用于系统软件和应用程序开发的高级编程语言。
在实际应用中,时延(也称为延迟)是指开始某个操作到完成该操作所经过的时间,对于实时性要求较高的系统,优化时延是至关重要的。
本文将探讨C语言中优化时延的打点方案。
一、理解时延在编程中,时延是指某个操作从开始到完成所消耗的时间。
这个时间通常由许多因素决定,包括硬件性能、软件算法和编码技巧等。
在C语言中,时延打点的主要目的是为了确定程序中的瓶颈和性能瓶颈,从而进行优化和改进。
二、时延打点方法1. 基础方法最简单的时延打点方法是使用标准库函数time.h中的clock()函数或者使用操作系统提供的计时函数。
这些函数可以在程序中插入时间戳,然后计算两个时间戳之间的差值,从而得到时延。
2. 微秒级时延打点为了更精确地测量时延,可以使用基于硬件的计时器,例如x86架构中的时间戳计数器(TSC)。
时间戳计数器可以精确到微秒级别,从而更精确地测量程序中的时延。
在C语言中,可以使用内联汇编来访问时间戳计数器。
以下是一个示例代码:c#include <stdio.h>static inline unsigned long long rdtsc(){unsigned int lo, hi;asm volatile ("rdtsc" : "=a" (lo), "=d" (hi));return ((unsigned long long)hi << 32) lo;}int main(){unsigned long long start, end, time;start = rdtsc(); 开始计时执行要测量时延的代码块end = rdtsc(); 结束计时time = end - start; 计算时延printf("The time delay is: llu\n", time);return 0;}3. 基于时钟周期的时延打点在一些特定的嵌入式系统中,可以通过统计CPU时钟周期的方式来测量时延。
单片机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语言延时计算

我现在就用两种方法来实现,一种是while()语句,另一种是for()语句,这两种语句均可产生汇编语句中的DJNZ语句,以12MHZ晶振为例(说明:在编写C程序时,变量尽量使用unsigned char,如满足不了才使用unsigned int):1.delay=99;while(--delay);000FH MOV 08H,#63H0012H DJNZ 08H,0012H这样产生的延时时间为:(99+1)×2us。
最小延时时间为2us,若加上对delay赋值语句,则最小为4us。
2.for(i=delay;i>0;i--);产生的汇编代码同while()语句。
下面来举例几个延时函数:一. 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--);}产生的汇编代码:C:0x0800 7F0F MOV R7,#0x0FC:0x0802 7ECA MOV R6,#0xCAC:0x0804 7D51 MOV R5,#0x51C:0x0806 DDFE DJNZ R5,C:0806C:0x0808 DEFA DJNZ R6,C:0804C:0x080A DFF6 DJNZ R7,C:0802C:0x080C 22 RET计算分析:程序共有三层循环一层循环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延时子程序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--); }三. 10ms延时子程序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延时子程序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--); }。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
c语言延时计算公式
分类:Work Log|标签:单片机应用
2007-09-1322:35阅读(?)评论(0)
今天在看单片机C编程的时候,突然想到在许多的编程中使用软件延时的方法,进行单片机的延时控制。
但是不是很清楚为会么如下的方法能够做到准确的延时。
程序如下:
void delay(void)
{
unsigned char i,j,k;
for(i=15;i>0;i--)
for(j=202;j>0;j--)
for(k=81;k>0;k--);
}
使用Keil uVersion2进行编译产生了汇编程序看了一下,原来在循环中使用的跳转语句是DJNZ。
结合Rn及直接地址进行操作,DJNZ的指令机器周期为2us(晶振为12MHZ时)。
上面一段程序的汇编语句如下:
C:0x00137F0F MOV R7,#0x0F;1us
;-----------------
C:0x00157ECA MOV R6,#0xCA;1us
;-----------------
C:0x00177D51MOV R5,#0x51;1us
C:0x0019DDFE DJNZ R5,C:0019;2us for(k=81;k>0;k--)
C:0x001B DEFA DJNZ R6,C:0017;2us for(j=202;j>0;j--)
;------------------
C:0x001D DFF6DJNZ R7,C:0015;2us for(i=15;i>0;i--)
其中(;)及其后面的内容是为了方便说明加上去了。
现在我们来计算这段代码执行时所需的时间。
for(k=81;k>0;k--)这一个循环所需时间为:1+2×81
执行完for(j=202;j>0;j--)这一个循环的时间为:1+(1+2×81+2)×202执行完三个循环的总时间为:1+〔1+(1+2×81+2)×202+2〕×15
最后加上调用子程序的时间2us和返回的时间2us,整个延时程序的时间就是
1+〔1+(1+2×81+2)×202+2〕×15+2+2=
〔3+(3+2×81)×202〕×15+5=500000us=500ms
这个值应该是一个准确的延时时间。
总结:在使用汇编语言进行延时设计时,其计算方法是:先从最里层的循环进行时间计算,再往外层循环时行计算。
一层层往外叠加,最后不要忘记子程序的调用及返回的时间也要加上去。