单片机汇编语言 编写一个延时50ms的子程序,设晶振主频率为12MHz

单片机汇编语言 编写一个延时50ms的子程序,设晶振主频率为12MHz,第1张

关于单片机延时程序的具体分析

前面我们介绍了延时程序,但这还不完善,因为,我们只知道DJNZ R6,D2这句话会被执行62500次,但是执行这么多次需要多长时间呢?是否满足我们的要求呢?我们还不知道,所以下面要来解决这个问题。

关于单片机延时程序的具体分析

先提一个问题:我们学校里什么是最重要的。(铃声)校长可以出差,老师可以休息,但学校一日无铃声必定大乱。整个学校就是在铃声的统一指挥下,步调一致,统一协调地工作着。这个铃是按一定的时间安排来响的,我们可以称之为“时序��时间的顺序”。一个由人组成的单位尚且要有一定的时序,计算机当然更要有严格的时序。事实上,计算机更象一个大钟,什么时候分针动,什么时候秒针动,什么时候时针动,都有严格的规定,一点也不能乱。计算机要完成的事更复杂,所以它的时序也更复杂。

我们已知,计算机工作时,是一条一条地从ROM中取指令,然后一步一步地执行,我们规定:计算机访问一次存储器的时间,称之为一个机器周期。这是一个时间基准,好象我们人用“秒”作为我们的时间基准一样,为什么不干脆用“秒”,多好,很习惯,学下去我们就会知道用“秒”反而不习惯。

一个机器周期包括12个时钟周期。下面让我们算一下一个机器周期是多长时间吧。设一个单片机工作于12M晶振,它的时钟周期是1/12(微秒)。它的一个机器周期是12(1/12)也就是1微秒。(请计算一个工作于6M晶振的单片机,它的机器周期是多少)。

MCS-51单片机的所有指令中,有一些完成得比较快,只要一个机器周期就行了,有一些完成得比较慢,得要2个机器周期,还有两条指令要4个机器周期才行。这也不难再解,不是吗?我让你扫地的执行要完成总得比要你完成擦黑板的指令时间要长。为了衡量指令执行时间的长短,又引入一个新的概念:指令周期。所谓指令周期就是指执行一条指令的时间。INTEL对每一条指令都给出了它的指令周期数,这些数据,大部分不需要我们去记忆,但是有一些指令是需要记住的,如DJNZ指令是双周期指令。

下面让我们来计算刚才的延时。首先必须要知道晶振的频率,我们设所用晶振为12M,则一个机器周期就是1微秒。而DJNZ指令是双周期指令,所以执行一次要2个微秒。一共执行62500次,正好125000微秒,也就是125毫秒。

1、首先,在电脑中打开keil软件,创建好工程,然后添加c文件,如下图所示。

2、然后添加c文件,接下来输入代码,先输入一个头文件命令。

3、然后,进行宏定义,代码如图所示。

4、然后声明P1口,如下图所示。

5、最后,将延时语句全部添加进去,代码按照图中所示的直接敲入即可。

6、最后,点击编译,生成HEX文件就可以了,这样51单片机延时语句就完成了。

举一个例子来说明吧比如你要编一个延时50毫秒的子程序,那么步骤如下:

1、查看一下你的硬件环境,比如晶振大小,CPU型号,不用CPU指令的机器周期是不一样的。

2、计算延时需要的机器周期。比如采用12M晶振,CPU采用通用8051,那么一个机器周期为1US,50毫秒为501000=50000US,需要的机器周期=50000/1=50000。

3、试编程,如下:

程序代码 指令时间 总共时间

DELAY50MS: ;2 2

MOV R7,#A ;1 1

DELAY1:

MOV R6,#B ;1 1A

DJNZ R6,$ ;2 2BA

DJNZ R7,DELAY1 ;2 2A

RET ;2 2

所以总时间=2+1+A+2AB+2A+2=5+3A+2AB

4、凑数求A、B

根据2、3得到如下式子:

50000=5+3A+2AB

可以有很多种结果,不过最好是以A尽可能小,B尽可能大为原则,当然不能大于255

我现在凑出A=110,B=225;那么总延时时间=5+3110+2110225=49835。还差165US

5、补齐不够时间

再加一个小循环就OK了,呵呵如下:

MOV R6,#C

DJNZ R6,$

会算了吧,2C+1=165;所以C=82。

现在完整的延时程序出来了,如下:

DELAY50MS: ;2 2

MOV R7,#110 ;1 1

DELAY1:

MOV R6,#225 ;1 1110

DJNZ R6,$ ;2 2225110

DJNZ R7,DELAY1 ;2 2110

MOV R6,#82 ;1 1

DJNZ R6,$ ;2 282

RET ;2 2

很圆满:总的时间50000微妙,也就是50毫秒。这种方式编程,在该硬件环境下可以保证最大误差为1微妙。

软件延时程序就是利用执行每一条指令时所用的时间来进行延时的。

一般采用循环结构,达到多次反复执行某一段指令的目的,来增加延时的时间,可以通过对循环次数的控制,来达到控制延时时间长短的目的。

为了延长延时时间,一般要采用多重循环,即由外循环内部又含有内循环。

延时时间=(内循环时间)×外循环次数。

例如:设计一个延时1ms的延时子程序ys1ms,设单片机8051的时钟频率为12MHZ。

则单片机8051一个机器周期=12T=12/f=12/12MHZ=1微秒

程序和延时时间计算如下:

ys1ms: MOV R7,#4 ; 单周期1uS ( 晶振为12MHz)

DEL1: MOV R6,#123 ; 单周期1uS

DEL2: DJNZ R6,DEL2 ; 双周期2uS123=246uS

DJNZ R7,DEL1 ; 双周期(2us+246+1)4=996uS

NOP ; 单周期1uS

RET; 双周期2uS

延时时间t=1uS +(1us+246uS+2uS)×4+1uS+2uS=1000uS=1ms

其中 (1us+246uS+2uS)=249uS 为内循环时间 4为外循环次数

第一个1uS 是第一条指令的执行时间

1uS+2uS 是 最后二条指令 NOP RET指令的执行时间。

哈哈 给俺加分吧

毫秒级别的延时代码,我昨天在写一个秒表,发现VB自带的timer不准,所以找到了下面这个API函数,改了一下,给你一个延时代码从百度贴吧找到的,并非原创

Private Declare Function GetTickCount& Lib "kernel32" () '声明API

Private Function yanshi(ms As Long) '我自创一个延时函数名为"yanshi"

starttim = GetTickCount

Do

DoEvents

Loop Until GetTickCount >= starttim + ms

End Function

打开VB,把上面的代码复制到通用处,当你想用到延时的时候,添加一句:

yanshi "引号里输入毫秒数"

就可以在两句代码之间延时一段时间执行了

多简单的小程序呀:

TIME1MS:

MOV R6, #2

TIME1:

;延时498uS

MOV R7, #248

DJNZ R7, $ ;R7的为0时,程序向下运行,否则继续减

;

DJNZ R6, TIME1 ;加上此命令后,每个小周期时间为500uS

;运行两周为1MS,再加上最前面的MOV R6那条指令,就是1002MS

RET

此程序实现的是1002MS的定时,当然这当中不算主程序调用此延时程序时现场保护的时间,即压栈和出栈的时间

DEL: MOV R7,#210

DEL1: MOV R6,#117

DEL2: DJNZ R6,DEL2

NOP

DJNZ R7,DEL1

NOP ;此处17个NOP

NOP

NOP

RET

1μs+(1+234+1+2)μs210+2μs+17=50000μs

其实考虑到LCALL调用这个函数的时间,末尾应该再减少2个NOP。

另外,实际使用中需要精确延时的话应该使用定时器中断,一方面是精确,另一方面延时函数执行时,如果有中断发生,那么延时就不正确了。

以上就是关于单片机汇编语言 编写一个延时50ms的子程序,设晶振主频率为12MHz全部的内容,包括:单片机汇编语言 编写一个延时50ms的子程序,设晶振主频率为12MHz、请帮忙在51系列单片机系统中,编写一个延时1ms的子程序。谢谢。。、单片机延时时间程序怎么编程等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!

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

原文地址: http://outofmemory.cn/zz/9341795.html

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

发表评论

登录后才能评论

评论列表(0条)

保存