江苏泰兴豪都spa会所:单片机延时子程序

来源:百度文库 编辑:偶看新闻 时间:2024/04/30 13:03:50
延时程序在单片机编程中使用非常广泛,但一些读者在学习中不知道延时程序怎么编程,不知道机器周期和指令周期的区别,不知道延时程序指令的用法, ,本文就此问题从延时程序的基本概念、机器周期和指令周期的区别和联系、相关指令的用法等用图解法的形式详尽的回答读者   我们知道程序设计是单片机开发最重要的工作,而程序在执行过程中常常需要完成延时的功能。例如在交通灯的控制程序中,需要控制红灯亮的时间持续30秒,就可以通过延时程序来完成。延时程序是如何实现的呢?下面让我们先来了解一些相关的概念。一、机器周期和指令周期1.机器周期是指单片机完成一个基本操作所花费的时间,一般使用微秒来计量单片机的运行速度,51 单片机的一个机器周期包括12 个时钟振荡周期,也就是说如果51 单片机采用12MHz 晶振,那么执行一个机器周期就只需要1μs;如果采用的是6MHz 的晶振,那么执行一个机器周期就需要2 μs。   2 .指令周期是指单片机执行一条指令所需要的时间,一般利用单片机的机器周期来计量指令周期。在51 单片机里有单周期指令(执行这条指令只需一个机器周期),双周期指令(执行这条指令只需要两个机器周期),四周期指令(执行这条指令需要四个机器周期)。除了乘、除两条指令是四周期指令,其余均为单周期或双周期指令。也就是说,如果51 单片机采用的是12MHz 晶振,那么它执行一条指令一般只需1~2 微秒的时间;如果采用的是6MH 晶振,执行一条指令一般就需2~4 微秒的时间。   现在的单片机有很多种型号,但在每个型号的单片机器件手册中都会详细说明执行各种指令所需的机器周期,了解以上概念后,那么可以依据单片机器件手册中的指令执行周期和单片机所用晶振频率来完成需要精确延时时间的延时程序。二、延时指令   在单片机编程里面并没有真正的延时指令,从上面的概念中我们知道单片机每执行一条指令都需要一定的时间,所以要达到延时的效果,只须让单片机不断地执行没有具体实际意义的指令,从而达到了延时的效果。1.数据传送指令 MOV   数据传送指令功能是将数据从一个地方复制、拷贝到另一个地方。   如:MOV R7,#80H   ;将数据80H 送到寄存器R7,这时寄存器R7 里面存放着80H,就单这条指令而言并没有任何实际意义,而执行该指令则需要一个机器周期。2.空操作指令 NOP   空操作指令功能只是让单片机执行没有意义的操作,消耗一个机器周期。3.循环转移指令 DJNZ   循环转移指令功能是将第一个数进行减1 并判断是否为0,不为0 则转移到指定地点;为0 则往下执行。   如:DJNZ R7,KK ;将寄存器R7 的内容减1 并判断寄存器R7 里的内容减完1 后是否为0,如果   不为0 则转移到地址标号为KK 的地方;如果为0 则执行下一条指令。这条指令需要2 个机器周期。   利用以上三条指令的组合就可以比较精确地编写出所需要的延时程序。三、1 秒延时子程序、流程图及时间计算 (以单片机晶振为12MHz 为例,1 个机器周期需要1μs)了解了以上的内容,现在让我们来看看程序总共所需时间:1+10+2560+330240+660480+5120+20+2=998433 μs≈1S   在这里运行这段程序共需998433 μs,还差1567μs 才达到1S 的,所以想要达到完美的1S 延时,需要在返回指令RET 前再添加一些指令让它把1567μs 的延时完成。有兴趣的读者可以自己试着添加完成。最后补充一点,编写程序时一般将延时程序编写成独立的子程序,而所谓子程序也就是一个实现某个功能的小模块。这样在主程序中就可以方便地反复调用编写好的延时子程序。   小提示:循环转移指令(DJNZ )除了可以给定地址标号让其跳转外,还可以将地址标号改成$,这样程序就跳回本指令执行。例如:   DJNZ R7,$ ;R7 内容减1 不为0,则再次执行本指令;为0 则往下执行,当R7 的值改为10时,则执行完该条程序所需的时间为2*10=20 μs。51单片机汇编延时程序算法详解将以12MHZ晶振为例,详细讲解MCS-51单片机中汇编程序延时的精确算法。   指令周期、机器周期与时钟周期  指令周期:CPU执行一条指令所需要的时间称为指令周期,它是以机器周期为单位的,指令不同,所需的机器周期也不同。  时钟周期:也称为振荡周期,一个时钟周期 =晶振的倒数。  MCS-51单片机的一个机器周期=6个状态周期=12个时钟周期。  MCS-51单片机的指令有单字节、双字节和三字节的,它们的指令周期不尽相同,一个单周期指令包含一个机器周期,即12个时钟周期,所以一条单周期指令被执行所占时间为12*(1/12000000)=1μs。  程序分析  例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)的成立。  注意,要实现较长时间的延时,一般采用多重循环,有时会在程式序里加入NOP指令,这时公式⑨不再适用,下面举例分析。  例3仍以1秒延时为例  DEL:MOV R7,#10 1指令周期1  DEL1:MOV R6,#0FFH 1指令周期10  DEL2:MOV R5,#80H 1指令周期255*10=2550  KONG:NOP 1指令周期128*255*10=326400  DJNZ R5,$ 2指令周期2*128*255*10=652800  DJNZ R6,DEL2 2指令周期2*255*10=5110  DJNZ R7,DEL1 2指令周期2*10=20  RET 2  延时时间=1+10+2550+326400+652800+5110+20+2 =986893μs约为1s  整理得:延时时间=[(3*第一层循环+3)*第二层循环+3]*第三层循环+3 ⑩  结论:针对初学者的困惑,对汇编程序的延时算法进行了分步讲解,并就几种不同写法分别总结出相应的计算公式,只要仔细阅读例1中的详解,并用例2、例3来加深理解,一定会掌握各种类型程序的算法并加以运用。单片机延时子程序1)延时为:20ms 晶振12M1+(1+2*248+2)*4+1+1+1=20000US=20MS用汇编..优点就是精确...缺点就是算有点复杂.DELAY20MS:MOV R7,#4D1:MOV R6,#248DJNZ R6,$DJNZ R7,D1NOPNOPRET2)一些通过计算51汇编指令得出的软延时子程序;*****************************************************************   ;延时10uS   ;*****************************************************************     time10us:               mov     r5,#05h                 ;11us                           djnz    r5,$                           ret    ;*****************************************************************   ;延时50uS   ;*****************************************************************     time50us:               mov     r5,#19h                 ;51us                           djnz    r5,$                           ret    ;*****************************************************************   ;延时100uS   ;*****************************************************************     time100us:              mov     r5,#31h                 ;99.6us                           djnz    r5,$                           ret    ;*****************************************************************   ;延时200uS   ;*****************************************************************     time200us:              mov     r5,#64h                 ;201us                           djnz    r5,$                           ret    ;*****************************************************************   ;延时250uS   ;*****************************************************************     time250us:              mov     r5,#7ch                 ;249.6us                           djnz    r5,$                           ret    ;*****************************************************************   ;延时350uS   ;*****************************************************************     time350us:              mov     r5,#0afh                 ;351us   time350us_1:            djnz    r5,time350us_1                           ret    ;*****************************************************************   ;延时500uS   ;*****************************************************************     time500us:              mov     r5,#0fah                 ;501us   time500us_1:            djnz    r5,time500us_1                           ret    ;*****************************************************************   ;延时1mS   ;*****************************************************************     time1ms:                mov     r5,#0fah                ;1001us   time1ms_1:              nop                          nop                          djnz    r5,time1ms_1                           ret    ;*****************************************************************   ;延时2.5mS   ;*****************************************************************     time2_5ms:              mov     r5,#05h          ;2.496ms   time2_5ms_1:            mov     r6,#0f8h         ;497us                           djnz    r6,$                           djnz    r5,time2_5ms_1                           ret    ;*****************************************************************   ;延时10mS   ;*****************************************************************     time10ms:               mov    r5,#14h         ;10.262ms   time10ms_1:             mov    r6,#0ffh        ;511us                           djnz   r6,$                           djnz   r5,time10ms_1                           ret    ;*****************************************************************   ;延时50mS   ;*****************************************************************     time50ms:               mov    r5,#63h         ;49.996ms   time50ms_1:             mov    r6,#0fbh        ;503us                           djnz   r6,$                           djnz   r5,time50ms_1                           ret    ;*****************************************************************   ;延时100mS   ;*****************************************************************     time100ms:              mov     r5,#0c3h        ;100.036ms   time100ms_1:            mov     r6,#0ffh        ;511us                           djnz    r6,$                           djnz    r5,time100ms_1                           ret    ;*****************************************************************   ;延时200mS   ;*****************************************************************     time200ms:              mov     r5,#02h         ;250.351ms   time200ms_1:            mov     r6,#0f4h        ;125.173ms   time200ms_2:            mov     r7,#0ffh        ;511us                           djnz    r7,$                           djnz    r6,time200ms_2                           djnz    r5,time200ms_1                           ret    ;*****************************************************************   ;延时500mS   ;*****************************************************************     time500ms:              mov    r5,#04h         ;500.701ms   time500ms_1:            mov    r6,#0f4h        ;125.173ms   time500ms_2:            mov    r7,#0ffh        ;511us                           djnz   r7,$                           djnz   r6,time500ms_2                           djnz   r5,time500ms_1                           ret    ;*****************************************************************   ;延时1S   ;*****************************************************************     time1s:                 mov    r5,#08h         ;1001.401ms   time1s_1:               mov    r6,#0f4h        ;125.173ms   time1s_2:               mov    r7,#0ffh        ;511us                           djnz   r7,$                           djnz   r6,time1s_2                           djnz   r5,time1s_1                           ret12M晶振 机器周期为1US  NOP为单周期指令 DJNZ为双周期指令.3);;晶振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,LOOP44);延时1分钟子程序,F=6MHz;程序已测过,延时时间60,000,000.0uSdelay60s:mov r3,#228         mov r2,#253         mov r1,#219loop1:   djnz r1,$         djnz r2,loop1         djnz r3,loop1         nop         ret5)计算机反复执行一段程序以达到延时的目的称为软件延时,单片机程序中经常需要短时间的延时,但是相当一部分人对延时程序很模糊,对延时程序的算法不够了解,在这里我以12MHz晶振和两个经典延时子程序为例,详细分析单片机汇编延时程序。何为时钟周期、机器周期、和指令周期?时钟周期:也就是振荡周期,以12MHz的时钟脉冲为例,那时钟周期就为(1/12000000)s=(1/12)us;机器周期:1个机器周期=6个状态周期=12个时钟周期=1us;指令周期:CPU执行一条指令所需要的时间称为指令周期,指令周期是以机器周期为单位的,不同的指令所需的机器周期不一定相同,可参考51单片机指令速查表。        由上可得:CPU执行一条单周期指令,需要1us;执行一条双周期指令需要2us。        下面是具体的延时子程序分析:0.1s延时子程序(12MHz晶振):           MOV R7,#200   ;单周期指令(1us)D1:     MOV R6,#250   ;单周期指令(1us)           DJNZ R6,$      ;双周期指令(2us)//该指令自身执行R6次           DJNZ R7,D1     ;双周期指令(2us)//D1执行R7次           RET            ;双周期指令(2us)T=1+(1+2*R6+2)*R7+2   =100603us   ≈0.1s0.5s延时子程序(12MHz晶振):           MOV R7,#5     ;单周期指令(1us)D1:     MOV R6,#200   ;单周期指令(1us)D2:     MOV R5,#250   ;单周期指令(1us           DJNZ R5,$      ;双周期指令(2us)//该指令自身执行R5次           DJNZ R6,D2     ;双周期指令(2us)//D2执行R6次           DJNZ R7,D1     ;双周期指令(2us)//D1执行R7次           RET            ;双周期指令(2us)T=1+[1+(1+2*R5+2)*R6+2]*R7+2   =503018us   ≈0.5s6) 51单片机经典流水灯程序,在51单片机的P2口接上8个发光二极管,产生流水灯的移动效果。                    ORG        0                   ;程序从0地址开始START:      MOV      A,#0FEH     ;让ACC的内容为11111110LOOP:         MOV      P2,A            ;让P2口输出ACC的内容                     RR          A                  ;让ACC的内容左移                     CALL     DELAY       ;调用延时子程序                     LJMP     LOOP          ;跳到LOOP处执行;0.1秒延时子程序(12MHz晶振)===================DELAY:      MOV      R7,#200      ;R7寄存器加载200次数D1:               MOV      R6,#250      ;R6寄存器加载250次数                     DJNZ     R6,$             ;本行执行R6次                     DJNZ     R7,D1          ;D1循环执行R7次                     RET                            ;返回主程序                     END                           ;结束程序