单片机延时子程序
单片机延时500ms程序汇编
单片机延时500ms程序汇编一、概述在单片机编程中,延时操作是非常常见且重要的一部分。
延时可以使程序在执行过程中暂停一段时间,以确保输入输出设备能够正常工作,或者是为了保护其他设备。
本文将介绍如何使用汇编语言编写单片机延时500ms的程序。
二、延时原理在单片机中,延时操作通常通过循环来实现。
每个循环需要一定的时间,通过控制循环次数和循环体内的指令数量,可以实现不同长度的延时。
在汇编语言中,可以使用计数器来控制循环次数,从而实现精确的延时操作。
三、汇编语言编写延时程序接下来,我们将使用汇编语言编写延时500ms的程序。
1. 设置计数器初值在程序的开头我们需要设置计数器的初值,这个初值需要根据单片机的工作频率和所需的延时时间来计算。
假设单片机的工作频率为1MHz,那么在循环500次后,就能够达到500ms的延时。
我们需要将计数器的初值设为500。
2. 循环计数接下来,我们进入一个循环,在循环中进行计数操作。
每次循环结束时,都需要检查计数器的值,当计数器减至0时,表示已经达到了500ms的延时时间,可以退出循环。
3. 优化程序为了提高程序的执行效率,可以对计数器进行优化。
例如可以通过嵌套循环的方式,减少循环的次数,从而提高延时的精度和稳定性。
四、程序示例下面是一个简单的示例程序,演示了如何使用汇编语言编写延时500ms的程序。
```org 0x00mov r2, #500 ; 设置计数器初值为500delay_loop:djnz r2, delay_loop ; 进行计数ret ; 延时结束,退出程序```五、结语通过以上的示例程序,我们可以看到如何使用汇编语言编写单片机延时500ms的程序。
当然,实际的延时程序可能会更加复杂,需要根据具体的单片机型号和工作频率进行调整,但是思路是相似的。
在实际的编程中,需要根据具体的需求和硬件环境来进行调整和优化,以实现更加稳定和精确的延时操作。
希望本文对单片机延时程序的编写有所帮助,也欢迎大家在评论区提出宝贵意见和建议。
单片机中延时算法和nop函数的使用
成,每个循环体内的变量仍然采用无符号字符变量。
unsigned char i,j
for(i=255;i>0;i--)
for(j=255;j>0;j--);
或
unsigned char i,j
i=255;
采用软件定时的计算方法
利用指令执行周期设定,以下为一段延时程序:
指令 周期
MOV 1
DJNZ 2
NOP 1
采用循环方式定时,有程序:
MOV R5,#TIME2 ;周期1
......
......
//============
......
......
_nop_(); //引用库函数
敬礼。
我一直都是借助仿真软件编。一点一点试时间。
C语言最大的缺点就是实时性差,我在网上到看了一些关于延时的讨论,其中有篇文章
51单片机 Keil C 延时程序的简单研究,作者:InfiniteSpace Studio/isjfk
}
产生的汇编
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
NOP指令为单周期指令,可由晶振频率算出延时时间,对于12M晶振,延时1uS。
对于延时比较长的,要求在大于10us,采用C51中的循环语句来实现。
在选择C51中循环语句时,要注意以下几个问题
第一、定义的C51中循环变量,尽量采用无符号字符型变量。
单片机延时程序
实验一单片机延时程序实验一、实验目的与要求:在使用4MH在外部晶体振荡器的PIC16F877A上用软件设计一个20ms的软件延时子程序。
另外,还要求用MPLAB的软件模拟器及其附带的软件工具窗口stopwatch观测延时程序执行的时间。
二、实验内容:1.硬件电路设计:本实验中用的是软件延时,利用循环来实现延时功能。
电路就用了单片机的原本电路。
没有用到其他的功能模块,单片机与ICD3相连接。
2.软件设计思路:单片机软件延时的前提和根底是每条指令的执行时间是固定的,且大局部指令的执行时间是一样的。
这要求对每条指令所花费的指令周期〔Tcy〕做到心中有数。
指令集中5条无条件跳转指令GOTO,CALL.RETURN,RETLW和RETFIE,由于它们必然引起程序跳转,造成流水线中断,因此肯定将占用2个指令周期。
而其他4条有可能引起程序跳转的条件跳转指令DECFSZ,INCFSZ,BTFSC和,BTFSS的执行时间,需要占用2个指令周期,当条件为假不发生跳转时,仅占用1个指令周期。
其余所有指令都只用1个指令周期。
每个指令周期Tcy的时间长度,计算方法:如果采用4MHz 的外部晶体〔fosc=4 MHz〕,那么PIC中档单片机的指令周期Tcy为1us,这是一个整数。
而采用其他频率的外部晶体时,指令周期时间将反比于外部晶体频率。
至于软件延时的构造和实现方法,其实可以采用任何指令和构造,因为只是通过执行指令消耗时间。
但通常情况下有两个选择延时程序构造的原那么:(1)执行指令周期数计算方便。
如果含有太多复杂的条件跳转循环等构造势必会造成指令周期的计算困难,甚至可能造成执行所造成的软件延时时间不等。
(2)不能占用太多的程序空间。
试想用20000个NOP指令来实现20ms的延时,显然是可以的,但是这样做浪费了整整一个页的程序存储器,得不偿失,而通过适当的循环构造,重复执行某些一样的程序是比拟合理的方法。
因此,软件延时程序一般采用以下方法:如果延时时间短〔微妙级别〕,可以连续插入几条NOP指令;如果延时时间长〔几个毫秒级别〕,那么可以使用双嵌套循环的方法来实现。
单片机常用子程序
// P3.4~P3.7,第1~4行
// 0 1 2 3
// 4 5 6 7
// 8 9 10 11
// 12 13 14 15
//****************************************************
void delay(unsigned int t)
while(P3!=0xf0);//等待按键弹出
//beep();
return(key);
}
void main()
{
while(1)
{
unsigned char key;
key=ScanKey44();
switch(key)
{
case 0x11:key=0; break; //0
case 0x24:key=6; break; //6
case 0x28:key=7; break; //7
case 0x41:key=8; break; //8
case 0x42:key=9; break; //9
case 0x44:key=10; break; //10
key=P3&0x3c;
while((P3&0x3c)!=0x3c); //等待弹出
//beep();
return(key);
}
#define S1 0x0e
#define S2 0x0d
#define S3 0x0b
#define S4 0x07
//4个简单按键扫描子程序
case 0x12:key=1; break; //1
单片机C51延时时间怎样计算
C程序中可使用不同类型的变量来进行延时设计。
经实验测试,使用unsi gned char类型具有比un signe d int更优化的代码,在使用时应该使用unsi gned char作为延时变量。
以某晶振为12MHz的单片机为例,晶振为12MH z即一个机器周期为1us。
一. 500ms延时子程序程序:void delay500ms(void){unsign ed 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 = 162usDJNZ 2us二层循环m:R6*(n+3) = 202*165 = 33330u s 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){unsign ed 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){unsign ed 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){unsign ed 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--);}参考链接:http://www.picav/news/2010-04/2106.htm摘要实际的单片机应用系统开发过程中,由于程序功能的需要,经常编写各种延时程序,延时时间从数微秒到数秒不等,对于许多C51开发者特别是初学者编制非常精确的延时程序有一定难度。
51单片机延时程序
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 delay(uint t)
{
for (;t>0;t--);
}
1ms延时子程序(12MHZ)
void delay1ms(uint p)//12mhz
{ uchar i,j;
for(i=0;i<p;i++)
{
for(j=0;j<124;j++)
{;}
在实际应用中,定时常采用中断方式,如进行适当的循环可实现几秒甚至更长时间的延时。使用定时器/计数器延时从程序的执行效率和稳定性两方面考虑都是最佳的方案。但应该注意,C51编写的中断服务程序编译后会自动加上PUSH ACC、PUSH PSW、POP PSW和POP ACC语句,执行时占用了4个机器周期;如程序中还有计数值加1语句,则又会占用1个机器周期。这些语句所消耗的时间在计算定时初值时要考虑进去,从初值中减去以达到最小误差的目的。
}
void Delay10us( ) //12mhz
{
_NOP_( );
_NOP_( );
_NOP_( );
_NOP_( );
_NOP_( );
_NOP_( );
}
/*****************11us延时函数*************************/
汇编延时程序讲解
延时程序在单片机编程中使用非常广泛,但一些读者在学习中不知道延时程序怎么编程,不知道机器周期和指令周期的区别,不知道延时程序指令的用法, ,本文就此问题从延时程序的基本概念、机器周期和指令周期的区别和联系、相关指令的用法等用图解法的形式详尽的回答读者我们知道程序设计是单片机开发最重要的工作,而程序在执行过程中常常需要完成延时的功能。
例如在交通灯的控制程序中,需要控制红灯亮的时间持续30秒,就可以通过延时程序来完成。
延时程序是如何实现的呢?下面让我们先来了解一些相关的概念。
一、机器周期和指令周期1.机器周期是指单片机完成一个基本操作所花费的时间,一般使用微秒来计量单片机的运行速度,51 单片机的一个机器周期包括12 个时钟振荡周期,也就是说如果51 单片机采用12MHz 晶振,那么执行一个机器周期就只需要1μs;如果采用的是6MHz 的晶振,那么执行一个机器周期就需要2 μs。
2 .指令周期是指单片机执行一条指令所需要的时间,一般利用单片机的机器周期来计量指令周期。
在51 单片机里有单周期指令(执行这条指令只需一个机器周期),双周期指令(执行这条指令只需要两个机器周期),四周期指令(执行这条指令需要四个机器周期)。
除了乘、除两条指令是四周期指令,其余均为单周期或双周期指令。
也就是说,如果51 单片机采用的是12MHz 晶振,那么它执行一条指令一般只需1~2 微秒的时间;如果采用的是6MH 晶振,执行一条指令一般就需2~4 微秒的时间。
现在的单片机有很多种型号,但在每个型号的单片机器件手册中都会详细说明执行各种指令所需的机器周期,了解以上概念后,那么可以依据单片机器件手册中的指令执行周期和单片机所用晶振频率来完成需要精确延时时间的延时程序。
二、延时指令在单片机编程里面并没有真正的延时指令,从上面的概念中我们知道单片机每执行一条指令都需要一定的时间,所以要达到延时的效果,只须让单片机不断地执行没有具体实际意义的指令,从而达到了延时的效果。
单片机课程实验报告-延时子程序
单片机实验报告实验报告单片机实验报告一、实验目的:学习P1口的使用方法,学习延时子程序的编写二、实验要求:以P1口作为输出口,控制6个发光二极管,模拟交通信号灯的管理。
在实验仪上选择两组红、黄、绿指示灯,代表交通信号灯。
设有一个十字路口为东西南北方向,其中东西方向为支路,南北方向为主路。
初始状态为4个路口的红灯全亮。
之后,南北路口的绿灯亮,东西路口的红灯亮。
南北路口方向通车,延时20秒后,南北路口绿灯熄灭,黄灯开始闪烁,闪烁5次后红灯亮。
而同时东西方向路口的绿灯亮,东西方向开始通车,延时10秒后,东西路口的绿灯熄灭,而黄灯开始闪烁。
闪烁5次后,在切换到南北路口的绿灯亮,东西路口的红灯亮。
之后重复上述过程。
三、实验电路:四、程序框图:五、程序清单:ORG 4000H ;定义程序存放区域的起始地址START: CLR P1.0 ;红灯亮LOOP: SETB P1.1SETB P1.2CLR P1.5SETB P1.6SETB P1.7ACALL DELAYSSETB P1.0 ;南北绿灯亮,东西红灯亮CLR P1.2ACALL DELAYL2 ;长延时20sMOV R3,#5 ;南北黄灯闪烁5次,东西红灯亮YELLOW1: ;南北黄灯亮,东西红灯亮CLR P1.1SETB P1.2ACALL DELAYS ;短延时;南北黄灯灭,东西红灯亮SETB P1.1ACALL DELAYS ;短延时DJNZ R3,YELLOW1;南北红灯亮,东西绿灯亮CLR P1.0SETB P1.5CLR P1.7ACALL DELAYL1 ;长延时10sMOV R3,#5 ;南北红灯亮,东西黄灯闪烁五次YELLOW2:CLR P1.6 ;东西黄灯亮SETB P1.7ACALL DELAYS ;短延时SETB P1.6 ;南北红灯灭,东西黄灯亮ACALL DELAYS ;短延时DJNZ R3,YELLOW2AJMP LOOP ;循环DELAYL2:MOV R4,#200 ;长延迟20sDELAY1: MOV R5,#200DELAY2: MOV R6,#250DELAY3: DJNZ R6,DELAY3DJNZ R5,DELAY2DJNZ R4,DELAY1RETDELAYS: MOV R4,#10 ;短延迟1sDELAY4: MOV R5,#200DELAY5: MOV R6,#250DELAY6: DJNZ R6,DELAY6DJNZ R5,DELAY5DJNZ R4,DELAY4RETDELAYL1:MOV R4,#100 ;长延迟10sDELAY7: MOV R5,#200DELAY8: MOV R6,#250DELAY9: DJNZ R6,DELAY9DJNZ R5,DELAY8DJNZ R4,DELAY7六、LST文件A51 MACRO ASSEMBLER LED04/21/2010 16:50:30 PAGE 1MACRO ASSEMBLER A51 V7.01OBJECT MODULE PLACED IN LED.OBJASSEMBLER INVOKED BY: C:\Keil\C51\BIN\A51.EXE LED.asm SET(SMALL) DEBUG EPLOC OBJ LINE SOURCE0000 1 ORG 0000H230000 7590DE 4 START: MOV P1,#11011110B0003 1155 5 CALL DALY1 ;0.5S0005 7590DB 6 MOV P1,#11011011B0008 1133 7 CALL DALY ;20S000A 7805 8 MOV R0,#5H000C 74DD 9 LOOP1: MOV A,#11011101B000E F590 10 MOV P1,A0010 1155 11 CALL DALY1 ;0.-5S0012 74DF 12 MOV A,#11011111B0014 F590 13 MOV P1,A0016 1155 14 CALL DALY10018 D8F2 15 DJNZ R0,LOOP1001A 747E 16 MOV A,#01111110B001C F590 17 MOV P1,A001E 1144 18 CALL DALY2 ;10S0020 7805 19 MOV R0,#5H0022 74BE 20 LOOP2: MOV A,#10111110B0024 F590 21 MOV P1,A0026 1155 22 CALL DALY10028 74FE 23 MOV A,#11111110B002A F590 24 MOV P1,A002C 1155 25 CALL DALY1002E D8F2 26 DJNZ R0,LOOP20030 020000 27 LJMP START2829 ;20S0033 7C64 30 DALY:MOV R4,#1000035 7B64 31 DELAY1:MOV R3,#1000037 7A14 32 DELAY2:MOV R2,#200039 792D 33 DELAY3:MOV R1,#45003B D9FE 34 DELAY4:DJNZ R1,DELAY4003D DAFA 35 DJNZ R2,DELAY3003F DBF6 36 DJNZ R3,DELAY20041 DCF2 37 DJNZ R4,DELAY10043 22 38 RET3940 ;10S0044 7C64 41 DALY2:MOV R4,#1000046 7B64 42 DEAY1:MOV R3,#1000048 7A0A 43 DEAY2:MOV R2,#10004A 792D 44 DEAY3:MOV R1,#45004C D9FE 45 DEAY4:DJNZ R1,DEAY4004E DAFA 46 DJNZ R2,DEAY30050 DBF6 47 DJNZ R3,DEAY20052 DCF2 48 DJNZ R4,DEAY10054 22 49 RET5051 ;0.5S0055 7C64 52 DALY1:MOV R4,#1000057 7B64 53 DEY1:MOV R3,#1000059 7A19 54 DEY2:MOV R2,#25005B DAFE 55 DEY3: DJNZ R2,DEY3005D DBFA 56 DJNZ R3,DEY2005F DCF6 57 DJNZ R4,DEY10061 22 58 RETA51 MACRO ASSEMBLER LED 04/22/2010 16:20:30 PAGE 25960 ENDA51 MACRO ASSEMBLER LED 04/21/2010 16:50:30 PAGE 3SYMBOL TABLE LISTING------ ----- -------N A M E T Y P E V A L U E ATTRIBUTESDALY . . . . . . . C ADDR 0033H ADALY1. . . . . . . C ADDR 0055H ADALY2. . . . . . . C ADDR 0044H ADEAY1. . . . . . . C ADDR 0046H ADEAY2. . . . . . . C ADDR 0048H ADEAY3. . . . . . . C ADDR 004AH ADEAY4. . . . . . . C ADDR 004CH ADELAY1 . . . . . . C ADDR 0035H ADELAY2 . . . . . . C ADDR 0037H ADELAY3 . . . . . . C ADDR 0039H ADELAY4 . . . . . . C ADDR 003BH ADEY1 . . . . . . . C ADDR 0057H ADEY2 . . . . . . . C ADDR 0059H ADEY3 . . . . . . . C ADDR 005BH ALOOP1. . . . . . . C ADDR 000CH ALOOP2. . . . . . . C ADDR 0022H AP1 . . . . . . . . D ADDR 0090H ASTART. . . . . . . C ADDR 0000H AREGISTER BANK(S) USED: 0ASSEMBLY COMPLETE. 0 WARNING(S), 0 ERROR(S) 七、实验步骤:(1)根据书中设计流程图编写源程序(见实验程序)(2)用keil软件仿真:(3)更改参数:(4)下载:1.正确连接实验仪与主机的RS-232通信电缆和电源2.把实验仪的工作模式选择开关切换到LOAD处,复位系统使实验仪工作于下载状态3.运行DPFlash下载软件4.把实验仪的工作模式选择开关切换到RUN处,复位系统使实验仪工作观察发光二极管的运行情况。
51单片机延时函数
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 DJNZ2us + 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延时子程序程序:{unsigned char i,j,k;for(i=5;i>0;i--)for(j=132;j>0;j --)for(k=150;k>0;k --);}三. 10ms延时子程序程序:{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语言的精确延时,网上很多都是大约给出延时值没有准确那值是多少,也就没有达到精确高的要求,而本函数克服了以上缺点,能够精确计数出要延时值且精确达到1us,本举例所用CPU为STC12C5412系列12倍速的单片机,只要修改一下参数值其它系例单片机也通用,适用范围宽。
单片机延时程序
要想随心所欲地编写自己需要的延时程序,你首先必须了解延时程序每行代码的运行次数,再结合具体单片机的机器周期来计算。
比如,传统的MSC-51系列单片机(如89S51、89C2051等),如果晶体为12MHz,那么机器周期为1uS-------------------------------------------程序分析例1 50ms 延时子程序:DEL:MOV R7,#200 ①DEL1:MOV R6,#125 ②DEL2:DJNZ R6,DEL2 ③DJNZ R7,DEL1 ④RET ⑤精确延时时间为:1+(1*200)+(2*125*200)+(2*200)+2=(2*125+3)*200+3 ⑥=50603µs≈50ms由⑥整理出公式(只限上述写法)延时时间=(2*内循环+3)*外循环+3 ⑦详解:DEL这个子程序共有五条指令,现在分别就每一条指令被执行的次数和所耗时间进行分析。
第一句:MOV R7,#200 在整个子程序中只被执行一次,且为单周期指令,所以耗时1µs第二句:MOV R6,#125 从②看到④只要R7-1不为0,就会返回到这句,共执行了R7次,共耗时200µs第三句:DJNZ R6,DEL2 只要R6-1不为0,就反复执行此句(内循环R6次),又受外循环R7控制,所以共执行R6*R7次,因是双周期指令,所以耗时2*R6*R7µs。
例2 1秒延时子程序:DEL:MOV R7,#10 ①DEL1:MOV R6,#200 ②DEL2:MOV R5,#248 ③DJNZ R5,$ ④DJNZ R6,DEL2 ⑤DJNZ R7,DEL1 ⑥RET ⑦对每条指令进行计算得出精确延时时间为:1+(1*10)+(1*200*10)+(2*248*200*10)+(2*200*10)+(2*10)+2=[(2*248+3)*200+3]*10+3 ⑧=998033µs≈1s由⑧整理得:延时时间=[(2*第一层循环+3)*第二层循环+3]*第三层循环+3 ⑨此式适用三层循环以内的程序,也验证了例1中式⑦(第三层循环相当于1)的成立。
延时子程序计算方法
学习MCS-51单片机,如果用软件延时实现时钟,会接触到如下形式的延时子程序:delay:mov R5,#data1d1:mov R6,#data2d2:mov R7,#data3d3:djnz R7,d3djnz R6,d2djnz R5,d1Ret其精确延时时间公式:t=(2*R5*R6*R7+3*R5*R6+3*R5+3)*T(“*”表示乘法,T表示一个机器周期的时间)近似延时时间公式:t=2*R5*R6*R7 *T假如data1,data2,data3分别为50,40,248,并假定单片机晶振为12M,一个机器周期为10-6S,则10分钟后,时钟超前量超过1.11秒,24小时后时钟超前159.876秒(约2分40秒)。
这都是data1,data2,data3三个数字造成的,精度比较差,建议C描述。
上表中e=-1的行(共11行)满足(2*R5*R6*R7+3*R5*R6+3*R5+3)=999,999e=1的行(共2行)满足(2*R5*R6*R7+3*R5*R6+3*R5+3)=1,000,001 假如单片机晶振为12M,一个机器周期为10-6S,若要得到精确的延时一秒的子程序,则可以在之程序的Ret返回指令之前加一个机器周期为1的指令(比如nop指令),data1,data2,data3选择e=-1的行。
比如选择第一个e=-1行,则精确的延时一秒的子程序可以写成:delay:mov R5,#167d1:mov R6,#171d2:mov R7,#16d3:djnz R7,d3djnz R6,d2djnz R5,d1nop ;注意不要遗漏这一句Ret附:#include"iostReam.h"#include"math.h"int x=1,y=1,z=1,a,b,c,d,e(999989),f(0),g(0),i,j,k;void main(){foR(i=1;i<255;i++){foR(j=1;j<255;j++){foR(k=1;k<255;k++){d=x*y*z*2+3*x*y+3*x+3-1000000;if(d==-1){e=d;a=x;b=y;c=z;f++;cout<<"e="<<e<<" "<<"R5="<<a<<" "<<"R6="<<b<<" "<<"R7="<<c<<""<<"f="<<f<<endl<<endl;};if(d==1){e=d;a=x;b=y;c=z;g++;cout<<"e="<<e<<" "<<"R5="<<a<<" "<<"R6="<<b<<" "<<"R7="<<c<<" "<<"g="<<g<<endl<<endl;};x++;}x=1;y++;}y=1;z++;}}。
51单片机几个延时程序
51单片机几个延时程序简介:51单片机几个精确延时程序:在精确延时的计算当中,最容易让人忽略的是计算循环外的那部分延时,在对时间要求不高的场合,这部分对程序不会造成影响.一. 500ms延时子程序(晶振12MHz,一个机器周期1us.)程序:void delay500ms(void){unsigned char i,j,k;for(i=15;i0;i)for(j=202;j0;j)for(k=81;k0;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;i0;i)for(j=132;j0;j)for(k=150;k0;k);}三. 10ms延时子程序程序:void delay10ms(void){unsigned char i,j,k;for(i=5;i0;i)for(j=4;j0;j)for(k=248;k0;k);}四. 1s延时子程序程序:void delay1s(void){unsigned char h,i,j,k;for(h=5;h0;h)for(i=4;i0;i)for(j=116;j0;j)for(k=214;k0;k);}void delay1s(void)//12M晶振,延时999999.00us {unsigned char i,j,k;for(i=46;i0;i)for(j=152;j0;j)for(k=70;k0;k);}。
用单片机C语言精确延时(定时)的方法
用单片机C语言精确延时(定时)的方法用单片机C语言精确延时(定时)的方法C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及不需要任何运行环境支持便能运行的编程语言。
那么用单片机C语言精确延时(定时)的方法都是怎样的呢?以下仅供参考!由于单片机C语言下利用软件延时不容易做到精确的定时,所以很多人在编写延时子程序的时候不能好好的把握延时的具体时间。
C 语言下,延时程序主要有以下几种:一:void delay(unsigned char k){unsigned char i,k; //定义变量for(i=0;i<k;i++); //for循环语句}该程序在Keil环境下,会先将C语言转化成汇编语言,那么我们就可以根据汇编语言来计算出精确的`时间,转化具体步骤如下:CLR A ;指令1MOV R7,A ;指令2LOOP:INC R7 ;指令3CJNE R7,k,LOOP ;指令4这里,指令1,指令2和指令3各消耗1个机器周期,指令4消耗两个机器周期(可查文末附录表),而在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,$;该语句消耗2us,一共执行i次,所以总共消耗时间t=i*2us。
三:下面的将形参换为整形int,这样的话,反汇编所执行的语句完全不同,用个具体的数字做例子:void delay(){unsigned int i=10000;while(--i);}反汇编后:4: unsigned int i=10000;C:0x0003 7F10 MOV R7,#0x10C:0x0005 7E27 MOV R6,#0x275: while(--i)6: ;C:0x0007 EF MOV A,R7C:0x0008 1F DEC R7C:0x0009 7001 JNZ C:000CC:0x000B 1E DEC R6C:0x000C 14 DEC AC:0x000D 4E ORL A,R6C:0x000E 70F7 JNZ C:0007具体计算如下1.R7经过10H(16)次循环减为0:t1=10H*(1+1+2+1+1+2)2.R6经过27H*256次循环减为0:t2=27H*256*(1+1+2+1+1+2)+27H*13.最后R7的是变为255,因此还要多出255次的循环:t3=255*(1+1+2+1+1+2)4.加上之前消耗的2us,总消耗时间:T=2+10H*(1+1+2+1+1+2)+27H*256*(1+1+2+1+1+2)+27H*1+255*(1+1+2+1+1+2)=2+16*7+39*256*7+39*1+255*7=71826us大约为72ms吧如果定义一个unsigned int i,那么延时计算公式为T=2+(i%256)*7+(i/256)*256*7+i/256+255*7关于其他类型的延时程序都可以按照这个方法对时间进行较为精确的计算。
1t单片机延时1us程序
1t单片机延时1us程序
单片机延时程序的具体实现方式会根据不同的单片机和编程语言有所不同。
这里以常见的C语言为例,使用一个假设的1T单片机(即单周期指令)来编写一个延时1微秒的程序。
请注意,这是一个非常基础的示例,实际应用中可能需要根据具体的单片机型号和编译器进行调整。
c
#include <intrins.h> // 包含处理器的指令集
void delay_1us() {
__delay_cycles(1); // 假设的单片机指令周期为1T,即1微秒
}
在这个示例中,__delay_cycles 是一个伪指令,用于产生一个指定数量的时钟周期延迟。
在这个例子中,它产生了一个1微秒的延迟。
需要注意的是,这里的代码只是一个示例,并不一定适用于所有的单片机。
在实际
应用中,需要根据具体的单片机型号和编译器的特性来编写相应的延时程序。
单片机中延时算法和nop函数的使用
计算分析:
程序共有三层循环
一层循环n:R5*2 = 81*2 = 162us DJNZ 2us
二层循环m:R6*(n+3) = 202*165 = 33330us DJNZ 2us + R5赋值 1us = 3us
成,每个循环体内的变量仍然采用无符号字符变量。
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);
_nop_(); // 产生一条NOP指令
作用:对于延时很短的,要求在us级的,采用“_nop_”函数,这个函数相当汇编NOP指令,延时几微秒。
NOP指令为单周期指令,可由晶振频率算出延时时间,对于12M晶振,延时1uS。
LOOP1: MOV R6,#TIME1 ; 1
LOOP2: NOP ; 1
NOP ; 1
DJNZ R6,LOOP2 ; 2
i--;
}
while(i);
或
unsigned char i,j
i=255;
while(i)
{j=255;
while(j)
{j--};
i--;
}
这三种方法都是用DJNZ指令嵌套实现循环的,由C51编
译器用下面的指令组合来完成的
MOV R7,#0FFH
MOV 09H,#0FFH
LOOP: DJNZ 09H,LOOP
指令相当简洁,也很好计算精确的延时时间。
51单片机汇编延时程序的设计方法
MOV 为1个机器周期,DNJZ 为2个机器周期,RET 为2个机器周期。
例1:
MAIN: AJMP DELAY1MS
DELAY1MS: ;误差 0us,包含调用时间
MOV R6,#0C7H 1个机器周期 0C7H=199
DL0:
MOV R5,#01H 1个机器周期
例3:
DELAY1MS: ;误差 0us,不包含调用时间
MOV R7,#01H
DL1:
MOV R6,#8EH
DL0:
MOV R5,#02H
DJNZ R5,$
DJNZ R6,DL0
DJNZ R7,DL1
RET
ห้องสมุดไป่ตู้
例4:
以此为基本的计时单位。如本实验要求0.2秒=200ms,10ms×R5=200ms,则R5=20,延时子程序如下:
DELAY200MS: MOV R5,#20
D1: MOV R6,#20
D2: MOV R7,#248
DJNZ R7,$
DJNZ R6,D2
DJNZ R5,D1
RET
作为单片机的指令的执行的时间是很短,数量大微秒级,因此,我们要求的闪烁时间间隔为0.2秒,相对于微秒来说,相差太大,所以我们在执行某一指令时,插入延时程序,来达到我们的要求,但这样的延时程序是如何设计呢?下面具体介绍其原理:
石英晶体为12MHz,因此,1个机器周期为1微秒,如果石英晶体为24MHz,1个机器周期为0.5微妙。
MOV R7,#05H
DL1:
MOV R6,#04H
DL0:
MOV R5,#0F8H
DJNZ R5,$
单片机延时子程序
精确延时计算公式:延时时间=[(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晶振Delay1S: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: ;500MS MOV 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 ;1DELAY24001: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+200*0.002ms ;(123*2+4)*200+12: DEL: MOV R7, #200DEL1: MOV R6, #123DEL2:NOPDJNZ R6,DEL2DJNZ R7,DEL1RETD500MS:PUSH PSWSETB RS0MOV R7,#200D51: MOV R6,#250D52: NOPNOPNOPNOPDJNZ R6,D52DJNZ R7,D51POP PSWRETDELAY: ;延时1毫秒PUSH PSWSETB 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的晶振,而在A VR单片机上常用的有8.000MHz和4.000MH的晶振所以在网上查找程序时如果涉及到精确延时则应该注意晶振的频率是多大。
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
下面几个是单片机的延时程序(包括asm和C程序,都是我在学单片机的过程中用到的),在单片机延时程序中应考虑所使用的晶振的频率,在51系列的单片机中我们常用的是11.0592MHz和12.0000MHz的晶振,而在AVR单片机上常用的有8.000MHz和4.000MH的晶振所以在网上查找程序时如果涉及到精确延时则应该注意晶振的频率是多大。
软件延时:(asm)
晶振12MHZ,延时1秒
程序如下:
DELAY:MOV 72H,#100
LOOP3:MOV 71H,#100
LOOP1:MOV 70H,#47
LOOP0:DJNZ 70H,LOOP0
NOP
DJNZ 71H,LOOP1
MOV 70H,#46
LOOP2:DJNZ 70H,LOOP2
NOP
DJNZ 72H,LOOP3
MOV 70H,#48
LOOP4:DJNZ 70H,LOOP4
定时器延时:
晶振12MHZ,延时1s,定时器0工作方式为方式1
DELAY1:MOV R7,#0AH ;; 晶振12MHZ,延时0.5秒
AJMP DELAY
DELAY2:MOV R7,#14H ;; 晶振12MHZ,延时1秒
DELAY:CLR EX0
MOV TMOD,#01H ;设置定时器的工作方式为方式1
MOV TL0,#0B0H ;给定时器设置计数初始值
MOV TH0,#3CH
SETB TR0 ;开启定时器
HERE:JBC TF0,NEXT1
SJMP HERE
NEXT1:MOV TL0,#0B0H
MOV TH0,#3CH
DJNZ R7,HERE
CLR TR0 ;定时器要软件清零
SETB EX0
RET
10ms延时子程序(12MHZ)
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延时子程序(12MHZ)
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--); }
200ms延时子程序(12MHZ)
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--);
}
500ms延时子程序程序: (12MHZ)
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--);
}
下面是用了8.0000MHZ的晶振的几个延时程序(用定时0的工作模式1):(1)延时0.9MS
void delay_0_9ms(void)
{
TMOD=0x01; /*定时器0工作在模式1下(16位计数器)*/
TH0=0xfd;
TL0=0xa8;
TR0=1; /*启动定时器*/
while(TF0==0);
TR0=0;
}
(2)延时1MS
void delay_1ms(void)
{
TMOD=0x01; /*定时器0工作在模式1下(16位计数器)*/
TH0=0xfd;
TL0=0x65;
TR0=1; /*启动定时器*/
while(TF0==0);
TR0=0;
}
(3)延时4.5ms
void delay_4_5ms(void)
{
TMOD=0x01; /*定时器0工作在模式1下(16位计数器)*/
TH0=0xf4;
TL0=0x48;
TR0=1; /*启动定时器*/
while(TF0==0);
TR0=0;
}
在用定时器做延时程序时如果懒得计算定时器计数的初始值可以在网上找一个专门用来做延时的小软件。