单片机延时程序经验

发布者:eaff86最新更新时间:2013-03-19 来源: 21ic关键字:单片机  延时程序  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指令来完成,相当于如下指令:

MOV 09H,#0FFH

LOOP: DJNZ 09H,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结构来完成,每个循环体内的变量仍然采用无符号字符变量。

unsigned char i,j

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

for(j=255;j>0;j--);

unsigned char i,j

i=255;

do{j=255;

do{j--}

while(j);

i--;

}

while(i);

unsigned char i,j

i=255;

while(i)

{j=255;

while(j)

{j--};

i--;

}

这三种方法都是用DJNZ指令嵌套实现循环的,由C51编译器用下面的指令组合来完成的

MOV R7,#0FFH

LOOP2: MOV R6,#0FFH

LOOP1: DJNZ R6,LOOP1

DJNZ R7,LOOP2

这些指令的组合在汇编语言中采用DJNZ指令来做延时用,因此它的时间精确计算也是很简单,假上面变量i的初值为m,变量j的初值为n,则总延时时间为:m×(n×T+T),其中T为DJNZ指令执行时间(DJNZ指令为双周期指令)。这里的+T为MOV这条指令所使用的时间。同样对于更长时间的延时,可以采用多重循环来完成。[page]

只要在程序设计循环语句时注意以上几个问题。

下面给出有关在C51中延时子程序设计时要注意的问题

1、在C51中进行精确的延时子程序设计时,尽量不要或少在延时子程序中定义局部变量,所有的延时子程序中变量通过有参函数传递。

2、在延时子程序设计时,采用do…while,结构做循环体要比for结构做循环体好。

3、在延时子程序设计时,要进行循环体嵌套时,采用先内循环,再减减比先减减,再内循环要好。

unsigned char delay(unsigned char i,unsigned char j,unsigned char k)

{unsigned char b,c;

b="j";

c="k";

do{

do{

do{k--};

while(k);

k="c";

j--;};

while(j);

j=b;

i--;};

while(i);

}

这精确延时子程序就被C51编译为有下面的指令组合完成

delay延时子程序如下:

MOV R6,05H

MOV R4,03H

C0012: DJNZ R3, C0012

MOV R3,04H

DJNZ R5, C0012

MOV R5,06H

DJNZ R7, C0012

RET

假设参数变量i的初值为m,参数变量j的初值为n,参数变量k的初值为l,则总延时时间为:l×(n×(m×T+2T)+2T)+3T,其中T为DJNZ和MOV指令执行的时间。当m=n=l时,精确延时为9T,最短;当m=n=l=256时,精确延时到16908803T,最长。

实现延时通常有两种方法:一种是硬件延时,要用到定时器/计数器,这种方法可以提高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。主函数调用Delay10us( )时,先执行一个LCALL指令(2 μs),然后执行6个_NOP_( )语句(6 μs),最后执行了一个RET指令(2 μs),所以执行上述函数时共需要10 μs。  可以把这一函数当作基本延时函数,在其他函数中调用,即嵌套调用[4],以实现较长时间的延时;但需要注意,如在Delay40us( )中直接调用4次Delay10us( )函数,得到的延时时间将是42 μs,而不是40 μs。这是因为执行Delay40us( )时,先执行了一次LCALL指令(2 μs),然后开始执行第一个Delay10us( ),执行完最后一个Delay10us( )时,直接返回到主程序。依此类推,如果是两层嵌套调用,如在Delay80us( )中两次调用Delay40us( ),则也要先执行一次LCALL指令(2 μs),然后执行两次Delay40us( )函数(84 μs),所以,实际延时时间为86 μs。简言之,只有最内层的函数执行RET指令。该指令直接返回到上级函数或主函数。如在Delay80μs( )中直接调用8次Delay10us( ),此时的延时时间为82 μs。通过修改基本延时函数和适当的组合调用,上述方法可以实现不同时间的延时。

2.2 在C51中嵌套汇编程序段实现延时

在C51中通过预处理指令#pragma asm和#pragma endasm可以嵌套汇编语言语句。用户编写的汇编语言紧跟在#pragma asm之后,在#pragma endasm之前结束。

如:#pragma asm

汇编语言程序段

#pragma endasm[page]

延时函数可设置入口参数,可将参数定义为unsigned char、int或long型。根据参数与返回值的传递规则,这时参数和函数返回值位于R7、R7R6、R7R6R5中。在应用时应注意以下几点:

◆ #pragma asm、#pragma endasm不允许嵌套使用;

◆ 在程序的开头应加上预处理指令#pragma asm,在该指令之前只能有注释或其他预处理指令;

◆ 当使用asm语句时,编译系统并不输出目标模块,而只输出汇编源文件;

◆ asm只能用小写字母,如果把asm写成大写,编译系统就把它作为普通变量;

◆ #pragma asm、#pragma endasm和 asm只能在函数内使用。

将汇编语言与C51结合起来,充分发挥各自的优势,无疑是单片机开发人员的最佳选择。

2.3 使用示波器确定延时时间

利用示波器来测定延时程序执行时间。方法如下:编写一个实现延时的函数,在该函数的开始置某个I/O口线如P1.0为高电平,在函数的最后清P1.0为低电平。在主程序中循环调用该延时函数,通过示波器测量P1.0引脚上的高电平时间即可确定延时函数的执行时间。方法如下:

sbit T_point = P1^0;

void Dly1ms(void) {

unsigned int i,j;

while (1) {

T_point = 1;

for(i=0;i<2;i++){

for(j=0;j<124;j++){;}

}

T_point = 0;

for(i=0;i<1;i++){

for(j=0;j<124;j++){;}

}

}

}

void main (void) {

Dly1ms();

}

把P1.0接入示波器,运行上面的程序,可以看到P1.0输出的波形为周期是3 ms的方波。其中,高电平为2 ms,低电平为1 ms,即for循环结构“for(j=0;j<124;j++) {;}”的执行时间为1 ms。通过改变循环次数,可得到不同时间的延时。当然,也可以不用for循环而用别的语句实现延时。这里讨论的只是确定延时的方法。

2.4 使用反汇编工具计算延时时间

用Keil C51中的反汇编工具计算延时时间,在反汇编窗口中可用源程序和汇编程序的混合代码或汇编代码显示目标应用程序。为了说明这种方法,还使用“for (i=0;i

C:0x000FE4CLRA//1T

C:0x0010FEMOVR6,A//1T

C:0x0011EEMOVA,R6//1T

C:0x0012C3CLRC//1T

C:0x00139FSUBBA,DlyT //1T

C:0x00145003JNCC:0019//2T

C:0x00160E INCR6//1T

C:0x001780F8SJMPC:0011//2T

可以看出,0x000F~0x0017一共8条语句,分析语句可以发现并不是每条语句都执行DlyT次。核心循环只有0x0011~0x0017共6条语句,总共8个机器周期,第1次循环先执行“CLR A”和“MOV R6,A”两条语句,需要2个机器周期,每循环1次需要8个机器周期,但最后1次循环需要5个机器周期。DlyT次核心循环语句消耗(2+DlyT×8+5)个机器周期,当系统采用12 MHz时,精度为7 μs。

当采用while (DlyT--)循环体时,DlyT的值存放在R7中。相对应的汇编代码如下:

C:0x000FAE07MOVR6, R7//1T

C:0x00111F DECR7//1T

C:0x0012EE MOVA,R6//1T

C:0x001370FAJNZC:000F//2T

循环语句执行的时间为(DlyT+1)×5个机器周期,即这种循环结构的延时精度为5 μs。

通过实验发现,如将while (DlyT--)改为while (--DlyT),经过反汇编后得到如下代码:

C:0x0014DFFE DJNZR7,C:0014//2T

可以看出,这时代码只有1句,共占用2个机器周期,精度达到2 μs,循环体耗时DlyT×2个机器周期;但这时应该注意,DlyT初始值不能为0。

注意:计算时间时还应加上函数调用和函数返回各2个机器周期时间。

关键字:单片机  延时程序  C语言 引用地址:单片机延时程序经验

上一篇:单片机程序延时方法详细介绍
下一篇:单片机C语言基础编程源码八则

推荐阅读最新更新时间:2024-03-16 13:20

手把手教您编写第一个单片机程序
51单片机的开发环境是Keil 软件。Keil 软件虽然是一个收费软件,但从uVision2到目前的uVison4版本都有破解版,在网上都可以找到下载。笔者推荐大家使用uVisong4破解版本,好处不用多说。Keil uVision4软件的压缩包里附有安装和破解说明,本文不再赘述。 开发一个单片机程序,一般都要经过这几个步骤:建立工程- 建立C文件- 添加C文件到工程- 编写C代码- 设置目标工程的选项- 编译工程产生HEX文件- 将HEX文件下载到单片机。本文将一步一步手把手教您开发一个LED闪烁的简单且实用的C51程序。让您从0基础起步学习开发51单片机。 安装Keil uVison4之后,第一次运行出现如图1的界面,从上
[单片机]
手把手教您编写第一个<font color='red'>单片机</font><font color='red'>程序</font>
AVR单片机的RC5和RC6算法比较与改进
摘要:RC5及RC6是两种新型的分组密码。AVR高速嵌入式单片机功能强大,在无线数据传输应用方面很有优势。本文基于Atmega128高速嵌入式单片机,实现RC5和RC6加密及解密算法,并对算法进行汇编语言的优化及改进。根据实验结果。对两种算法的优热点进行比较和分析。 关键词:Atmega128 RC5 RC6 分组密码 混合密钥 Flash 引言 在无线局域网中,传输的介质主要是无线电波和红外线,任何具有接收能力的窍听者都有可能拦截无线信道中的数据,掌握传输的内容,造成数据泄密。因此,对于无线局域网来说,数据的加密是关键技术之一。 AVR高速嵌入式单片机是8位RISC MCU,执行大多数指令只需一个时钟周期,速度快(8M
[单片机]
51单片机驱动点阵显示数字程序+电路
电路原理图:X轴为P2 Y轴为P0 c51单片机程序代码: #include reg52.H #include intrins.h #define uint unsigned int #define uchar unsigned char //1 unsigned char code tab1P0 ={0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; unsigned char code tab1P2 ={0xff,0xcF,0xc7,0xc3,0xcf,0xcf,0xcf,0xff}; //2 unsigned char code tab2P0 ={0x0
[单片机]
51<font color='red'>单片机</font>驱动点阵显示数字<font color='red'>程序</font>+电路
基于GPRS的单片机固件升级系统设计
引言 嵌入式技术的迅速发展使得越来越多的嵌入式终端设备应用在人们的日常生活中,其中不乏应用在一些偏远地方,甚至工作在无人看管的场合下。人口比较稀少的地方,由于基站分布比较分散,加之人口比较稀疏,基站维护等操作常难以执行,这就需要在某些地方放置网络信号测试仪检测该地区的通信信号质量,并将该信息反馈到远程服务器。同时,由于硬件系统程序设计固有的局限性,固件程序的升级在所难免。针对实际情况,本文开发了网络信号测试仪的单片机远程升级系统。 1 系统硬件设计 整个系统以Silicon Labs公司推出的混合信号片上系统型单片机C8051F340作为核心控制单元,采用GSM/GPRS/EDGE无线模块MC75作为与远程服务器的通
[单片机]
AVR单片机C语言入门一例
AVR单片机C语言编译软件有IAR、ICCAVR、winavr、Atmanavr、CodeVisionAVR等。其中CodeVisionAVR又称 CVAVR,它可以说是目前最容易入门的C编译器,它体积小巧,但是代码效率却很高, 风格与keil-C51类似,与Keil-C51一样支持位变量、支持IO端口的位操作(其它的如IAR、ICCAVR、GCCAVR都没有此功能)下面就以CodeVisionAVR1.25.1为例来说说如何使用这个软件。   设置软件的工作界面。软件的默认字体并不太好看,需要设置一下,先运行CodeVisionAVR,点击菜单栏的 Settings 选择 Editor 就可以打开设置界面了,其中 Font 就是
[单片机]
谈谈51单片机延时程序
延时程序在单片机编程中使用非常广泛,但一些读者在学习中不知道延时程序怎么编程,不知道机器 周期和指令周期的区别,不知道延时程序指令的用法, ,本文就此问题从延时程序的基本概念、机器周期和指 令周期的区别和联系、相关指令的用法等用图解法的形式详尽的回答读者 我们知道程序设计是单片机开发最重要的工作,而程序在执行过程中常常需要完成延时的功能。例如 在交通灯的控制程序中,需要控制红灯亮的时间持续30秒,就可以通过延时程序来完成。延时程序是如何 实现的呢?下面让我们先来了解一些相关的概念。 一、机器周期和指令周期 1.机器周期是指单片机完成一个基本操作所花费的时间,一般使用微秒来计量单片机的运行速度, 51 单片机的一个
[单片机]
单片机进行脉宽调制(PWM) 直流电机调速测试程序
单片机 进行脉宽 调制 ( PWM ) 直流电机调速测试程序 ;UNL2003提供电机驱动 电流 .( =500MA/5V) ;使用六个按键实现六种不同速度 DC BIT P1.0 speed equ 20h org 000h jmp dc_MOTOR ORG 100H dc_MOTOR: MOV a,p1 MOV speed,a ;键盘去抖动 lcall del MOV a,p1 cjne a,speed,dc_MOTOR JB P3.3,JUD
[单片机]
基于单片机的智能输液控制系统设计
0 引言 随着智能化控制研究的不断发展,自动化临床设备的研究日益成为医疗器械发展的一个重点,因而设计一种智能输液管理系统实现对输液过程的全程监控是医学发展的必然趋势。本文以远程监控实现输液实时监测为目标,通过下位机采集各床位患者的输液信息,再以无线的方式将数据传达至上位机,实现输液数据的实时显示和存储,以及在特殊情况下的报警等功能。 1 系统总体设计 系统由主、从站(或上位机和下位机)构成,核心控制器件是单片机。主站由数据通信单片机组成,从站由数据处理单片机和数据通信单片机组成。主要包括四个设计模块:a.从站数据采集电路,包括液滴信号的采集和输毕信号的采集;b.从站数据处理电路,包括实时数据的显示、处理及控制;c.从站数据发
[单片机]
基于<font color='red'>单片机</font>的智能输液控制系统设计
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
  • ARM裸机篇--按键中断
    先看看GPOI的输入实验:按键电路图:GPF1管教的功能:EINT1要使用GPF1作为EINT1的功能时,只要将GPFCON的3:2位配置成10就可以了!GPF1先配 ...
  • 网上下的--ARM入门笔记
    简单的介绍打今天起菜鸟的ARM笔记算是开张了,也算给我的这些笔记找个存的地方。为什么要发布出来?也许是大家感兴趣的,其实这些笔记之所 ...
  • 学习ARM开发(23)
    三个任务准备与运行结果下来看看创建任务和任运的栈空间怎么样的,以及运行输出。Made in china by UCSDN(caijunsheng)Lichee 1 0 0 ...
  • 学习ARM开发(22)
    关闭中断与打开中断中断是一种高效的对话机制,但有时并不想程序运行的过程中中断运行,比如正在打印东西,但程序突然中断了,又让另外一个 ...
  • 学习ARM开发(21)
    先要声明任务指针,因为后面需要使用。 任务指针 volatile TASK_TCB* volatile g_pCurrentTask = NULL;volatile TASK_TCB* vol ...
  • 学习ARM开发(20)
  • 学习ARM开发(19)
  • 学习ARM开发(14)
  • 学习ARM开发(15)
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved