关于单片机延时程序的具体分析
前面我们介绍了延时程序,但这还不完善,因为,我们只知道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的子程序。谢谢。。、单片机延时时间程序怎么编程等相关内容解答,如果想了解更多相关内容,可以关注我们,你们的支持是我们更新的动力!
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)