单片机89C51精确延时
- 格式:docx
- 大小:19.25 KB
- 文档页数:3
单片机精确毫秒延时函数单片机精确毫秒延时函数实现延时通常有两种方法:一种是硬件延时,要用到定时器/计数器,这种方法可以提高CPU的工作效率,也能做到精确延时;另一种是软件延时,这种方法主要采用循环体进行。
今天主要介绍软件延时以及单片机精确毫秒延时函数。
单片机的周期介绍在电子技术中,脉冲信号是一个按一定电压幅度,一定时间间隔连续发出的脉冲信号。
脉冲信号之间的时间间隔称为周期;而将在单位时间(如1秒)内所产生的脉冲个数称为频率。
频率是描述周期性循环信号(包括脉冲信号)在单位时间内所出现的脉冲数量多少的计量名称;频率的标准计量单位是Hz(赫)。
电脑中的系统时钟就是一个典型的频率相当精确和稳定的脉冲信号发生器。
指令周期:CPU执行一条指令所需要的时间称为指令周期,它是以机器周期为单位的,指令不同,所需的机器周期也不同。
对于一些简单的的单字节指令,在取指令周期中,指令取出到指令寄存器后,立即译码执行,不再需要其它的机器周期。
对于一些比较复杂的指令,例如转移指令、乘法指令,则需要两个或者两个以上的机器周期。
通常含一个机器周期的指令称为单周期指令,包含两个机器周期的指令称为双周期指令。
时钟周期:也称为振荡周期,一个时钟周期= 晶振的倒数。
对于单片机时钟周期,时钟周期是单片机的基本时间单位,两个振荡周期(时钟周期)组成一个状态周期。
机器周期:单片机的基本操作周期,在一个操作周期内,单片机完成一项基本操作,如取指令、存储器读/写等。
机器周期=6个状态周期=12个时钟周期。
51单片机的指令有单字节、双字节和三字节的,它们的指令周期不尽相同,一个单周期指令包含一个机器周期,即12个时钟周期,所以一条单周期指令被执行所占时间为12*(1/ 晶振频率)= x s。
常用单片机的晶振为11.0592MHz,12MHz,24MHz。
其中11.0592MHz 的晶振更容易产生各种标准的波特率,后两种的一个机器周期分别为1 s和2 s,便于精确延时。
1,_nop_() 适用于us级的少量延时标准的C语言中没有空语句。
但在单片机的C语言编程中,经常需要用几个空指令产生短延时的效果。
这在汇编语言中很容易实现,写几个nop就行了。
在keil C51中,直接调用库函数:#include<intrins.h> //声明了void _nop_(void);_nop_(); //产生一条NOP指令作用:对于延时很短的,要求在us级的,采用“_nop_”函数,这个函数相当汇编NOP指令,延时几微秒。
NOP指令为单周期指令,可由晶振频率算出延时时间,对于12M晶振,延时1uS。
2,一般延时大于10us一,定义的C51中循环变量,尽量采用无符号字符型变量。
二,在FOR循环语句中,尽量采用变量减减来做循环。
三,在do…while,while语句中,循环体内变量也采用减减方法这因为在C51编译器中,对不同的循环方法,采用不同的指令来完成的例:unsigned char i;for(i=255;i>0;i--);用keil C51编译后MOV09H,#0FFHLOOP:DJNZ09H,LOOP指令相当简洁,也很好计算精确的延时时间。
3,延时更长,达到MS级,这时需要嵌套循环循环嵌套的方法常用于达到ms级的延时。
对于循环语句同样可以采用for,do…while,while结构来完成,每个循环体内的变量仍然采用无符号字符变量。
例:unsigned char i,jfor(i=255;i>0;i--)for(j=255;j>0;j--);或unsigned char i,ji=255;do{j=255;do{j--}while(j);i--;}while(i);或unsigned char i,ji=255;while(i){j=255;while(j){j--};i--;}下面给出有关在C51中延时子程序设计时要注意的问题(一些经验之谈)1、在C51中进行精确的延时子程序设计时,尽量不要或少在延时子程序中定义局部变量,所有的延时子程序中变量通过有参函数传递。
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秒钟的延时。
51单片机延时程序51单片机延时程序应用单片机的时候,经常会遇到需要短时间延时的情况。
需要的延时时间很短,一般都是几十到几百微妙(us)。
有时候还需要很高的精度,比如用单片机驱动DS18B20的时候,误差容许的范围在十几us 以内,不然很容易出错。
这种情况下,用计时器往往有点小题大做。
而在极端的情况下,计时器甚至已经全部派上了别的用途。
这时就需要我们另想别的办法了。
以前用汇编语言写单片机程序的时候,这个问题还是相对容易解决的。
比如用的是12MHz晶振的51,打算延时20us,只要用下面的代码,就可以满足一般的需要:mov r0, #09hloop: djnz r0, loop51 单片机的指令周期是晶振频率的1/12,也就是1us一个周期。
mov r0, #09h需要2个极其周期,djnz也需要2个极其周期。
那么存在r0里的数就是(20-2)/2。
用这种方法,可以非常方便的实现256us 以下时间的延时。
如果需要更长时间,可以使用两层嵌套。
而且精度可以达到2us,一般来说,这已经足够了。
现在,应用更广泛的毫无疑问是Keil的C编译器。
相对汇编来说,C固然有很多优点,比如程序易维护,便于理解,适合大的项目。
但缺点(我觉得这是C的唯一一个缺点了)就是实时性没有保证,无法预测代码执行的指令周期。
因而在实时性要求高的场合,还需要汇编和C的联合应用。
但是是不是这样一个延时程序,也需要用汇编来实现呢?为了找到这个答案,我做了一个实验。
用C语言实现延时程序,首先想到的就是C常用的循环语句。
下面这段代码是我经常在网上看到的:void delay2(unsigned char i){for(; i != 0; i--);到底这段代码能达到多高的精度呢?为了直接衡量这段代码的效果,我把 Keil C 根据这段代码产生的汇编代码找了出来:; FUNCTION _delay2 (BEGIN); SOURCE LINE # 18;---- Variable i assigned to Register R7 ----; SOURCE LINE # 19; SOURCE LINE # 200000 ?C0007:0000 EF MOV A,R70001 6003 JZ ?C00100003 1F DEC R70004 80FA SJMP ?C0007; SOURCE LINE # 210006 ?C0010:0006 22 RET; FUNCTION _delay2 (END)真是不看不知道~~~一看才知道这个延时程序是多么的不准点~~~光看主要的那四条语句,就需要6个机器周期。
单片机C51延时时间怎样计算?C程序中可使用不同类型的变量来进行延时设计。
经实验测试,使用unsigned char类型具有比unsigned int更优化的代码,在使用时应该使用unsigned char作为延时变量。
以某晶振为12MHz的单片机为例,晶振为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三层循环: 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--); }。
基于89C51的多段延时过程控制器的设计作者:刘晗来源:《中国新技术新产品》2009年第23期摘要:本文论述了以89C51单片机为核心,通过单片机内部的定时来实现控制延时的功能。
采用四键设置,设置分、秒的数值由4个LED数码管显示,延时过程的通、断工作状态由红、绿发光二极管来指示,并可实现多延时设置,根据需要,本装置拟设计十段,适用于可预制的工作过程控制的场合。
关键词:89C51;多段延时;过程控制;开关1 引言在生产过程中,利用单片机的中断、计时等程序来设计多段延时开关,达到对电源重复通断的时间预制,适用于可预制工作过程控制。
其中核心部分是单片机,用按键电路实现对延时时间的设置,延时时间由单片机的内部定时器部件靠程序控制,执行器的动作用电磁继电器控制交流接触器实现。
2 系统需求分析用MCS-51系列单片机实现控制插座的延时连通和延时断开的时间。
在按键电路中,通电后,系统时钟显示00:00并闪烁,并且绿色LED亮,红色LED灭,表示系统处于等候状态,需要进行按键控制,执行机构处于断开状态。
如要转换成需要接通执行机构,通过按确认键来切换。
系统需设置四个按键,各自完成的功能为:设置/运行键当该键按下后,可以对所需的延时时间进行设置,4个LED数码管均闪烁;再按一下,系统按所设置的多段时间参数进入运行状态,对执行机构实施规定的通、断;四个LED数码管稳定显示时间参数,并逐步按秒减1显示。
分钟加1键:每按一下该按键,则对分钟进行加1并在分钟显示区显示加1后的结果,当加到59后再按一下,则显示00。
秒加1键:同分钟加1键,但加1后的显示区域为秒显示区。
确认键:当时间参数设置好后,按该键,则程序将该时间参数记录在内部的数据存储区域,并切换红绿指示灯。
如需继续输入下一段的时间参数,可以在按确认键后,继续输入时间参数,直到按下设置/运行键为止,或十段时间已经输入完毕。
3 电路硬件设计根据系统需求分析需要设计的电路硬件有如下模块:单片机基本系统模块、按键模块、LED数码管显示模块、控制执行机构模块等四部分。
SECOND EQU 40H ;给内存RAM空间中40H单元起名SECOND MINUTE EQU 41H ;给内存RAM空间中41H单元起名MINUTE HOUR EQU 42H ;给内存RAM空间中42H单元起名HOUR SECONDGEWEI EQU 43H ;给43H单元起名SECONDGEWEI存秒的个位SECONDSHIWEI EQU 44H ;给44H单元起名SECONDSHIWEI存秒的十位MINUTEGEWEI EQU 45H ;给45H单元起名MINUTEGEWEI存分的个位MINUTESHIWEI EQU 46H ;给46H单元起名MINUTESHIWEI存分的十位HOURGEWEI EQU 47H ;给47H单元起名HOURGEWEI存小时的个位HOURSHIWEI EQU 48H ;给48H单元起名HOURSHIWEI存小时的十位ORG 0000H ;复位时程序从此开始SJMP START ;跳到START进行初始化ORG 000BH ;定时器0中断入口AJMP TIMER0 ;跳转到TIMER0处ORG 0030H ;初始化程序从30H开始;---------------初始化START------------------------------START:MOV SECOND, #0 ;给秒存储单元SECOND赋初始值0MOV MINUTE, #0 ;给分存储单元MINUTE赋初始值0MOV HOUR , #12 ;给小时存储单元HOUR赋初始值12MOV DPTR , #TAB ;给数据指针赋值,将DPTR指向TAB数据表头处MOV 30H, #0 ;给30H单元赋初始值0(用于计20次的50ms中断)MOV TH0,#3CH ;给计数容器的高8位TH0赋初始值3CHMOV TL0,#0B0H ;给计数容器的低8位TL0赋初始值B0HMOV TMOD,#00000001B ; C/T位设置为0,M1M0设置位10,即模式1定时MOV TCON,#00010000B ;TR0设置为1,即启动定时器0开始工作SETB ET0 ;IE中的ET0位设置为1,开定制器中断0SETB EA ; IE中的EA位设置为1,开总中断;-----------------------主程序MAIN-----------------------------MAIN:CALL KEY ;调按键子程序KEYCALL PROCESS ;调数据处理子程序PROCESSCALL DISPLAY ;调显示子程序DISPLAYSJMP MAIN ;跳转到MAIN标号处;------------------------------按键子程序KEY调时-------------------KEY:MOV P1,#0FEH ; 行扫描LCALL DELAY ;JNB P1.4,HOURJIA ; P1.4引脚如果是低电平就跳到HOURJIA处JNB P1.5,HOURJIAN ; P1.5引脚如果是低电平就跳到HOURJIAN处JNB P1.6,MINUTEJIA ; P1.6引脚如果是低电平就跳到MIMUTEJIA处JNB P1.7,MINUTEJIAN ; P1.7引脚如果是低电平就跳到MIMUTEJIAN处FANHUI:RET ;子程序返回(如果没有按键按下)HOURJIA:CALL DELAY ;调延时程序目的是跳过按键抖动期(去抖)JB P1.4,FANHUI ; P1.4如果是高电平就跳到FANHUI处(没键按) JNB P1.4,$ ;如果P1.4是低电平就停在当前位置等键释放MOV R4,HOURCJNE R4,#23,A1 ;判断时数字是否为23AJMP A2A1:INC HOUR ;把小时位加1MOV SECOND, #0 ;小时进位,秒归0RETA2:MOV HOUR,#0 ;小时数为23时加一为0MOV SECOND, #0 ; 小时进位,秒归0RET ;子程序返回HOURJIAN:CALL DELAY ;调延时程序目的是跳过按键抖动期(去抖)JB P1.5,FANHUI ; P1.5如果是高电平就跳到FANHUI处(没键按) JNB P1.5,$ ;如果P1.5是低电平就停在当前位置等键释放MOV R5,HOURCJNE R5,#0,A3 ;判断时数字是否为23AJMP A4A3:DEC HOUR ;把小时位减1MOV SECOND, #0RETA4:MOV HOUR,#23 ;小时数为0时减一为23MOV SECOND, #0RET ;子程序返回MINUTEJIA:CALL DELAY ;调延时程序目的是跳过按键抖动期(去抖)JB P1.6,FANHUI ; P1.6如果是高电平就跳到FANHUI处(没键按) JNB P1.6,$ ;如果P1.6是低电平就停在当前位置等键释放MOV R6,MINUTECJNE R6,#59,A5 ;判断分钟数是否为59AJMP A6A5:INC MINUTE ;把分钟位加1MOV SECOND, #0 ;给秒存储单元SECOND赋初始值0RETA6:MOV SECOND, #0MOV MINUTE, #0 ;分钟数为59则分钟归0MOV R4,HOURCJNE R4,#23,A10 ;判断时数字是否为23MOV HOUR,#0 ;23时增1归0RETA10:INC HOUR ;分钟数为59 自增1后小时增1RET ;子程序返回MINUTEJIAN:CALL DELAY ;调延时程序目的是跳过按键抖动期(去抖)JB P1.7,FANHUI ; P1.7如果是高电平就跳到FANHUI处(没键按) JNB P1.7,$ ;如果P1.7是低电平就停在当前位置等键释放MOV R7,MINUTECJNE R7,#0,A7 ;判断分钟数是否为0AJMP A8A7:DEC MINUTE ;分钟不为0把分钟位减1MOV SECOND, #0RETA8:MOV MINUTE, #59 ;分钟数为0时减一为59MOV R4,HOURCJNE R4,#0,A9 ;判断时钟数是否为0MOV HOUR,#23 ;时钟数为0减1为23MOV SECOND, #0RETA9:DEC HOUR ;时钟数不为0则减1MOV SECOND, #0RET ;子程序返回;-------------------处理子程序PROCESS-----------------------PROCESS:MOV A, SECOND ;把SECOND中的秒值拷贝给AMOV B, #10 ;给寄存器B赋值10DIV AB ;A除以B,结果存入A中,余数存入B中MOV SECONDSHIWEI , A ;结果即秒的十位数拷贝给SECONDSHIWEIMOV SECONDGEWEI , B ;余数即秒的个位拷贝给SECONDGEWEIMOV A, MINUTE ;把MINUTE中的分值拷贝给AMOV B, #10 ;给寄存器B赋值10DIV AB ;A除以B,结果存入A中,余数存入B中MOV MINUTESHIWEI , A ;结果即分的十位拷贝给MINUTESHIWEIMOV MINUTEGEWEI , B ;余数即分的个位拷贝给MINUTEGEWEIMOV A, HOUR ;把HOUR中的小时值拷贝给AMOV B, #10 ;给寄存器B赋值10DIV AB ;A除以B,结果存入A中,余数存入B中MOV HOURSHIWEI , A ;结果即小时的十位拷贝给HOURSHIWEIMOV HOURGEWEI , B ;余数即小时的个位拷贝给HOURGEWEIRET ;子程序结束返回到主程序;-----------------显示子程序DISPLAY--------------DISPLAY:MOV A, HOURSHIWEI ;小时的十位拷贝给AMOVC A, @A+DPTR ;到A+DPRT这个数对应的地方找显示段码拷贝给A MOV P0, A ;把显示段码(小时的十位)送到P0CLR P2.0 ;将P2.0置低电平,对应的三极管导通CALL DELAY ;调延时(让显示小时十位的数码管持续亮一段时间)SETB P2.0 ;将P2.0置高电平,对应三极管截止,对应数码管灭MOV A, HOURGEWEI ;小时的个位拷贝给AMOVC A,@A+DPTR ; 到A+DPRT这个数对应的地方找显示段码拷贝给A MOV P0, A ;把显示段码(小时的个位)送到P0CLR P2.1 ;将P2.1置低电平,对应的三极管导通CALL DELAY ;调延时(让显示小时个位的数码管持续亮一段时间)SETB P2.1MOV P0,#7FHCLR P2.1CALL DELAYSETB P2.1 ;将P2.1置高电平,对应三极管截止,对应数码管灭MOV A, MINUTESHIWEI ;分钟的十位拷贝给AMOVC A,@A+DPTR ;到A+DPRT这个数对应的地方找显示段码拷贝给A MOV P0, A ;把显示段码(分钟的十位)送到P0CLR P2.2 ;将P2.2置低电平,对应的三极管导通CALL DELAY ;调延时(让显示分钟十位的数码管持续亮一段时间)SETB P2.2 ;将P2.2置高电平,对应三极管截止,对应数码管灭MOV A, MINUTEGEWEI ;分钟的个位拷贝给AMOVC A,@A+DPTR ;到A+DPRT这个数对应的地方找显示段码拷贝给A MOV P0, A ;把显示段码(分钟的个位)送到P0CLR P2.3 ;将P2.3置低电平,对应的三极管导通CALL DELAY ;调延时(让显示分钟个位的数码管持续亮一段时间)SETB P2.3 ;将P2.3置高电平,对应三极管截止,对应数码管灭MOV P0,#7FHCLR P2.3CALL DELAYSETB P2.3MOV A, SECONDSHIWEI ;秒的十位拷贝给AMOVC A,@A+DPTR ;到A+DPRT这个数对应的地方找显示段码拷贝给A MOV P0, A ;把显示段码(秒钟的十位)送到P0CLR P2.4 ;将P2.4置低电平,对应的三极管导通CALL DELAY ;调延时(让显示秒钟十位的数码管持续亮一段时间)SETB P2.4 ;将P2.4置高电平,对应三极管截止,对应数码管灭MOV A, SECONDGEWEI ;秒的个位拷贝给AMOVC A,@A+DPTR ;到A+DPRT这个数对应的地方找显示段码拷贝给A MOV P0, A ;把显示段码(秒钟的个位)送到P0CLR P2.5 ;将P2.5置低电平,对应的三极管导通CALL DELAY ;调延时(让显示秒钟个位的数码管持续亮一段时间)SETB P2.5 ;将P2.5置高电平,对应三极管截止,对应数码管灭RET ;显示子程序结束返回主程序;--------------------中断服务子程序----------------------------TIMER0:MOV R3, A ;把A中的数据送入R3保护起来INC 30H ;30H单元中的数加1MOV A, 30H ;30H单元中的数据拷贝给ACJNE A,#20,JIXU ;A中的数据与20比较不相等就跳转到JIXU处MOV 30H,#0 ;(如果30H单元计满20了)给30H赋值0INC SECOND ;把SECOND中的秒钟数加1MOV A,SECOND ;把SECOND中的数据拷贝给ACJNE A, #60, JIXU ;A中的数据与60比较不相等就跳转到JIXU处MOV SECOND, #0 ;给秒SECOND赋值0INC MINUTE ;把MINUTE中的分钟数加1MOV A, MINUTE ;把MINUTE中的数据拷贝给ACJNE A, #60, JIXU ;A中的数据与60比较不相等就跳转到JIXU处MOV MINUTE, #0 ;给分钟MINUTE赋值0INC HOUR ;把HOUR中的小时数据加1MOV A, HOUR ;把HOUR中的数据拷贝给ACJNE A, #24, JIXU ;A中的数据与24比较不相等就跳转到JIXU处MOV HOUR, #0 ;给小时HOUR赋值0JIXU: MOV A,R3 ;把刚才送入R3中的数据还给AMOV TH0,#3CH ;给计数容器的高8位TH0赋初始值3CHMOV TL0,#0B0H ;给计数容器的低8位TL0赋初始值B0HRETI ;中断子程序返回主程序;---------------------------延时子程序----------------------------DELAY:MOV R0, #50 ;给R0赋值50D2:MOV R1, #10 ;给R1赋值10D1:DJNZ R1, D1 ;R1减1不等于0跳到D1处DJNZ R0, D2 ;R0减1不等于0跳到D2处RET ; 延时子程序结束返回调用该程序的下一条;---------------下面的数据表中存储的是显示段码(共阳)-------------------TAB:DB 0C0H,0F9H,0A4H,0B0H,99H ;从TAB处开始存储0、1、2、3、4 DB 92H ,82H ,0F8H,80H ,90H ;5、6、7、8、9对应的显示段码END ;程序结束。
51单片机延时函数
51单片机延时函数是51单片机在实际应用中必不可少的一种函数,它的作用是延迟指令的执行,可以让程序运行的更加精确,因此十分重要。
51单片机延时函数可以用来控制时间、分析数据、检测信号、按指定时间触发特定事件等等。
以实际应用为例,如果使用51单片机实现一个报警装置,延时函数可以用来实现报警时间的控制,以及报警过程间隔时间的控制,从而控制不同报警信号的发出。
51单片机延时函数的实现有很多种,比如空循环实现、定时器实现等。
空循环实现的51单片机延时函数,是通过一个无限循环来实现的,这样就可以让程序在循环中计算循环次数,从而实现对时间的控制。
但是,空循环有其局限性,在51单片机运行的环境越来越复杂的今天,空循环实现的51单片机延时函数的灵敏度越来越低,达不到精确控制时间的需要。
另外,定时器实现的51单片机延时函数,是通过51单片机自带的定时器来实现的,定时器实现的51单片机延时函数能够精确控制时间,而且还可以实现多种复杂的功能,比如定时检测信号、定时触发特定事件等。
51单片机延时函数在实际应用中十分重要,有空循环实现和定时器实现两种实现方法,空循环实现的51单片机延时函数简单易实现,但在复杂环境下灵敏度较低;而定时器实现的51单片机延时函数能够精确控制时间,实现复杂功能,但程序复杂度较高。
所以,在51单片机实际应用中,应根据实际情况选择最佳的实现方法。
单片机89C51精确延时
高手从菜鸟忽略作起之(六)一,晶振与周期:
89C51晶振频率约为12MHZ。
在此基础上,计论几个与单片机相关的周期概念:时钟周期,状态周期,机器周期,指令周期。
晶振12MHZ,表示1US振动12次,此基础上计算各周期长度。
时钟周期(W sz):Wsz=1/12=0.083us
状态周期(W zt) Wzt=2*Wsz=0.167us
机器周期(W jq): Wjq=6*Wzt=1us
指令周期(W zl): W zl=n*Wjq(n=1,2,4)
二,指令周期
汇编指令有单周期指令,双周期指令,四周期指令。
指令时长分别是1US,2US,4US.指令的周期可以查询绘编指令获得,用下面方法进行记忆。
1.四周期指令:MUL,DIV
2.双周期指令:与SP,PC相关(见汇编指令周期表)
3.单周期指令:其他(见汇编指令周期表)
三,单片机时间换算单位
1.1秒(S)=1000毫秒(ms)
2.1毫秒(ms)=1000微秒(us)
3.1微秒(us)=1000纳秒(ns)
单片机指令周期是以微秒(US)为基本单位。
四,单片机延时方式
1.计时器延时方式:用C/T0,C/T1进行延时。
2.指令消耗延时方式:
本篇单片机精确延时主要用第2种方式。
五,纳秒(ns)级延时:
由于单片机指令同期是以微秒(US)为基本单位,因此,纳秒级延时,全部不用写延时。
六,微秒(US)级延时:
1.单级循环模式:delay_us_1
最小值:1+2+2+0+2+1+2+2=12(US),运行此模式最少需12US,因此12US以下,只能在代码中用指定数目的NOP来精确延时。
最大值:256*2+12-2=522(US),256最大循环次数,2是指令周期,12是模式耗时,-2是模式耗时中计1个时钟周期。
延时范围:值域F(X)[12,522],变量取值范围[0,255].
函数关系:Y=F(x):y=2x+12,由输入参数得出延时时间。
反函数:Y=F(x):y=1/2x-6:由延时时间,计算输入参数。
例延时500US,x=500,y=244,即输入244时,精确延时500US.
2.双级循环模式:delay_us_2
最小值:固定值(红色部分)=15us,外循环值(绿及中间)=5US,故最小值为20US.
最大值:固定值(红色部分)=15us,单个内循环256*2=512,外循下的内循环256*512=131072,外循环赋值与转移256*(1+2)=768,最大值为:15+131072+768=131855
延时范围:[20,131855],变量X[0,255],Y[0,255]
函数关系:Z=F(X,Y),Z=15+(Y+1)*[(X+1)*2+3]
双级循环模式延时查询表:可用EXCEL设计公式。
3.其他级循环模式:
可按上述方法,进行分析,从而达到自己所需的精确延时。
计时器延时,不在本章讨论之列。