用单片机实现延时(自己经验及网上搜集).
- 格式:doc
- 大小:21.00 KB
- 文档页数:10
使用KeilC进行51单片机延时程序编写的几点心得使用Keil C进行51单片机延时程序编写的几点心得应用单片机的时候,经常会遇到需要短时间延时的情况。
需要的延时时间很短,一般都是几十到几百微妙(us)。
有时候还需要很高的精度,比如用单片机驱动DS18B20的时候,误差容许的范围在十几us以内,不然很容易出错。
这种情况下,用计时器往往有点小题大做。
而在极端的情况下,计时器甚至已经全部派上了别的用途。
这时就需要我们另想别的办法了。
以前用汇编语言写单片机程序的时候,这个问题还是相对容易解决的。
比如用的是12MHz 晶振的51,打算延时20us,只要用下面的代码,就可以满足一般的需要:mov r0,#09hloop:djnzr0,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--);}。
51 单片机定时器延时1s函数1.引言1.1 概述本文介绍了51单片机中的定时器功能以及如何通过定时器实现延时1秒的函数。
在单片机应用中,定时器是一种非常重要且常用的功能模块之一。
它能够精确计时,并可用于实现周期性的任务触发、计时、脉冲输出等功能。
本文首先将对51单片机进行简要介绍,包括其基本概念、结构和特点。
随后,重点讲解了定时器的基本原理和功能。
定时器通常由一个计数器和一组控制寄存器组成,通过预设计数器的初值和控制寄存器的配置来实现不同的计时功能。
接着,本文详细介绍了如何通过编程实现一个延时1秒的函数。
延时函数是单片机开发中常用的功能,通过定时器的计时功能可以实现精确的延时控制。
本文将以C语言为例,介绍延时函数的编写步骤和原理,并给出示例代码和详细的说明。
最后,本文对所述内容进行了总结,并展望了定时器在单片机应用中的广泛应用前景。
通过学习定时器的相关知识和掌握延时函数的编写方法,我们可以更好地应用定时器功能,提高单片机应用的效率和精确性。
综上所述,通过本文的学习,读者可全面了解51单片机中定时器的功能和应用,并能够掌握延时函数的编写方法,为单片机应用开发提供一定的参考和指导。
1.2 文章结构本文以51单片机定时器功能为主题,旨在介绍如何使用定时器进行延时操作。
文章分为引言、正文和结论三个主要部分。
在引言部分,首先会对文章的背景进行概述,介绍单片机的基本概念和应用领域。
然后,给出本文的整体结构,并阐述文章的目的和意义。
正文部分将分为两个小节。
在2.1节中,将对单片机进行详细介绍,包括其构造与工作原理。
这部分的内容将帮助读者全面了解单片机的基本知识,为后续的定时器功能介绍打下基础。
2.2节将重点介绍定时器的功能和特点。
这部分将涵盖定时器的基本原理、工作模式以及在实际应用中的使用方法。
同时,还将详细讲解如何使用定时器进行1秒钟的延时操作,包括具体的代码实现和注意事项。
结论部分将对全文进行总结,并强调定时器的重要性和应用前景。
让我们来深入探讨一下89C51单片机延迟代码的概念。
单片机是一种集成了微处理器、存储器和输入/输出设备的微型计算机系统,被广泛应用于各种电子设备中。
而89C51单片机是一种由英特尔生产的经典单片机产品,具有稳定可靠、功能丰富等特点。
在实际应用中,由于一些特定的需求,我们常常需要编写延迟代码来实现一些功能或者满足一些特定的需求。
了解89C51单片机延迟代码的实现方法和原理,对于深入理解单片机编程和实际应用是非常重要的。
在89C51单片机中,延迟代码的实现有多种方法,下面我将结合实际经验和专业知识,为您详细介绍几种常见的实现方式,并进行深入解析。
1. 软件延迟:软件延迟是我们在89C51单片机编程中经常使用的一种延迟实现方式。
通过在程序中增加一些空指令或者循环操作,可以实现一定的延迟效果。
在实际应用中,我们可以根据实际需求和单片机的性能来确定循环次数,从而实现精确的延迟时间。
软件延迟的优点是实现简单,适用于各种场景,但缺点是占用了CPU资源,可能影响其他任务的执行效率。
2. 硬件延迟:除了软件延迟外,我们还可以利用89C51单片机的定时器和中断功能来实现硬件延迟。
通过设置定时器的计数值和工作模式,可以精确地控制延迟时间。
可以将延迟代码放入中断服务函数中,从而实现在延迟过程中可以执行其他任务的效果。
硬件延迟的优点是精确可控,不会占用CPU资源,适用于对延迟精度要求较高的场景。
3. 外部设备延迟:在实际应用中,我们还可以利用外部设备(如晶振、定时电路等)来实现延迟功能。
通过控制外部设备的频率和工作模式,可以实现各种精确的延迟时间。
外部设备延迟的优点是可以进一步提升延迟的精度和稳定性,适用于对延迟要求非常严格的场景。
在实际应用中,我们可以根据不同的需求和场景选择合适的延迟实现方式,从而兼顾延迟时间的精确性和系统的执行效率。
我们还可以结合多种延迟实现方式,根据实际情况进行灵活应用,从而更好地满足各种复杂的需求。
引言概述:C51单片机是一种广泛应用于嵌入式系统中的微控制器,它具有高度集成化、易于编程和灵活性强等特点。
在C51单片机的软件开发过程中,延时程序设计是非常重要的一部分。
本文将介绍C51单片机中几种常用的延时程序设计方法,包括循环延时、定时器延时、外部中断延时等。
这些方法不仅可以满足在实际应用中对延时的需求,而且可以提高程序的稳定性和可靠性。
正文内容:一、循环延时1. 使用循环控制语句实现延时功能,例如使用for循环、while循环等。
2. 根据需要设置延时的时间,通过循环次数来控制延时的时长。
3. 循环延时的精度受到指令执行时间的影响,可能存在一定的误差。
4. 循环延时的优点是简单易用,适用于较短的延时时间。
5. 注意在循环延时时要考虑其他任务的处理,避免长时间的等待造成程序卡死或响应延迟。
二、定时器延时1. 使用C51单片机内置的定时器模块来实现延时。
2. 配置定时器的工作模式,如工作方式、定时器精度等。
3. 设置定时器的初值和重装值,控制定时器中断的触发时间。
4. 在定时器中断服务函数中进行延时计数和延时结束标志的设置。
5. 定时器延时的优点是精确可控,适用于需要较高精度的延时要求。
三、外部中断延时1. 在C51单片机上配置一个外部中断引脚。
2. 设置外部中断中断触发条件,如上升沿触发、下降沿触发等。
3. 在外部中断中断服务函数中进行延时计数和延时结束标志的设置。
4. 外部中断延时的优点是能够快速响应外部信号,适用于实时性要求较高的场景。
5. 注意在外部中断延时时要处理好外部中断的抖动问题,确保延时的准确性。
四、内部计时器延时1. 使用C51单片机内部的计时器模块来实现延时。
2. 配置计时器的工作模式,如工作方式、计时器精度等。
3. 设置计时器的初值和重装值,使计时器按照一定的频率进行计数。
4. 根据计时器的计数值进行延时的判断和计数。
5. 内部计时器延时的优点是能够利用单片机内部的硬件资源,提高延时的准确性和稳定性。
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,并设置定时器中断。
在中断服务程序中,我们进行相应的操作来实现精确的延时。
这种方法需要使用到单片机的定时器中断功能,相对复杂一些,但是可以实现精确的延时。
实验一单片机延时程序实验一、实验目的1.掌握汇编语言程序设计的基本流程2.学会使用MPLAB进行开发和调试。
3.掌握在线调试工具的使用方法。
二、实验内容1.用4MHz外部晶体振荡器的PIC16F877A上用软件设计一个20ms的软件延时子程序。
2.用MPLAB的软件模拟器及其附带的软件工具窗口Stopwatch观测延时子程序执行的时间。
3.使用在线调试工具ICD2对所写程序进行调试。
三、软件设计单片机软件延时的前提和基础是每条指令的执行时间是固定的,且大部分指令的执行时间是相同的。
这就要求对于本章介绍的,每条指令所花费的的指令周期做到心中有数。
指令集中5条跳转指令GOTO,CALL、RETURN、RETLW和RETFIE,由于它们必然引起程序跳转,造成流水线中断,因此肯定将占用2个指令周期。
而其他4条有可能引起程序跳转的条件跳转指令DECFSZ、INCFSZ、BTFSC和BTFSS的执行时间随着条件而定。
当条件为真发生跳转时,需要占用2个指令周期,当条件为假不发生跳转时,仅占用1个指令周期。
其余所有指令都只用1个指令周期。
如果延时时间较短(微秒级别),可以连续插入几条NOP指令;如果延时时间较长(几个毫秒级别),可以插入单循环结构的程序;如果时间延时程序很长(10ms以上),则可以使用双嵌套循环的方法来实现。
这次我们要延时20ms,应该采用双嵌套循环的方法来实现。
四、流程图:五、程序代码及测试#INCLUDE "P16F877A.INC"I EQU 20HJ EQU 21HORG 0000HNOPGOTO MAINORG 0010HMAIN BSF STATUS,5CLRF TRISDBCF STATUS,5CLRF PORTDLOOPBSF PCLATH,3CALL DELAYBSF PORTD,0CALL DELAYBCF PORTD,0BCF PCLATH,3GOTO L OOPORG 0810HDELAY MOVLW D'200'MOVWF ILOOP1 MOVLW D'200'MOVWF JLOOP2 DECFSZ J,fGOTO L OOP2DECFSZ I,fGOTO L OOP1RETURNEND我们在程序中设置断点,用Stopwatch来查看程序运行的时间,发现和计算的相差不多。
1t单片机延时1t单片机是一种高性能的微处理器,具有强大的计算和控制能力。
在嵌入式系统中,延时是一项常见的操作。
本文将探讨如何使用1t 单片机实现延时功能。
延时是指在程序中暂停一段时间,让程序按照一定的时间间隔执行。
在实际应用中,延时常常用于控制设备的时间间隔,例如LED灯的闪烁、蜂鸣器的鸣叫、电机的转动等。
在1t单片机中,延时通常使用定时器来实现。
定时器是一种计时装置,可以在程序中设置计时的时间和触发事件。
定时器通常由计数器和控制逻辑组成。
在使用1t单片机实现延时功能时,首先需要初始化定时器。
通过设置定时器的计数器初始值和控制逻辑,可以实现不同的延时时间。
然后,程序进入一个循环,不断检测定时器的计数器是否达到设定的延时时间。
如果达到,程序执行相应的操作,否则继续等待。
在编写程序时,需要考虑延时时间的单位和精度。
1t单片机通常使用时钟频率来表示时间单位,例如1秒对应的时钟周期数。
在设置延时时间时,需要根据具体的时钟频率和所需的延时时间来计算计数器的初始值。
延时功能的实现还需要考虑系统的稳定性和可靠性。
延时时间过长或过短都可能导致系统工作异常。
因此,在编写程序时,需要根据具体的应用场景和硬件环境来选择合适的延时时间。
除了使用定时器实现延时功能,1t单片机还可以通过其他方式实现延时。
例如,可以使用循环语句来实现简单的延时功能。
在循环中执行一定的空操作,达到延时的效果。
然而,这种方式相对于定时器来说,延时时间不够准确,且不适用于需要较长延时时间的应用。
1t单片机是一种强大的微处理器,可以实现丰富的控制功能。
延时是一项常见的操作,在1t单片机中可以通过定时器来实现。
通过合理设置定时器的初始值和控制逻辑,可以实现不同精度的延时功能。
在实际应用中,需要根据具体的需求选择合适的延时方式和时间。
延时功能的实现需要考虑系统的稳定性和可靠性,确保系统正常运行。
51 单片机精确延时程序51 单片机精确延时程序(晶振12MHz,一个机器周期1us.)几个精确延时程序:在精确延时的计算当中,最容易让人忽略的是计算循环外的那部分延时,在对时间要求不高的场合,这部分对程序不会造成影响.一. 500ms 延时子程序程序:.(晶振12MHz,一个机器周期1us.)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--);}void delay1s(void)//12M 晶振,延时999999.00us {unsigned char i,j,k;for(i=46;i>0;i--)for(j=152;j>0;j--)for(k=70;k>0;k--);}扩展阅读:单片机延时问题20 问。
单片机实现延时方法总结实现延时通常有两种方法:一种是硬件延时,要用到定时器/计数器,这种方法可以提高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。
单片机定时器实现1s延迟:
在单片机中,使用定时器实现1秒延迟通常需要以下步骤:
1.设置定时器模式:首先,你需要设置单片机的定时器模式。
这通常涉及到选择定时
器的工作方式(例如,模式1、模式2等),并设置适当的预分频值。
预分频值决定了定时器溢出时的时间间隔。
2.计算定时器初值:接下来,你需要计算定时器的初始值。
定时器的初始值是定时器
计数到溢出时所用的时间长度。
要实现1秒延迟,你需要知道单片机的工作频率以及你选择的定时器模式和预分频值。
3.启动定时器:设置好定时器模式和初始值后,你可以启动定时器。
一旦定时器开始
计数,它会不断增加,直到达到设定的初始值。
4.检测定时器溢出:当定时器计数到初始值并溢出时,你可以检测这个事件。
一旦检
测到溢出,你可以执行相应的操作,例如触发一个中断或执行一个函数。
5.重置定时器:在执行完溢出的操作后,你需要重置定时器以开始下一个计时周期。
单片机延时方法总结
实现延时通常有两种方法:一种是硬件延时,要用到定时器/计数器,这种方法可以提高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 软件延时与时间计算。
51单片机精确延时程序大集合51单片机精确延时程序大集合以下程序说是精确延时,实际上都不对。
调用一次差个几微秒、几百微秒,一天下来差好几分钟。
加我的QQ群有精确版本哦,不同频率的晶振都适用。
群:383977592008-04-24 12:10:26,在论坛上看到不少不错的延时程序,整理如下共同分享:精确延时计算公式:延时时间=[(2*第一层循环+3)*第二层循环+3]*第三层循环+5;延时5秒左右DELAY5S:PUSH 04H;2个机器周期PUSH 05H;2个机器周期PUSH 06H;2个机器周期MOV R4,#50;1个机器周期DELAY5S_0:MOV R5,#200;1个机器周期DELAY5S_1:MOV R6,#245;1个机器周期DJNZ R6,$;2×245=490个机器周期DJNZ R5,DELAY5S_1;这条2个机器周期,这层循环包含R5×(490+1)+2×R5=98600个机器周期DJNZ R4,DELAY5S_0;这条2个机器周期,这层循环包含R4×(98600+1)+2×R4=4930150个机器周期POP 06H;2个机器周期POP 05H;2个机器周期POP 04H;2个机器周期RET;2个机器周期;(共2+2+2+1+4930150+2+2+2+2=4930165个机器周期);513微秒延时程序DELAY: MOV R2,#0FEH;1个机器周期JUZINAIYOU: DJNZ R2,JUZINAIYOU;2×R21即2×245RET;2个机器周期;(实际上是493个机器周期);10毫秒延时程序DL10MS: MOV R3,#14HDL10MS1:LCALL DELAYDJNZ R3,DL10MS1RET;(缺DELAY);0.1s延时程序12MHzDELAY: MOV R6,#250DL1: MOV R7,#200DL2: DJNZ R6,DL2DJNZ R7,DL1RET;延时1046549微秒(12MHz);具体的计算公式是:;((((r7*2+1)+2)*r6+1)+2)*r5+1+4 = ((r7*2+3)*r6+3)*r5+5 DEL : MOV R5,#08HDEL1: MOV R6,#0FFHDEL2: MOV R7,#0FFHDJNZ R7,$DJNZ R6,DEL2DJNZ R5,DEL1RET;1秒延时子程序是以12MHz晶振DELAY:MOV R1,#50del0: mov r2,#91del1: mov r3,#100djnz r3,$djnz r2,del1djnz r1,del0Ret;1秒延时子程序是以12MHz晶振为例算指令周期耗时KK: MOV R5,#10 ;1指令周期×1K1: MOV R6,#0FFH ;1指令周期×10K2: MOV R7,#80H ;1指令周期256×10=2560K3: NOP ;1指令周期;128*256*10=327680DJNZ R7,K3 ;2指令周期2*128*256*10=655360DJNZ R6,K2 ;2指令周期2*256*10=5120DJNZ R5,K1 ;2指令周期2*10=20RET;2指令周期;21+10+2560+327680+655360+5120+20+2=990753 ;约等于1秒=1000000微秒;这个算下来也只有0.998抄T_0: MOV R7,#10;D1: MOV R6,#200;D2: MOV R5,#248;DJNZ R5,$DJNZ R6,D2;DJNZ R7,D1;RET;这样算下来应该是1.000011秒T_0: MOV R7,#10;D1: MOV R6,#200;D2: NOPMOV R5,#248;DJNZ R5,$DJNZ R6,D2;DJNZ R7,D1;RETDELAY_2S: ;10MS(11.0592mhz) MOV R3,#200JMP DELAY10MSDELAY_100MS: ;100MS(11.0592mhz) MOV R3,#10JMP DELAY10MSDELAY_10MS:MOV R3,#1DELAY10MS: ;去抖动10MS(11.0592mhz)MOV R4,#20DELAY10MSA:MOV R5,#247DJNZ R5,$DJNZ R4,DELAY10MSADJNZ R3,DELAY10MSRETDELAY_500MS: ;500MSMOV R2,#208JMP DELAY_MSDELAY_175MS: ;175MSMOV R2,#73JMP DELAY_MSdelaY_120MS: ;120MSMOV R2,#50JMP DELAY_MSdelay_60ms: ;60msMOV R2,#25JMP DELAY_MSdelay_30ms: ;30msMOV R2,#12JMP DELAY_MSDELAY_5MS: ;5MSMOV R2,#2;=================================== DELAY_MS:CALL DELAY2400DJNZ R2,DELAY_MSRET;=================================== DELAY2400: ;10x244+4=2447 /1.024=2390 MOV R0,#244 ;1 DELAY24001:MUL AB ;4MUL AB ;4DJNZ R0,DELAY24001 ;2RETDELAY: ;延时子程序(1秒)MOV R0,#0AHDELAY1: MOV R1,#00HJUZINAIYOU: MOV R2,#0B2HDJNZ R2,$DJNZ R1,JUZINAIYOUDJNZ R0,DELAY1RETMOV R2,#10 ;延时1秒LCALL DELAYMOV R2,#50 ;延时5秒LCALL DELAYDELAY: ;延时子程序PUSH R2PUSH R1PUSH R0DELAY1: MOV R1,#00HJUZINAIYOU: MOV R0,#0B2HDJNZ R0,$DJNZ R1,JUZINAIYOU ;延时 100 mSDJNZ R2,DELAY1POP R0POP R1POP R2RET1:DEL: MOV R7, #200DEL1: MOV R6, #123NOPDEL2: DJNZ R6, DEL2DJNZ R7, DEL1RET是50.001ms 算法是:0.001ms+200*0.001ms+200*0.001ms+200*123*0.002ms+2 00*0.002ms ;(123*2+4)*200+12: DEL: MOV R7, #200 DEL1: MOV R6, #123 DEL2:NOPDJNZ R6,DEL2DJNZ R7,DEL1RETD500MS:PUSH PSWSETB RS0MOV R7,#200D51: MOV R6,#250D52: NOPNOPNOPNOPDJNZ R6,D52DJNZ R7,D51POP PSWRETDELAY: ;延时1毫秒PUSH PSW SETB RS0MOV R7,#50D1: MOV R6,#10D2: DJNZ R6,$DJNZ R7,D1POP PSWRETORG 0LJMP MAINORG 000BHLJMP CTC0MAIN: MOV SP, #50HCLR EAMOV TMOD, #01HMOV TH0,#3CHMOV TL0,#0B0HMOV R4, #10SETB ET0SETB EASETB TR0SJMP $ ;CTC0: MOV TH0, #3CHMOV TL0, #0B0HDJNZ R4, LPCPL P1.0MOV R4, #10LP: RETIEND; 定时器中断延时TMOD=0x01; /*定时器0工作在模式1下(16位计数器)*/TH0=0xfd;TL0=0x83;TR0=1; /*启动定时器*/TF0==0;TR0=0;等待中断;100ms定时,11.0592晶振他定时准确啊又不影响程序运行2008-06-10 13:50:46 来源:来于网络,服务大家作者:未知【大中小】点击:9 次下面几个是单片机的延时程序(包括asm和C程序,都是我在学单片机的过程中用到的),在单片机延时程序中应考虑所使用的晶振的频率,在51系列的单片机中我们常用的是11.0592MHz和12.0000MHz的晶振,而在AVR单片机上常用的有8.000MHz和4.000MH的晶振所以在网上查找程序时如果涉及到精确延时则应该注意晶振的频率是多大。
单片机延时计算
在单片机编程中,延时是一种常用的控制方法。
延时的基本原理是利用单片机内部的计时器来实现时间的计算。
以下是一个简单的延时计算程序的中文代码:
1. 定义延时时间
首先需要定义需要延时的时间,例如下面的代码定义了一个需要延时10毫秒的时间:
unsigned int delay_time = 10;
2. 计算延时时间
接下来需要编写延时计算的函数,在这个函数中需要使用单片机内部的计时器来实现时间的计算。
以51单片机为例,我们可以使用定时器和定时器中断来实现延时计算。
具体代码如下:
void delay(unsigned int time) // time为需要延时的时间(单位:毫秒)
{
unsigned char i, j;
while (time--)
{
i = 10;
j = 120;
do
{
while (--j);
} while (--i);
}
}
3. 调用延时函数
最后,在需要进行延时的地方调用延时函数即可,例如下面的代
码在执行delay函数后会延时10毫秒:
delay(delay_time);
以上就是一个简单的中文延时计算程序,希望能对你有所帮助。
标准的C语言中没有空语句。
但在单片机的C语言编程中,经常需要用几个空指令产生短延时的效果。
这在汇编语言中很容易实现,写几个nop就行了。
在keil C51中,直接调用库函数:#include<intrins.h> // 声明了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,#0FFHLOOP: 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结构来完成,每个循环体内的变量仍然采用无符号字符变量。
单片机写延时程序的几种方法1)空操作延時 (12MHz)void delay10us(){_NOP_();_NOP_();_NOP_();_NOP_();_NOP_();_NOP_();}2)循環延時 (12MHz)Void delay500ms(){unsigned char i,j,k;for(i=15;i>0;i--)for(j=202;j>0;j--)for(k=81;k>0;k--);}延時總時間=[(k*2+3)*j+3]*i+5k*2+3=165 us165*j+3=33333 us33333*i+5=500000 us=500 ms3)計時器中斷延時(工作方式2) (12MHz)#include<reg52.h>sbit led=P1^0;unsigned int num=0; void main(){TMOD=0x02;TH0=6;TL0=6;EA=1;ET0=1;TR0=1;while(1){if(num==4000){num=0;led=~led;}}}void T0_time() interrupt 1 {num++;}4)C程序嵌入組合語言延時#pragma asm……組合語言程序段……#pragma endasmKEIL軟件仿真測量延時程序延時時間這是前段事件總結之延時程序、由於不懂組合語言,故NO.4無程序。
希望對你有幫助對於12MHz晶振,機器周期為1uS,在執行該for循環延時程式的時候Void delay500ms(){unsigned char i,j,k;for(i=15;i>0;i--)for(j=202;j>0;j--)for(k=81;k>0;k--);}賦值需要1個機器周期,跳轉需要2個機器周期,執行一次for循環的空操作需要2個機器周期,那么,對於第三階循環for(k=81;k>0;k--);,從第二階跳轉到第三階需要2機器周期,賦值需要1個機器周期,執行81次則需要2*81個機器周期,執行一次二階for循環的事件為81*2+1+2;執行了220次,則(81*2+3)*220+3,執行15次一階循環,則[(81*2+3)*220+3]*15,由於不需要從上階跳往下階,則只加賦值的一個機器周期,另外進入該延時子函數和跳出該函數均需要2個機器周期,故還需要+5。
单片机的延时与中断问题及解决方法一、延时问题在单片机编程中, 经常需要生成一定延时时间, 延时一般实现方式有两种, 一种是软件延时, 另一种是硬件延时。
1. 软件延时软件延时是逐个扫描处理器的时钟脉冲, 每一个时钟周期执行一次循环程序, 每次循环的时间固定。
通过循环次数的控制, 达到延时的目的。
在软件延时期间,程序是被占用的,故需要考虑延时时间尽量短,同时不影响程序的执行。
实现代码:void delay(unsigned int x) //延时函数,x表示延时时间{unsigned int i,j;for(i=0;i<x;i++)for(j=0;j<1000;j++); //短跑}下面的例子是让板载LED在开启1秒、关闭1秒间缓慢闪烁,延时采用软件延时的方式:硬件延迟又称为定时器延迟, 定时器是一个独立的片内设备, 可以独立于CPU运行,定时器的时间不受程序的执行速度和被调用函数的影响, 它运行在一个专用的时钟上面,它具有高可靠性和高精度的特点。
单片机的周期性和准确性都是要靠定时器来完成的。
同时这种方法不影响CPU的其他操作,具有很好的实时性。
二、中断问题中断是单片机的一种重要功能,它可以让CPU在执行某个任务的同时立即执行另一个任务,这种即时响应的能力是单片机的一个最大优点,常常用来响应实时性较高的任务。
微控制器具有中断请求和响应功能的芯片,中断处理器独立于当前CPU的执行,即产生中断时CPU停止执行当前指令,转而执行中断程序处的指令,用完后从停止的地方继续执行当前程序。
根据取决于它们发生的原因,中断可以分为两类:内部中断和外部中断。
中断的优点:相对于软件循环,中断方式的优势主要体现在:实现简单,处理时间短,对CPU的干扰小,实现实时性强。
中断的缺点:1. 中断需要单片机芯片本身支持,若不支持,需通过其他芯片辅助实现。
2. 硬件结构较为复杂,且比较占用IO口。
3. 中断只有在硬件支持的情况下才能使用,所以其可移植性不强。
用单片机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,$;。
实验一:单片机延时程序实验一、实验目的与要求:由于发光管亮灭变化频率为4Mhz,无法观察到LED0的闪烁,而是以较低的亮度保持LED0常亮,要求加入延时子程序能够看到LED0的闪烁。
二、实验内容:1.硬件电路设计:PIC单片机的绝大部分引脚作为输出I/O端口时,能够提供25mA的电流,因此,本实验直接用PORTD的8个I/O端口驱动连接了限流电阻的发光二极管即可。
为了TMR0定时计算方便,采用4MHz的外部晶体振荡器作为单片机的系统时钟,这样未经过预分频的TMR0内部计数时钟周期,就是指令周期1微秒。
2.软件设计思路:①将小试牛刀出的实验运行得到结果代码如下:#INCLUDE "P16F877A.INC";ORG 0000H;NOP;BSF STATUS,5;CLRF TRISDBCF STATUS,5;CLRF PORTD;LOOPBCF PORTD,0;BSF PORTD,0;GOTO LOOP;END②加入延时子程序后继续调试得到结果代码如下:#include P16F877A.inci EQU 20H ;定义寄存器ij EQU 21H ;定义寄存器jORG 0000H;NOP;BSF STATUS,5;CLRF TRISDBCF STATUS,5;CLRF PORTD;LOOPBCF PORTD,0;CALL DELAYBSF PORTD,0;CALL DELAYGOTO LOOP;DELAYMOVLW D'131' ;设置外部循环次数MOVWF i ;LOOP1MOVLW D'50' ;设置内部循环次数MOVWF j ;LOOP2DECFSZ j ,f ;内部循环变量自减1,GOTO LOOP2 ;为0则跳转DECFSZ i,f ;外部循环变量自减1,GOTO LOOP1 ;为0则跳转RETURN ;返回主程序END三、实验步骤及结果:①将小试牛刀实验在MPLAB IDE v8.8的软件中编译成功;②配置单片机的基本工作方式,由于PIC16F877A振荡器为4MHz,所以把处理器频率设置为4MHz;③完成configure菜单下的configure bits菜单项,逐一设置窗口中提供的单片机配置④连接ICD3和实验套件相连,将ICD3和PC机用USB电缆线连接。
标准的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,#0FFHLOOP: 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,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--;}这三种方法都是用DJNZ指令嵌套实现循环的,由C51编译器用下面的指令组合来完成的MOV R7,#0FFHLOOP2: MOV R6,#0FFHLOOP1: DJNZ R6,LOOP1DJNZ R7,LOOP2这些指令的组合在汇编语言中采用DJNZ指令来做延时用,因此它的时间精确计算也是很简单,假上面变量i的初值为m,变量j的初值为n,则总延时时间为:m×(n×T+T),其中T为DJNZ指令执行时间(DJNZ指令为双周期指令)。
这里的+T为MOV这条指令所使用的时间。
同样对于更长时间的延时,可以采用多重循环来完成。
只要在程序设计循环语句时注意以上几个问题。
下面给出有关在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,05HMOV R4,03HC0012: DJNZ R3, C0012MOV R3,04HDJNZ R5, C0012MOV R5,06HDJNZ R7, C0012RET假设参数变量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延时函数可设置入口参数,可将参数定义为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 。
在程序中加入这一循环结构,首先选择 build taget ,然后单击 start/stop debug session 按钮进入程序调试窗口,最后打开 Disassembly window ,找出与这部分循环结构相对应的汇编代码,具体如下:C:0x000FE4CLRA//1TC:0x0010FEMOVR6,A//1TC:0x0011EEMOVA,R6//1TC:0x0012C3CLRC//1TC:0x00139FSUBBA,DlyT //1TC:0x00145003JNCC:0019//2TC:0x00160E INCR6//1TC:0x001780F8SJMPC:0011//2T可以看出, 0x000F ~ 0x0017 一共 8 条语句,分析语句可以发现并不是每条语句都执行DlyT 次。