如何利用for循环实现C语言的精确延时

合集下载

51单片机技巧:精确延时

51单片机技巧:精确延时

在用C语言写程序时,初学者遇到的一个难题时精确延时程序的设计。

我刚开始用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--);}以上的这先希望对大家有帮组,如有不足之处请指出,如有更好的方法也可以告诉我,大家一起分享第二部分关于单片机C语言的精确延时,网上很多都是大约给出延时值没有准确那值是多少,也就没有达到精确高的要求,而51hei给出的本函数克服了以上缺点,能够精确计数出要延时值且精确达到1us,本举例所用CPU为STC12C5412系列12倍速的单片机,只要修改一下参数值其它系例单片机也通用,适用范围宽。

如何利用for循环实现C语言的精确延时

如何利用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,#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--);}产生的汇编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,#0xD6C:0x0808 DCFE DJNZ R4,C:0808C:0x080A DDFA DJNZ R5,C:0806C:0x080C DEF6 DJNZ R6,C:0804C:0x080E DFF2 DJNZ R7,C:0802C:0x0810 22 RET在精确延时的计算当中,最容易让人忽略的是计算循环外的那部分延时,在对时间要求不高的场合,这部分对程序不会造成影响.以下为6MHZ的晶振8051的核心单片机C语言的延时1秒的延时:void delay1s(void){unsigned char h,i,j,k;for(h=3;h>0;h--)for(i=5;i>0;i--)for(j=82;j>0;j--)for(k=19;k>0;k--);}。

51单片机延时函数

51单片机延时函数

51单片机延时函数在嵌入式系统开发中,51单片机因其易于学习和使用、成本低廉等优点被广泛使用。

在51单片机的程序设计中,延时函数是一个常见的需求。

通过延时函数,我们可以控制程序的执行速度,实现定时器功能,或者在需要的时候进行延时操作。

本文将介绍51单片机中常见的延时函数及其实现方法。

一、使用for循环延时这种方法不精确,但是对于要求不高的场合,可以用来估算延时。

cvoid delay(unsigned int time){unsigned int i,j;for(i=0;i<time;i++)for(j=0;j<1275;j++);}这个延时函数的原理是:在第一个for循环中,我们循环了指定的时间次数(time次),然后在每一次循环中,我们又循环了1275次。

这样,整个函数的执行时间就是time乘以1275,大致上形成了一个延时效果。

但是需要注意的是,这种方法因为硬件和编译器的不同,延时时间会有很大差异,所以只适用于对延时时间要求不精确的场合。

二、使用while循环延时这种方法比使用for循环延时更精确一些,但是同样因为硬件和编译器的不同,延时时间会有差异。

cvoid delay(unsigned int time){unsigned int i;while(time--)for(i=0;i<1275;i++);}这个延时函数的原理是:我们先进入一个while循环,在这个循环中,我们循环指定的时间次数(time次)。

然后在每一次循环中,我们又循环了1275次。

这样,整个函数的执行时间就是time乘以1275,大致上形成了一个延时效果。

但是需要注意的是,这种方法因为硬件和编译器的不同,延时时间会有差异,所以只适用于对延时时间要求不精确的场合。

三、使用定时器0实现精确延时这种方法需要在单片机中开启定时器0,并设置定时器中断。

在中断服务程序中,我们进行相应的操作来实现精确的延时。

这种方法需要使用到单片机的定时器中断功能,相对复杂一些,但是可以实现精确的延时。

c语言中延时的方法

c语言中延时的方法

c语言中延时的方法C语言中实现延时的方法有多种方式。

下面将介绍两种常用的延时方法:方法一:使用循环实现延时使用循环来进行延时是C语言中常用的方法之一。

通过循环次数来控制延时的时间,代码如下:```#include <stdio.h>void delay(int milliseconds) {for (int i = 0; i < milliseconds * 10000; i++) {// 延时}}int main() {printf("开始延时\n");delay(1000); // 延时1秒printf("延时结束\n");return 0;}```在上述代码中,delay函数使用了一个for循环来实现延时,其中循环次数通过乘以10000与延时时间相乘得到。

这种方法的缺点是无法精确控制延时时间,受系统执行速度的影响较大。

方法二:使用<time.h>库函数实现延时另一种常用的延时方法是利用<time.h>头文件中的库函数,如sleep函数。

代码如下:```#include <stdio.h>#include <time.h>void delay(int seconds) {sleep(seconds);}int main() {printf("开始延时\n");delay(1); // 延时1秒printf("延时结束\n");return 0;}```在上述代码中,delay函数通过调用sleep函数来实现延时,参数表示延时的秒数。

这种方法的优点是延时时间较为精确,但缺点是无法实现毫秒级的延时。

以上是C语言中实现延时的两种常用方法。

开发者可以根据具体需求选择合适的延时方法。

51单片机c语言延时

51单片机c语言延时

51单片机c语言延时51单片机(8051微控制器)是一种广泛使用的嵌入式系统芯片,其编程语言包括C语言和汇编语言等。

在C语言中,实现51单片机延时的方法有多种,下面介绍其中一种常用的方法。

首先,我们需要了解51单片机的指令周期和机器周期。

指令周期是指单片机执行一条指令所需的时间,而机器周期是指单片机执行一个操作所需的时间,通常以微秒为单位。

在C语言中,我们可以使用循环结构来实现延时。

#include <reg51.h> // 包含51单片机的寄存器定义void delay(unsigned int time) // 延时函数,参数为需要延时的微秒数{unsigned int i, j;for (i = 0; i < time; i++)for (j = 0; j < 1275; j++); // 1275个机器周期,约等于1ms}void main() // 主函数{while (1) // 无限循环{// 在这里添加需要延时的代码P1 = 0x00; // 例如将P1口清零delay(1000); // 延时1秒P1 = 0xFF; // 将P1口清零delay(1000); // 延时1秒}}在上面的代码中,我们定义了一个名为delay的函数,用于实现延时操作。

该函数接受一个无符号整数参数time,表示需要延时的微秒数。

在函数内部,我们使用两个嵌套的循环来计算延时时间,其中外层循环控制需要延时的次数,内层循环控制每个机器周期的时间(约为1微秒)。

具体来说,内层循环执行了约1275次操作(具体数值取决于编译器和单片机的型号),以实现约1毫秒的延时时间。

需要注意的是,由于单片机的指令周期和机器周期不同,因此我们需要根据具体的单片机型号和编译器进行调整。

在主函数中,我们使用一个无限循环来不断执行需要延时的操作。

例如,我们将P1口的所有引脚清零,然后调用delay函数进行1秒钟的延时,再将P1口清零并再次调用delay函数进行1秒钟的延时。

通用C语言延时

通用C语言延时

通用C语言延时在嵌入式C编程中,免不了要用到软件延时。

这一般通过循环语句实现。

通过控制循环语句的循环次数,便可获得多种不同的延时时间。

为了便于使用和提高程序代码的复用率,一般又将循环语句封装成一个带参数的函数,称为延时函数。

如:void wait(unsigned int n){unsigned int i;for(i=0;i<n;i++);}延时函数的参数(形参,如上例中的变量 n ),即为控制循环语句循环次数的变量。

这样,在需要软件延时的时候,只需要调用延时函数,并将实际参数(实参,即n的实际值)代入形参,便可获得与该实际参数对应的延时时间。

这便是经典的软件延时的实现方法,非常简单。

但细心的读者会发现:延时函数的参数(比如上面的 n ),表征的是循环语句的“循环次数”,而不是“实际的延时时间”。

一般来说,假令循环语句每循环一次的时间为 b(注意,单位是“步”,即一个时钟周期,下同),函数调用、传值和返回所需的固有时间为 a ,那么,给定参数 n 时,调用一次延时函数实际实现的延时时间应为 t = a + b*n , ——而不是 n !这就意味着,当需要的延时时间为 t 时,应当传入的实参为 n = (t-a)/b,而不是 t 。

这样,为了获得比较准确的延时,每次调用函数之前,都要手工计算实际参数,很不方便;其次,当需要改变晶振频率的时候,程序中所有的延时参数都要重新计算,这显然不利于程序的移植。

为了解决这两个问题,提高程序的可移植性,可以利用宏定义的方式,对延时函数进行参数预修正。

例如,对上面给出的wait延时函数,可以使用下面的宏定义:#define delay(n) wait( ( (n) - a ) / b )这样,调用 delay(t) 就意味着调用 wait( (t-a)/b ) ,从而得到时间为t的延时,实现了参数与延时时间的同步,使用起来更加方便。

为了进一步提高可移植性,使软件延时能够适应不同的晶振频率,应当顺着上面的思路选择寻找更优方案。

C语言延时子程序准确设置

C语言延时子程序准确设置

C语言延时子程序准确设置
在给单片机写程序的时候往往需要一个微秒或者毫秒的延时子程序,但是C语言不同于汇编,很难根据语句确定准确的延时时间,经过各种查资料得到一种简单实用的方法:通过keil下断点调试确定时间。

就是编写一个延时子程序,然后在延时程序处和while(1)设置断点,运行程序,在调试模式下就可以获得该延时子程序的准确延时时间。

1,编写如下源程序:
#include
void delay_ms(unsigned intms)
{
unsigned int i;
unsigned char j;
for(i=0;i
{
for(j=0;j<200;j++);
for(j=0;j<102;j++);
}
}
void main (void)
{
delay_ms(1);
while(1);
}
2,下图位置设置断点
3,进入运行模式,开始运行(1处所示),程序会在延时子程序前的断点处停下,此时记录程序运行时间,2处所示。

4,再次点运行(1处所示),此时程序会在第二个断点处,也就是while(1)停下,这时候程序刚刚运行完延时子程序,读取此时的程序运行时间,如2所示,,二者想减就是延时子程序运行时间。

如下图:
0.00143989-0.00042209=0.0010178,约等于1mS,ok,这样就得到你所写的延时子程序的延时时间,准确的哦,可以在你得到的运行时间的基础上更改数值来得到希望的延时时间。

当然记得设置晶振为你所需要的,我这里是11.0592。

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

c语言延时程序的计算方法经典
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;
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的晶振所以在网上查找程序时如果涉及到精确延时则应该注意晶振的频率是多大。
{
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--)
DJNZ R7,HERE
CLR TR0 ;定时器要软件清零
SETB EX0
RET
C语言延时程序:
10ms延时子程序(12MHZ)
void delay10ms(void)
{

c语言精确delay函数

c语言精确delay函数

c语言精确delay函数C语言中的精确延时函数是指能够以指定的时间精确延迟程序执行的函数。

在实际开发中,我们经常会遇到需要程序暂停一段时间的情况,这时就需要使用延时函数来实现。

在C语言中,常用的延时函数有两种,一种是使用循环来实现延时,另一种是使用系统提供的延时函数。

下面将详细介绍这两种方法的实现原理及其使用场景。

1. 循环延时法循环延时法是通过循环来实现延时的方法,其原理是让程序在一个循环中空转一段时间,从而达到延时的效果。

具体实现代码如下:```cvoid delay(unsigned int ms){unsigned int i, j;for(i = 0; i < ms; i++)for(j = 0; j < 10000; j++);}```上述代码中,delay函数接收一个参数ms,表示要延时的毫秒数。

函数内部使用两个嵌套的循环,外层循环控制延时的次数,内层循环则是一个空转的过程,通过调整内层循环的次数来控制延时的时间。

循环延时法的优点是简单易懂,适用于较简单的延时场景。

但是由于循环的执行时间受到处理器的影响,不同的处理器执行相同的循环时间可能会有差异,因此不能保证延时的精确性。

2. 系统延时函数系统延时函数是通过调用系统提供的函数来实现延时的方法,其原理是让程序暂停一段时间,从而达到延时的效果。

具体实现代码如下:```c#include <unistd.h>void delay(unsigned int ms){usleep(ms * 1000);}```上述代码中,delay函数接收一个参数ms,表示要延时的毫秒数。

函数内部使用usleep函数来实现延时,usleep函数的参数是微秒,所以需要将毫秒转换为微秒。

系统延时函数的优点是精确可靠,适用于对延时精度要求较高的场景。

由于系统延时函数是由操作系统提供的,可以保证延时的精确性,不受处理器的影响。

C语言中的精确延时函数有循环延时法和系统延时函数两种方法,根据实际需求选择合适的方法来实现延时。

PIC单片机C语言延时程序和循环子程序

PIC单片机C语言延时程序和循环子程序

PIC单片机C语言延时程序和循环子程序
PIC单片机C语言延时程序和循环子程序
很多朋友说C 中不能精确控制延时时间,不能象汇编那样直观。

其实不然, 对延时函数深入了解一下就能设计出一个理想的框价出来。

一般的我们都用
for(x=100;--x;){;}此句等同与x=100;while(--x){;};
或for(x=0;x 来写一个延时函数。

在这里要特别注意:X=100,并不表示只运行100 个指令时间就跳出循环。

可以看看编译后的汇编:
x=100;while(--x){;}
汇编后:
movlw 100
bcf 3,5
bcf 3,6
movwf_delay
l2 decfsz _delay
goto l2
return
从代码可以看出总的指令是是303 个,其公式是8+3*(X-1)。

注意其中循环周期是X-1 是99 个。

这里总结的是x 为char 类型的循环体,当x 为int 时候,其中受X 值的影响较大。

建议设计一个char 类型的循环体,然后再用一个循环体来调用它,可以实现精确的长时间的延时。

8位单片机微妙延时函数

8位单片机微妙延时函数

在单片机编程中,延时函数是非常重要的部分,它可以帮助我们控制程序的执行速度和节奏。

下面是一个基于8位单片机的微妙延时函数的示例。

假设我们使用的是8位单片机,如AT89C51,并且我们使用C语言进行编程。

这个延时函数将使用循环来达到延时的效果。

```c
#include <reg51.h> // 包含单片机特定的头文件
// 延时函数,单位为微秒
void delay(unsigned int time) {
unsigned int i, j;
for (i = 0; i < time; i++) {
for (j = 0; j < 125; j++); // 假设单片机的晶振频率为12.5MHz
}
}
```
这个函数的基本原理是通过循环延迟来达到延时的效果。

在每次循环中,我们使用一个空的for循环来消耗时间,这个循环的次数正好是所需延迟时间的倒数。

这里我们假设单片机的晶振频率为12.5MHz,这是许多8位单片机常见的频率。

需要注意的是,延时函数的具体实现会根据单片机型号、晶振频率、系统时钟等不同而有所差异。

在某些情况下,可能需要更精确或更适合的延时算法。

另外,对于大规模的应用,通常建议使用专门的时间库或者操作系统提供的延时函数,这样可以避免手动编写复杂的延时逻辑。

最后,要注意的是延时函数只是实现时间控制的一个手段,具体的实现需要根据具体的需求和环境来决定。

例如,如果你的应用需要高精度的延时,那么可能需要使用更复杂的方法,如定时器中断等。

Keil C中软件实现精确延时的几种方法

Keil C中软件实现精确延时的几种方法
1ms基准延时程序设置断点计算延时时间对于熟悉汇编语言的开发人员可用keil序员可能对汇编语言不太熟悉特别是每个指令执行的时间是很难记忆的因此常使用keil的性能分析器计算延时时间
KeilC中软件实现精确延时的几种方法
赵晓东,张丽梅
(中北大学信息与通信工程学院山西太原030051)
摘要:在单片机应用系统开发过程中,经常需要编写各种延时程序,延时时间从数微秒到数秒不等,本文讨论了几种常用的软件延时及计算时间的方法,以供学习和使用。
1.2使用while循环或for循环
两种循环可以单独使用,也可以嵌套使用,即可以编写成延时函数使用,也可以在程序中直接使用,但是会有微小的差别,即增加了调用函数的时间。下面的函数可实现1ms到1s的延时,误差为16us,基本满足一般应用的要求。需要注意的是使用不同的循环变量类型,得到的延时也会不同。
1软件延时பைடு நூலகம்法
为了讨论方便,在下面的实例中采用12M晶振,即一个机器周期为1us。
1.1使用_nop_()语句
在程序中可以通过使用带_nop_()语句的函数实现延时。定义一系列不同的延时函数,如Delayl0us()、Delay20us()、Delay40us()等,需要时在主程序中调用。如延时10us的延时函数可编写如下:
void delay (uint i)
{
uchar j;
while(i--)
{
for(j=0;j<123;j++);//1ms基准延时程序
}
}
2设置断点计算延时时间
对于熟悉汇编语言的开发人员可用Keil C中的反汇编工具计算延时时间。但很多C程序员可能对汇编语言不太熟悉,特别是每个指令执行的时间是很难记忆的,因此,常使用Keil C的性能分析器计算延时时间。这里以前面介绍的for(i=0;i<124;i--)结构为例。使用这种方法时,必须先设置系统所用的晶振频率,选择Optionsfor target中的target选项,在Xtal(MHz)中填入所用晶振的频率。将程序编译后,分别在延时程序开始和结束处设置两个运行断点。选择start/stop debug session按钮进入程序调试窗口。运行程序前,要首先将程序复位,计时器清零,然后按F5键运行程序,从左边窗口的sec项可以看到程序到了第一个断点,也就是所要计算的程序段的开始处,用了多少时间;再按F5键,程序到了第2个断点处也就是所要计算的程序段的结束处,记下此时sec项显示的时间。最后用结束处的时间减去开始处时间,就得到循环程序段所占用的时间。

c语言的延时函数

c语言的延时函数

c语言的延时函数c语言中的延时函数是一种非常常用的编程方法,主要用于控制程序在某些场景下的运行速度。

在很多情况下,我们需要让程序暂停执行一段时间,以等待外部条件满足或等待其他设备的响应等等。

而这个时候,延时函数就非常有用了。

在c语言中,延时函数的实现主要是通过循环来完成的。

我们可以通过循环执行一些无用的操作,从而达到控制程序执行时间的目的。

下面我们来看一个简单的例子,实现一个延时函数:```cvoid Delay(unsigned int ms){unsigned int i, j;for(i = 0; i < ms; i++)for(j = 0; j < 1000; j++);}```上面的代码实现了一个简单的延时函数,它的参数是一个unsigned int类型的变量ms,表示需要延时的时间(以毫秒为单位)。

函数内部通过两层循环来控制程序的执行时间,循环次数为ms * 1000次。

这个函数看起来非常简单,但它确实非常实用。

不过需要注意的是,延时函数有时候也会带来一些问题。

首先,延时函数会占用CPU的执行时间。

在延时函数执行的过程中,CPU会一直处于忙碌状态,这会导致其他任务无法被及时执行。

如果延时时间过长,会影响系统的整体性能。

其次,延时函数的精度有时也不是很高。

在实际使用中,延时函数的执行时间并不是完全准确的,因为CPU的工作状态有很多不确定性因素,比如操作系统的调度、硬件设备的中断等等。

因此,我们在使用延时函数时,需要注意这点。

除了上面的问题以外,延时函数还有一些其他方面的注意事项。

比如,延时时间过短或过长都会导致系统出现异常。

因此,在使用延时函数时,我们需要事先了解系统的性能特点,并根据实际情况来选择适当的延时时间。

另外,延时函数也不是在所有的程序中都适用的。

在一些实时性要求较高的系统中,通常不能使用延时函数,因为这会影响系统的时序要求。

在这种情况下,我们通常需要使用硬件定时器或者其他更加高级的调度方式来控制程序的执行。

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

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

用单片机C语言精确延时(定时)的方法
本人在闲暇的时候对单片机C语言下的各类延时程序做了下总结。

由于单
片机C语言下利用软件延时不容易做到精确的定时,所以很多人在编写延时子
程序的时候不能好好的把握延时的具体时间。

C语言下,延时程序主要有以下
几种:
 一:
 void delay(unsigned char k){
unsigned char i,k; //定义变量 for(i=0;ik;i++); //for循环语句
 }
 该程序在Keil环境下,会先将C语言转化成汇编语言,那么我们就可以根据
汇编语言来计算出精确的时间,转化具体步骤如下:
CLR A ;指令1 MOV R7,A ;指令2 LOOP: INC R7 ;指令3 CJNE R7,k,LOOP ;指令4
 这里,指令1,指令2和指令3各消耗1个机器周期,指令4消耗两个机器
周期(可查此表得知:51hei/mcuteach/1312.html),而在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,$;。

C语言延时计算

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--); }。

for循环编写延时函数的方法

for循环编写延时函数的方法

很多初学者对于程序中ms级延时函数的编写方法比较疑惑,其原理和方式虽然简单,但是却没有相关资料。

这里用一个例程详细介绍一下。

过程参考如下:
在编译器下建立一个新项目,也可以利用已有项目。

此过程中需要注意,单片机晶振的选择,因为for循环里指令的执行时间和晶振有直接关系,本例中晶振使用11.0592M。

编写一段关于延时的函数,主要利用for循环,代码如下:
void delay_ms(unsigned int ms)
{
unsigned int i;
unsigned char j;
for(i=0;i<ms;i++)
{
for(j=0;j<200;j++);
for(j=0;j<102;j++);
}
}
其中ms是输入参数,如果输入1,就是要求程序延时1ms。

j变量是调整程序运行的时间参数。

调整j的数值,使1次循环的时间在1ms。

将此程序编译通过,然后利用软件仿真,调整时间。

两次时间差就是延时函数使用的时间,如果与1ms相差比较多,用户可以调整j 参数的值,使延时时间尽量接近1ms。

如增大j的值for(j=0;j<105;j++);
此方法得出延时函数,在晶振不同的情况下,延时时间会不准。

另外这种方法不是完全精确的延时,所以不要太深研究误差的问题。

软件调试结果,这个程序的延时时间为:1.01779ms,一般的单片机系统中都可以应用。

for循环实现延时函数解析

for循环实现延时函数解析
——for循环语句的应用
一、情景导入
(一) 实物展示,引入新课
动画:流水灯效果演示
二、编译程序查找问题
请各组同学运用keil与proteus联调仿真 led灯闪烁程序,验证课前编写的程序
请程序仿真出错的同学说一说原因
请仿真成功的同学总结for循环实现延时 函数
主要问题: for循环语
句理解不 够深刻
四、项目开发计划
1.制定方案 2.设计思路 3.硬件电路方框图 4.巡视并指导
五、项目研发
(一)单片机如何控制多个环闪烁?
设计思路
(三)提高闪烁的速度(改变延时时间参数设置方法)?
五、项目研发
(四)二进制转换十六进制
五、项目研发
(五) 设置延时时间参数
P1=0xfd; delay(500); // 1111 1101 P1=0xfd; delay(
P1=0xfb; delay(500); // 1111 1011 P1=0xfb; delay(
P1=0xf7; delay(500); // 1111 0111 P1=0xf7; delay(
P1=0xef; delay(500); // 1110 1111 P1=0xef; delay(
根据编程思路填写并设置延时时间参数;注:500ms=0.5s
六、项目验收
(三)调试与分析 (四)效果验证 (五)结果测试
七、产品验收
(一)项目评价
评价方式: 自评 互评 师评
工作态度 职业操守 团队合作 理论知识
操作过程
项目完成
1. 不旷课,不迟到,不早退 2. 课堂回答问题,学习积极性高 3. 学习认真,上课不开小差 4. 按时完成作业,字迹工整,整洁美观 1. 安全、文明工作 2. 具有良好的职业操守 3. 符合6S管理理念 1. 服从组长的工作安排 2. 按时完成组长分配的任务 3. 热心帮助小组其他成员 1.资讯部分单片机IO的理解 2.资讯部分单片机存储器的理解 3. 资讯部分对C语言程序的理解 硬件: 1.绘制硬件框图、原理图 2.电路安装调试检修 3.正确使用开发板,使用仪表设备、排查硬件故障 软件: 1.正确绘制软件流程图 2.主程序设计 3.子程序设计 1. 功能全部实现 2. 性能达到标准 3. 有创新点
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
3us
三层循环: R7*(m+3) = 15*33333 = 499995us DJNZ 2us + R6赋值 1us =
3us
循环外: 5us 子程序调用 2us + 子程序返回 2us + R7赋值 1us =
5us
延时总时间 = 三层循环 + 循环外 = 499995+5 = 500000us =500ms
{
unsigned char h,i,j,k;
for(h=3;h>0;h--)
for(i=5;i>0;i--)
for(j=82;j>0;j--)
for(k=19;k>0;k--);
}

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 =
}
产生ห้องสมุดไป่ตู้汇编
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
四. 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
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: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: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
计算公式:延时时间=[(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--);
样我没有去试.所有这些都没有给出具体的实例程序来.还看到一些延时的例子多多少少总有点延时差.为此我用for循环写了几个延
时的子程序贴上来,希望能对初学者有所帮助.(晶振12MHz,一个机器周期1us.)
一. 500ms延时子程序
程序:
void delay500ms(void)
{
unsigned char i,j,k;
如何利用for循环实现C语言的精确延时
C语言最大的缺点就是实时性差,我在网上到看了一些关于延时的讨论,其中有篇文章51单片机 Keil C 延时程序的简单研究,
他是用while(--i);产生DJNZ 来实现精确延时,后来有人说如果while里面不能放其它语句,否则也不行,用do-while就可以,具体怎
C:0x080E DFF2 DJNZ R7,C:0802
C:0x0810 22 RET
在精确延时的计算当中,最容易让人忽略的是计算循环外的那部分延时,在对时间要求不高的场合,这部分对程序不会造成影响.
以下为6MHZ的晶振8051的核心单片机C语言的延时1秒的延时:
void delay1s(void)
相关文档
最新文档