实现单片机延时方法总结

发布者:心灵律动最新更新时间:2017-11-18 来源: eefocus关键字:单片机  延时方法 手机看文章 扫描二维码
随时随地手机看文章

    实现延时通常有两种方法:一种是硬件延时,要用到定时器/计数器,这种方法可以提高CPU的工作效率,也能做到精确延时;另一种是软件延时,这种方法主要采用循环体进行。

    1、使用定时器/计数器实现精确延时

    单片机系统一般常选用11.0592MHz、12MHz或6MHz晶振。第一种更容易产生各种标准的波特率,后两种的一个机器周期分别为1μs和2μs,便于精确延时。本程序中假设使用频率为12MHz的晶振。最长的延时时间可达216=65536μs。若定时器工作在方式2,则可实现极短时间的精确延时;如使用其他定时方式,则要考虑重装定时初值的时间(重装定时器初值占用2个机器周期)。

    在实际应用中,定时常采用中断方式,如进行适当的循环可实现几秒甚至更长时间的延时。使用定时器/计数器延时从程序的执行效率和稳定性两方面考虑都是最佳的方案。但应该注意,C51编写的中断服务程序编译后会自动加上PUSHACC、PUSHPSW、POPPSW和POPACC语句,执行时占用了4个机器周期;如程序中还有计数值加1语句,则又会占用1个机器周期。这些语句所消耗的时间在计算定时初值时要考虑进去,从初值中减去以达到最小误差的目的。

    2、软件延时与时间计算

    在很多情况下,定时器/计数器经常被用作其他用途,这时候就只能用软件方法延时。下面介绍几种软件延时的方法。

    2.1短暂延时

    可以在C文件中通过使用带_NOP_()语句的函数实现,定义一系列不同的延时函数,如Delay10us()、Delay25us()、Delay40us()等存放在一个自定义的C文件中,需要时在主程序中直接调用。如延时10μs的延时函数可编写如下:

    voidDelay10us(){

    _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中通过预处理指令#pragmaasm和#pragmaendasm可以嵌套汇编语言语句。用户编写的汇编语言紧跟在#pragmaasm之后,在#pragmaendasm之前结束。

    如:#pragmaasm

    …

    汇编语言程序段

    …

    #pragmaendasm

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

    ◆#pragmaasm、#pragmaendasm不允许嵌套使用;

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

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

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

    ◆#pragmaasm、#pragmaendasm和asm只能在函数内使用。

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

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

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

    sbitT_point=P1^0;

    voidDly1ms(void){

    unsignedinti,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++){;}

    }

    }

    }

    voidmain(void){

    Dly1ms();

    }

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

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

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

    for(i=0;i

    C:0000FE4CLRA//1T

    C:00010FEMOVR6,A//1T

    C:00011EEMOVA,R6//1T

    C:00012C3CLRC//1T

    C:000139FSUBBA,DlyT//1T

    C:000145003JNCC:0019//2T

    C:000160EINCR6//1T

    C:0001780F8SJMPC:0011//2T

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

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

    C:0000FAE07MOVR6,R7//1T

    C:000111FDECR7//1T

    C:00012EEMOVA,R6//1T

    C:0001370FAJNZC:000F//2T

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

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

    C:00014DFFEDJNZR7,C:0014//2T

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

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

关键字:单片机  延时方法 引用地址:实现单片机延时方法总结

上一篇:单片机RAM故障测试方法
下一篇:单片机上Flash和EEPROM的异同

推荐阅读最新更新时间:2024-03-16 15:45

单片机初学者更好学习单片机的建议
  1、单片机种类不要贪多   单片机生产厂家众多,种类繁多,例如PIC单片机就有多达500种型号!显然要把各种单片机都学会是不可能的,也是没有必要的。实际上一个人会1 2种单片机(例如STC、AVR、STM32等)就足够了。我们多年来做过100多个单片机项目,主要使用的不过就3种单片机。   对于初学者,建议就选一种单片机为主(当然,最基础的51单片机是必学的),把它学透、用精。即使以后需要用到其它种类的单片机,由于基础扎实很快也能学会,因为单片机功能毕竟都是大同小异的。至于选用哪种单片机,最好请教有经验的老师或工程师。   2、学的精比学的多好   有些学习板号称带有几G 几十G的 免费 学习资料,且不说这些海量资料是怎么
[单片机]
MCU实战经验:多种的按键处理
按键通常有:IO口按键(BUTTON),AD按键(通过AD采样电压),IR(遥控器) 按按键功能分:有短按键,长按键,连续按键。打个比方,遥控电视机,按一下音量键,音量增加1,这个就是短按键。按住音量键不放,音量连续加,这个就是连续按键。按住一个按键5s,系统会复位,这个是长按键。 1、IO口按键,就是我们比较常见的一个IO接一个按键,或者是一个矩阵键盘。很多新人的处理方法可能是采样延时的方法,当年我也是这样的,如下 if(GETIO==low) { delay_10ms() if(GETIO==low) { //得到按键值 } } 这种方法虽然简单,但是有很大弊端。首先 D
[单片机]
FPGA进入传感器协处理领域 比MCU功耗还低
智慧型手机的兴起,连带使得感测元件的重要性也跟著水涨船高,像是MEMS领域的三轴加速度计、陀螺仪与磁力计等,都可说是智慧型手机的标準配备。也因為如此,诸如ST(意法半导体)或是TI(德州仪器)都提出了以MCU(微控制器)来处理感测器元件所带来的资讯,这种概念就被统称為「Sensor Hub」。 这种作法其实类似於电源或是音讯处理器的独立设计考量,让许多不同的类比讯号先由外部的处理器先行处理,以减轻应用处理器不必要的处理负担,除了达到有效分工之外,应用处理器本身也可以降低功耗。这种作法,过去一般是由MCU来担当大任,但这种独大的局面,似乎将会被某些可编程晶片业者所打破。 我们都知道,Lattice併购Silicon Blue之后
[嵌入式]
AVR单片机(学习ing)—(一)、ATMEGA16的I\0端口的使用—01
一、ATMEGA16的I\0端口的使用:(只有一个实验,下面的部分每个小节可能有几个实验验证,你懂得) 一—(01)、)—使用4*4行列式按键开关的使用 I/O端口介绍: 直接一个图就哦了,因为根本没什么,就是控制寄存器(这里一定要注意,后面的ATmega16的引脚的功能都是控制寄存器来实现引脚或者器件的功能的,说白了,知道了寄存器,会用了寄存器,再来点51的基础,那这些东西真的就没什么了,AVR单片机很简单的~~~) 我用的就是IAR和Proteus(我这还有AVRStudio和WinAVR,有要的Q我,哈哈 好了先给个图,这个是按照手机上的设计的~~你看了就懂了 别的就不费话了,一看图不就全明白了 然后就是今天的
[单片机]
AVR<font color='red'>单片机</font>(学习ing)—(一)、ATMEGA16的I\0端口的使用—01
基于A3967SLB的步进电机细分驱动系统设计
步进电机精度高,惯性小,在不失步的情况下没有步距误差积累,特别适用于数字控制的定位系统。传统的细分驱动电路由细分环行分配器、放大器和合成器等部分组成。这种电路应用复杂,灵活性差。本文利用A3967SLB作为步进电机微控芯片,简化了步进电机的控制实现。由于单片机资源没有PC丰富,人机界面也没有PC友好,因此,本文采用了主从式结构,即PC用于管理,单片机用于执行。 由A3967SLB构成步进电机的驱动部分 A3967SLB是美国Allegro公司生产的PWM恒流控制微步距驱动二相步进电机专用驱动器。它的工作电压可达30V,驱动电流达750mA,一个A3967SLB即可驱动一台二相步进电机,可实现8细分驱动。芯片内部的PWM电流控制电
[工业控制]
一种基于MC32P21单片机的移动电源电路设计
移动电源 是一种集供电和充电功能于一体的便携式充电器,可以给手机等数码设备随时随地充电或待机供电。一般由锂电芯或者干电池作为储电单元。区别于产品内部配置的电池,也叫外挂电池。一般配备多种电源转接头, 通常具有大容量、多用途、体积小、寿命长和安全可靠等特点,是可随时随地为智能手机、平板电脑、数码相机、MP3、MP4等多种数码产品供电或待机充电的功能产品。 移动电源可以通过USB电缆线使用在任何符合USB国际标准的设备,其具有短路、过充过放、恒流恒压等保护措施,还有高性能电源管理技术。 移动电源方案,根据是否可以编程,分为硬件移动电源和软件移动电源两种技术路线。硬件移动电源方案主要存在的问题是:1.发热严重,采用非同步整流模式,温度高
[电源管理]
一种基于MC32P21<font color='red'>单片机</font>的移动电源电路设计
STM8L151C8单片机学习例程(14)——LoRa_RX+TX
STM8L_14_LoRa_RX+TX: Function: RTC定时唤醒,LoRa无线收发,串口打印收发数据 RTC定时10s发一次,active-halt模式低功耗唤醒,LoRa收发数据,串口打印 #include bsp.h // 常量定义 #define TX 1 // 发送模式 #define RX 0 // 接收模式 #define SEND_MAX 30 // 测试发送最大值 #define SEND_GAP 1000 // 每间隔1s发送一次数据 #define RECV_TIMEOUT 800 // 接收超时 #define ACK
[单片机]
STM8L151C8<font color='red'>单片机</font>学习例程(14)——LoRa_RX+TX
基于C8051F016单片机和功率放大器实现程控三相交流功率源的设计
前言 程控三相交流功率源的应用十分广泛,它被大量应用于冶金、通信、化工、电力及军工等诸多行业。用于交流调压、调功、调光及电机软启动等工业自动化控制领域,还可以用于计量以及产品的性能试验等方面。用于计量和产品试验等领域的功率源对于其输出波形要求较高,要求功率源输出完整的正弦波信号,对于正弦波的失真度有一定的限制。目前此类交流功率源的实际输出功率都很小,它们一般只强调单项指标,即电流或电压输出。而用于电能表计量时,其功率源输出的不是真实的功率,而是利用产生“虚功率”的方法来实现电能的计量。在某些产品的性能试验或计量过程中需要产生实际的交流功率,且要求其任意相的电流、电压、相位都能够独立调节。目前的交流功率源都无法满足要求,本文介绍的三
[单片机]
基于C8051F016<font color='red'>单片机</font>和功率放大器实现程控三相交流功率源的设计
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

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

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