搜档网
当前位置:搜档网 › c语言延时程序的计算方法经典

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

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

void delay()

{

uchar i,j;

for(i=2;i>0;i--)

{for(j=250;j>0;j--);}

}

//i=1000时,结果是输出周期为234ms的方波,即delay(1000)=117ms

//延时时间=i*(j*2T+2T)+iT+T, T为及其周期,其中i、j小于255,

大于则只取16进制的后8位。计算方法不是此种方法

//i=100 j=250时,T=1微妙时,延时时间=50.301ms,通过示波器验证

//i=1000,则转为十六进制为03E8,取i=0xe8=232

//则此时延时时间为116697微秒,116.697ms

上述程序等价于:

Mov r7, #i;单周期指令

Loop1: mov r6, #j 单周期质量

Loop2: djnz r6, loop2; djnz 双周期指令

Djnz r7, loop1,

延时时间=T+i*T+i*j*2T+i*2T

下面几个是单片机的延时程序(包括asm和C程序,都是我在学单片机的过程中用到的),在单片机延时程序中应考虑所使用的晶振的频率,在51系列的单片机中我们常用的是11.0592MHz和12.0000MHz的晶振,而在AVR单片机上常用的有8.000MHz和4.000MH的晶振所以在网上查找程序时如果涉及到精确延时则应该注意晶振的频率是多大。

软件延时:(asm)

晶振12MHZ,延时1秒

程序如下:

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;

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)

{

TMOD=0x01; /*定时器0工作在模式1下(16位计数器)*/ TH0=0xf4;

TL0=0x48;

TR0=1; /*启动定时器*/

while(TF0==0);

TR0=0;

}

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=6 delay2(1):延时7us(原帖写“5us”是错的,^_^) delay2(10):延时25us 25-20=5 delay2(20):延时45us 45-40=5 delay2(100):延时205us 205-200=5 delay2(200):延时405us 405-400=5 见上可得可调度为2us,而最大误差为6us。 精度是很高了! 但这个程序的最大延时是为518us 显然不 能满足实际需要,因为很多时候需要延迟比较长的时间。 那么,接下来讨论将t分配为两个字节,即uint型的时候,会出现什么情况。

用C语言实现精确的延时

怎么用C语言做单片机的精确延时在单片机应用中,经常会遇到需要短时间延时的情况,一般都是几十到几百μs,并且需要很高的精度(比如用单片机驱动DS18B20时,误差容许的范围在十几μs以内,不然很容易出错);而某些情况下延时时间较长,用计时器往往有点小题大做。另外在特殊情况下,计时器甚至已经全部用于其他方面的定时处理,此时就只能使用软件定时了[1]。 1C语言程序延时 Keil C51的编程语言常用的有2种:一种是汇编语言;另一种是C语言。用汇编语言写单片机程序时,精确时间延时是相对容易解决的。比如,用的是晶振频率为12MHz 的AT89C51,打算延时20μs,51单片机的指令周期是晶振频率的1/12,即一个机器周期为1μs;“MOV R0,#X”需要2个机器周期,DJNZ也需要2个机器周期,单循环延时时间t=2X+3(X为装入寄存器R0的时间常数)[2]。这样,存入R0里的数初始化为8即可,其精度可以达到1μs。用这种方法,可以非常方便地实现512μs以下时间的延时。如果需要更长时间,可以使用两层或更多层的嵌套,当然其精度误差会随着嵌套层的增加而成倍增加。 虽然汇编语言的机器代码生成效率很高,但可读性却并不强,复杂一点的程序就更难读懂;而C语言在大多数情况下,其机器代码生成效率和汇编语言相当,但可读性和可移植性却远远超过汇编语言,且C语言还可以嵌入汇编程序来解决高时效性的代码编写问题。就开发周期而言,中大型软件的编写使用C语言的开发周期通常要比汇编语言短很多,因此研究C语言程序的精确延时性能具有重要的意义。 C程序中可使用不同类型的变量来进行延时设计。经实验测试,使用unsigned char类型具有比unsigned int更优化的代码,在使用时应该使用unsigned char作为延时变量。 2单层循环延时精度分析 下面是进行μs级延时的while程序代码。 延时函数: void delay1(unsigned char i){ while(i);} 主函数: void main(){ while(1){ delay1(i); } } 使用Keil C51的反汇编功能,延时函数的汇编代码如下: C:0x00E6AE07MOVR6,0x07 C:0x00E81FDECR7 C:0x00E9EEMOVA,R6 C:0x00EA70FAJNZC:00E6 C:0x00EC22RET 图1断点设置位置图 通过对i赋值为10,在主程序中图1所示的位置设置断点。经过测试,第1次执行到断点处的时间为457μs,再次执行到该处的时间为531μs,第3次执行到断点处的时间为605μs,10次while循环的时间为74μs,整个测试结果如图2所示。 图2使用i--方式测试仿真结果图 通过对汇编代码分析,时间延迟t=7X+4(其中X为i的取值)。测试表明,for循环方式虽然生成的代码与用while语句不大一样,但是这两种方法的效率几乎相同。C语言中的自减方式有两种,前面都使用的是i--的方式,能不能使用--i方式来获得不同的效果呢?将前面的主函数保持不变,delay1函数修改为下面的方式:void delay1(unsigned char i){ while(--i);} 同样进行反汇编,得到如下结果: C:0x00E3DFFEDJNZR7, C:00E3C:0x00E522RET 比较发现,--i的汇编代码效率明显高于i--方式。由于只有1条语句DJNZ,执行只需要2个时钟周期,1个时钟周期按1μs计算,其延时精度为2μs;另外,RET

STC12系列单片机C语言的延时程序

STC12系列单片机C语言的延时程序 本举例所用CPU 为STC12C5412 系列12 倍速的单片机,只要修改一下参数值其它系例单片机也通用,适用范围宽。共有三条延时函数说明如下:函数调用 分两级:一级是小于10US 的延时,二级是大于10US 的延时 //====================小于10US 的【用1US 级延时】 ====================//----------微秒级延时---------for(i=X;i>X;i--) 延时时间 =(3+5*X)/12 提示(单位us, X 不能大于255)//================大于10US0;Ms--)for(i=26;i>0;i--);}i=[(延时值-1.75)*12/Ms-15]/4 如想延时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+2)% 0x100;TH0=(0xffff-1000+2)/0x100; //每毫秒执行一次if(DelayMs_1>0) DelayMs_1--;//大于20Ms 延时程序}函数调用void DelayMs(uint a)//延时 a 乘以1(ms)的时间。{ DelayMs_1=a; while(DelayMs_1);}如果延时50Ms 则函数值为DelayMs(50)tips:感谢大家的阅读,本文由我司收集整编。仅供参阅!

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

C程序中可使用不同类型的变量来进行延时设计。经实验测试,使用unsigned char类型具有比unsigned int更优化的代码,在使用时 应该使用unsigned char作为延时变量。以某晶振为12MHz的单片 机为例,晶振为12M H z即一个机器周期为1u s。一. 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延时子程序 程序: 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--);

c语言中的精确延时程序举例

c语言中的精确延时程序举例 我在网上到看了一些关于延时的讨论,其中有篇文章51单片机Keil C 延时程序的简单研究,作者:InfiniteSpace Studio/isjfk 写得不错,他是用while(--i);产生DJNZ 来实现精确延时,后来有人说如果while里面不能放其它语句,否则也不行,用do-while就可以,具体怎样我没有去试.所有这些都没有给出具体的实例程序来.还看到一些延时的例子多多少少总有点 延时差.为此我用for循环写了几个延时的子程序贴上来,希望能对初学者有所帮助.(晶振12 MHz,一个机器周期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--); } 产生的汇编: C:0x0800 7F0F MOV R7,#0x0F C:0x0802 7ECA MOV R6,#0xCA C:0x0804 7D51 MOV R5,#0x51 C:0x0806 DDFE DJNZ R5,C:0806 C:0x0808 DEFA DJNZ R6,C:0804 C:0x080A DFF6 DJNZ R7,C:0802 C: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--); } 产生的汇编

单片机c语言中nop函数的使用方法和延时计算

单片机c语言中nop函数的使用方法和延时计算 标准的C语言中没有空语句。但在单片机的C语言编程中,经常需要用几个空指令产生短延时的效果。 这在汇编语言中很容易实现,写几个nop就行了。 在keil C51中,直接调用库函数: #include // 声明了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,#0FFH LOOP:DJNZ09H,LOOP 指令相当简洁,也很好计算精确的延时时间。 同样对do…while,while循环语句中,也是如此 例: unsigned char n; n=255; do{n--}

Keil C51精确延时程序(C语言)

Keil C51精确延时程序 程序说明如下: 振荡频率:12MHz 机器周期=12/振荡频率=12/12000000=1us #include 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=25us delay2(10); //赋值并调延时程序delay2 说明:本句为赋值并调用Delayus2:延时时间=(1+2)*机器周期。 全部延时时间为:延时时间=(1+2+6*i+2)*机器周期。 i=1~255。 本例:延时时间=(1+2+6*10+2)*1us=65us m=10; //赋值,m=1~255 while(--m) ; //计算,延时时间=2*m*机器周期 说明:本两句为赋值并计算。 全部延时时间为:延时时间=(1+2*m)*机器周期。 m=1~255。 本例:延时时间=(1+2*10)*1us=25us while(1); }

单片机C语言延时程序

单片机C语言延时程序 我的资料 2009-07-25 06:50 阅读211 评论0 字号:大中小 用C语言写出来程序非常的简练,它是一种模块化的语言,一种比汇编更高级的语言,但是就是这样一种语言也还是有它不足之处:它的延时很不好控制,我们常常很难知道一段延时程序它的精确延时到底是多少,这和汇编延时程序没法比。但有时后写程序又不得不要用到比较精确的延时,虽然说可以用混合编程的方式解决,但这种方式不是每个人都能掌握,且写起来也麻烦。所以,通过测试我给大家提供一个延时子程序模块,并以此给一个出我们经常用到的延时的数据表格。(注意:表格中的数据只适合我的延时模块,对其他的延时程序不适用,切忌!!!!!!!!别到时候延时不对来骂我) 延时模块:其中问号代表要填的数,要延时多少,到表格中去找数据,然后填上就OK!切忌3条FOR语句不能颠倒顺序 void Delay() { unsigned char a,b,c; for(a=0;a

for循环实现C语言精确延时

for实现C语言精确延时C语言最大的缺点就是实时性差,我在网上到看了一些关于延时的讨论,其中有篇文章 51单片机Keil C 延时程序的简单研究, 写得不错,他是用while(--i);产生DJNZ 来实现精确延时,后来有人说如果while里面不能放其它语句,否则也不行,用do-while就可以,具体怎样我没有去试.所有这些都没有给出具体的实例程序来.还看到一些延时的例子多多少少总有点延时差.为此我用for循环写了几个延时的子程序贴上来,希望能对初学者有所帮助.(晶振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--); } 产生的汇编: C:0x0800 7F0F MOV R7,#0x0F C:0x0802 7ECA MOV R6,#0xCA C:0x0804 7D51 MOV R5,#0x51 C:0x0806 DDFE DJNZ R5,C:0806 C:0x0808 DEFA DJNZ R6,C:0804 C:0x080A DFF6 DJNZ R7,C:0802 C: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--); } 产生的汇编 C:0x0800 7F05 MOV R7,#0x05 C:0x0802 7E84 MOV R6,#0x84 C:0x0804 7D96 MOV R5,#0x96 C:0x0806 DDFE DJNZ R5,C:0806 C:0x0808 DEFA DJNZ R6,C:0804 C:0x080A DFF6 DJNZ R7,C:0802 C:0x080C 22 RET 三. 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--); } 产生的汇编 C:0x0800 7F05 MOV R7,#0x05 C:0x0802 7E04 MOV R6,#0x04 C:0x0804 7DF8 MOV R5,#0xF8 C:0x0806 DDFE DJNZ R5,C:0806 C:0x0808 DEFA DJNZ R6,C:0804 C:0x080A DFF6 DJNZ R7,C:0802 C:0x080C 22 RET 四. 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:0x0800 7F05 MOV R7,#0x05 C:0x0802 7E04 MOV R6,#0x04 C:0x0804 7D74 MOV R5,#0x74 C:0x0806 7CD6 MOV R4,#0xD6 C:0x0808 DCFE DJNZ R4,C:0808 C:0x080A DDFA DJNZ R5,C:0806 C:0x080C DEF6 DJNZ R6,C:0804 C:0x080E DFF2 DJNZ R7,C:0802 C:0x0810 22 RET 在精确延时的计算当中,最容易让人忽略的是计算循环外的那部分延时,在对时间要求不高的场合,这部分对程序不会造成影响.

c语言延时语句

C语言程序延时 Keil C51的编程语言常用的有2种:一种是汇编语言;另一种是C 语言。用汇编语言写单片机程序时,精确时间延时是相对容易解决的。比如,用的是晶振频率为12 MHz的AT 89C51,打算延时20 μs,51单片机的指令周期是晶振频率的1/12,即一个机器周期为1 μs;“MOV R0,#X”需要2个机器周期,DJNZ也需要2个机器周期,单循环延时时间t=2X+3(X为装入寄存器R0的时间常数)[2]。这样,存入R0里的数初始化为8即可,其精度可以达到1 μs。用这种方法,可以非常方便地实现512 μs以下时间的延时。如果需要更长时间,可以使用两层或更多层的嵌套,当然其精度误差会随着嵌套层的增加而成倍增加。 C程序中可使用不同类型的变量来进行延时设计。经实验测试,使用unsigned char类型具有比unsigned int更优化的代码,在使用时应该使用unsigned char作为延时变量。 有人说如果while里面不能放其它语句,否则也不行,用do-while 就可以,具体怎样我没有去试.所有这些都没有给出具体的实例程序来.还看到一些延时的例子多多少少总有点延时差.为此我用for循环写 了几个延时的子程序贴上来,希望能对初学者有所帮助.(晶振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

C语言延时程序

标准的C语言中没有空语句。但在单片机的C语言编程中,经常需要用几个空指令产生短延时的效果。 这在汇编语言中很容易实现,写几个nop就行了。 在keil C51中,直接调用库函数: #include // 声明了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,#0FFH LOOP:DJNZ09H,LOOP 指令相当简洁,也很好计算精确的延时时间。 同样对do…while,while循环语句中,也是如此 例: unsigned char n; n=255; do{n--} while(n); 或 n=255; while(n) {n--}; 这两个循环语句经过C51编译之后,形成DJNZ来完成的方法, 故其精确时间的计算也很方便。

通用C语言延时

通用C语言延时 在嵌入式C编程中,免不了要用到软件延时。这一般通过循环语句实现。通过控制循环语句的循环次数,便可获得多种不同的延时时间。为了便于使用和提高程序代码的复用率,一般又将循环语句封装成一个带参数的函数,称为延时函数。如: void wait(unsigned int n) { unsigned int i; for(i=0;i

PIC16系列的C语言延时子程序

PIC16系列的C语言延时子程序 //******************************************** // 主芯片采用PIC16F630;4M晶振。 // us级延时3个,使用固定延时方式,分别是: // Delay_1us(); // Delay_10us(); // Delay_100us(); // 精确度为100% // ms级延时1个,使用填值方式,可以任意写入值 // Delay_1ms(1~10000); // 固定误差:+24us // 此文由lishenglin24于2011.8.13编写,经仿真验证。 //******************************************** #define Delay_1us() asm("nop") //******************************************** #define Delay_10us() asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop");asm("nop"); asm("nop");asm("nop") //******************************************** void Delay_100us() { Delay_10us(); //1 Delay_10us(); //2 Delay_10us(); //3 Delay_10us(); //4 Delay_10us(); //5 Delay_10us(); //6 Delay_10us(); //7 Delay_10us(); //8 Delay_10us(); //9 Delay_1us(); //6us Delay_1us(); Delay_1us(); Delay_1us(); Delay_1us(); Delay_1us(); } //******************************************* void Delay_ms(unsigned int ms) { unsigned int j; for(j=ms;j>0;j--) {

单片机的C语言延时程序

单片机C语言环境延时程序设计 东北电力学院(132012)盛文利 摘要:讨论运用C语言的单片机开发中,对于时序要求苛刻的延时的开发过程。实例说明在高级语言中,严格控制时序的可能性和注意事项。 关键词:单片机C语言编译器 现在单片机的开发中,C语言以其方便、灵活、逻辑性强、易于维护和可移植性好等强大优势,占据了单片机开发的主要地位。过去,由于单片机C 语言本身存在的缺陷,加之单片机工程本身都不大,C语言在单片机中的应用没有被重视。在C语言环境下,我们只需关心程序的逻辑关系,实现细节由编译器完成,这给我们快速开发提供了条件,也大大减小了开发工作量。但同时实现细节就不被控制了,这个问题对于经常重视实现细节的单片机,就必须得到解决。好在一般的C语言编译器都提供嵌入汇编、与汇编互调用和汇编级的代码察看等功能。现以KEIL C51[1]下的一线总线器件程序开发为例,说明我的解决方法。 1 一线总线协议器件 一线总线协议(1 wire bus protocol)也叫做单总线协议,是单总线器件数据传输协议。因为数据(也可以包括电源)都由一条线来传输,没有辅助的数据同步信号,这时就只能由时序来解析协议内容。这样就只有依靠对时序的严格要求,来保障数据传输的准确性。 单总线协议的信号主要有:初始化时序,包括复位脉冲和在线脉冲,是主机与器件的联络信号。然后是读、写时序。单总线器件完全依靠对线上的时序来做出响应,这些有效的时序称作时隙,也有称作时间片的,是同一词汇的不同翻译[2]。 初始化时序时间裕度大,容易实现。读写脉冲对时序要求相对严格,尤其在慢速的MCS-51下,指令的运行在微妙级,而读写时序在15微秒的后小部分,大约4微秒,不同批次的芯片会有少许差距。有的会允许你的时序有少许误差,有的则非常严格。 2 C语言编译器 在用汇编语言编写的程序时,很容易控制时间,因为我们知道每条语句的执行时间,每段宏的执行时间,每段子程序加调用语句所消耗的时间。在单片机的C语言开发中,C语言编译器都对标准C 作了针对单片机特点的扩展。但对于不同的单片机,不同的C语言编译器在将源程序翻译成目标机器语言时,会有不同的编译方法,在生成目标代码时,会有所不同。开发人员必须研究它生成的汇编语言代码,来保证时间的准确性。这也许是除了使用嵌入汇编或直接编写汇编函数的唯一方法。其实在单片机的C编译器中,已经有足够的底层操作方面的扩展,所以这里只考虑纯C语言的方法。 3. 延时程序设计 我们以德国Keil公司的MCS-51C语言编译器为例,目前它已被公认为业界的标准。以下讨论均假设单片机时钟晶振为6兆的51芯片,以小模式下编译,这时MCS-51程序指令执行的最小单位是2微秒。如果使用非英特尔且内核优化过的单片机,应切换回普通模式,或仔细研究它的时序。以DS18B20为例,我们临时在程序中需要延时2微秒,那末可以用以下程序 #include void somefunc(void) { ……; _nop_(); ……; } 如果要延时64微秒甚至640微妙,我们不可能在程序中重复上述_nop_(),虽然这并不会出错。可以利用它来构建延时程序,精确定时的问题就变为延时程序的精度问题。我们先讨论以上的空操作延时。 3.1 空操作延时及延时函数 注意到DS18B20最小时隙除大于一微秒的外,最小的就是15微秒。而数据的读或写也包含在这15微秒中。由于定时器的延时要对定时器进行初始化,不易得到小的延时。只能用于复位脉冲,即在480至960微秒之间的延时,程序实现接近960

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

void delay() { uchar i,j; for(i=2;i>0;i--) {for(j=250;j>0;j--);} } //i=1000时,结果是输出周期为234ms的方波,即delay(1000)=117ms //延时时间=i*(j*2T+2T)+iT+T, T为及其周期,其中i、j小于255, 大于则只取16进制的后8位。计算方法不是此种方法 //i=100 j=250时,T=1微妙时,延时时间=50.301ms,通过示波器验证 //i=1000,则转为十六进制为03E8,取i=0xe8=232 //则此时延时时间为116697微秒,116.697ms 上述程序等价于: Mov r7, #i;单周期指令 Loop1: mov r6, #j 单周期质量 Loop2: djnz r6, loop2; djnz 双周期指令 Djnz r7, loop1, 延时时间=T+i*T+i*j*2T+i*2T 下面几个是单片机的延时程序(包括asm和C程序,都是我在学单片机的过程中用到的),在单片机延时程序中应考虑所使用的晶振的频率,在51系列的单片机中我们常用的是11.0592MHz和12.0000MHz的晶振,而在AVR单片机上常用的有8.000MHz和4.000MH的晶振所以在网上查找程序时如果涉及到精确延时则应该注意晶振的频率是多大。 软件延时:(asm) 晶振12MHZ,延时1秒 程序如下: 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

C语言延时计算公式

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

单片机C语言的延时计算

单片机C语言的延时计算标准的C语言中没有空语句。但在单片机的C语言编程中,经常需要用几个空指令产生短延时的效果. 这在汇编语言中很容易实现,写几个nop就行了。 在keilC51中,直接调用库函数: #include<intrins.h〉 //声明了vo id _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指令来完成,相当于如下指令: MOV 09H,#0FFH LOOP: DJNZ09H,LOOP 指令相当简洁,也很好计算精确的延时时间。 同样对do…while,while循环语句中,也是如此例: unsigned char n; n=255; do{n-—} while(n); 或 n=255; while(n) {n-—};

c语言编的延时程序

c语言延时程序的研究 2007-08-19 21:02 有个好帖,从精度考虑,它得研究结果是: void delay2(unsigned char i) { while(--i); } 为最佳方法。 分析:假设外挂12M(之后都是在这基础上讨论) 我编译了下,传了些参数,并看了汇编代码,观察记录了下面的数据: delay2(0):延时518us 518-2*256=6 delay2(1):延时7us(原帖写“5us”是错的,^_^) delay2(10):延时25us 25-20=5 delay2(20):延时45us 45-40=5 delay2(100):延时205us 205-200=5 delay2(200):延时405us 405-400=5 见上可得可调度为2us,而最大误差为6us。 精度是很高了! 但这个程序的最大延时是为518us 显然不 能满足实际需要,因为很多时候需要延迟比较长的时间。 那么,接下来讨论将t分配为两个字节,即uint型的时候,会出现什么情况。 void delay8(uint t) { while(--t); } 我编译了下,传了些参数,并看了汇编代码,观察记录了下面的数据: delay8(0):延时524551us 524551-8*65536=263 delay8(1):延时15us delay8(10):延时85us 85-80=5 delay8(100):延时806us 806-800=6 delay8(1000):延时8009us 8009-8000=9 delay8(10000):延时80045us 80045-8000=45 delay8(65535):延时524542us 524542-524280=262 如果把这个程序的可调度看为8us,那么最大误差为263us,但这个延时程序还是不能满足要

keilc的延时函数实例,delay函数

#define uchar unsigned char #define uint unsigned int void delay8us(uchar num) {uchar i,j; for(j=0;j

} void delay500ms(uchar num) {uchar i,j; for(j=0;j

相关主题