哪位高手知道 单片机精确延时1秒得C语言子程序 谢谢了

哪位高手知道 单片机精确延时1秒得C语言子程序 谢谢了,第1张

下面几个是单片机的延时程序(包括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

C语言延时程序:

10ms延时子程序(12MHZ)

void delay10ms(void)

{

unsigned char i,j,k

for(i=5i>0i--)

for(j=4j>0j--)

for(k=248k>0k--)

}

1s延时子程序(12MHZ)

void delay1s(void)

{

unsigned char h,i,j,k

for(h=5h>0h--)

for(i=4i>0i--)

for(j=116j>0j--)

for(k=214k>0k--)

}

200ms延时子程序(12MHZ)

void delay200ms(void)

{

unsigned char i,j,k

for(i=5i>0i--)

for(j=132j>0j--)

for(k=150k>0k--)

}

500ms延时子程序程序: (12MHZ)

void delay500ms(void)

{

unsigned char i,j,k

for(i=15i>0i--)

for(j=202j>0j--)

for(k=81k>0k--)

}

下面是用了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

}

push cx先把cx推进栈以保存cx原来的值。然后用mov cx,0ffh赋值,loop循环每执行一次cx自减一,到cx为0为止,此时循环共执行0ffh次即255次。再将栈中cx原来的值d出给cx寄存器。

如果CUP主频为40mHz,则时钟周期为1/40=0.025微秒。

在808X中,一条LOOP指令如果实现跳转的话需要18个时钟周期,退出时需要5个时钟周期。所以这个延时子程序循环部分的延时(0.025*18*255+5)微秒,其他语句的延时基本可以忽略

延时程序在单片机编程中使用非常广泛,但一些读者在学习中不知道延时程序怎么编程,不知道机器

周期和指令周期的区别,不知道延时程序指令的用法, ,本文就此问题从延时程序的基本概念、机器周期和指

令周期的区别和联系、相关指令的用法等用图解法的形式详尽的回答读者

我们知道程序设计是单片机开发最重要的工作,而程序在执行过程中常常需要完成延时的功能。例如

在交通灯的控制程序中,需要控制红灯亮的时间持续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 晶振12M

1+(1+2*248+2)*4+1+1+1=20000US=20MS

用汇编..优点就是精确...

缺点就是算有点复杂.

DELAY20MS:

MOV R7,#4

D1:

MOV R6,#248

DJNZ R6,$

DJNZ R7,D1

NOP

NOP

RET

2)一些通过计算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

ret

12M晶振 机器周期为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,LOOP4

4)延时1分钟子程序,F=6MHz

程序已测过,延时时间60,000,000.0uS

delay60s:mov r3,#228

mov r2,#253

mov r1,#219

loop1:   djnz r1,$

djnz r2,loop1

djnz r3,loop1

nop

ret

5)计算机反复执行一段程序以达到延时的目的称为软件延时,单片机程序中经常需要短时间的延时,但是相当一部分人对延时程序很模糊,对延时程序的算法不够了解,在这里我以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.1s

0.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.5s

6) 51单片机经典流水灯程序,在51单片机的P2口接上8个发光二极管,产生流水灯的移动效果。

ORG        0                   程序从0地址开始

START:      MOV      A,#0FEH     让ACC的内容为11111110

LOOP:         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                           结束程序


欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/yw/11217713.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2023-05-14
下一篇 2023-05-14

发表评论

登录后才能评论

评论列表(0条)

保存