第二篇 声明:作者初学单片机编程,本着刨根问底的探索精神,对延时代码进行了完全透彻的分析,计算出其中的误差,根据不同代码占用机器周期进行调整。至于调整0.01ms左右的时间误差对实际应用有何实际意义则不敢妄谈。不过您看完这篇**的绿色部分,即可明确延时程序的设计方法。 举例程序段落: ;系统频率:6MHz Delay: MOV R5,#25 ;5ms延时——MOV指令占用1机器周期时间 Delay1: MOV R6,#200 ;200ms延时 Delay2: MOV R7,#166 ;1ms延时常数 Delay3: NOP ;空指令,什么都不做,停留1机器周期时间 DJNZ R7,Delay3 ;R7减1赋值给R7,如果此时R7不等于零,转到Delay3执行。——2机器周期时间 DJNZ R6,Delay2 DJNZ R5,Delay1 解析如下: 1、首先计算机器周期T=12*1/f=2μs。 2、注意DJNZ R7,Delay3每执行1次需要占用NOP的时间和DJNZ本身的时间共3个机器周期。6μs。那么1ms的时间需要1ms*1000/6μs=166.67,取166。 3、注意DJNZ R6,Delay2是在166次循环后执行1次的(时间为MOV机器周期+本身机器周期,3*2=6μs),直到166*200次后,R6=0,才执行DJNZ R5,Delay1。 4、DJNZ R5,Delay1是在R5不为0的时候循环回去。时间也为6μs。 5、时间总计:166*200*25*6μs+200*25*6μs+25*6μs=5010150μs,合计5.01015ms(编程的人都遇到过类似的潜逃循环,此程序忽略了执行MOV的时间,只计算了循环所用时间,即166*200*25*6/1000000=4.98ms,近似5ms)。 程序改进: 去掉NOP命令,整数化1ms需要的延时常数。 Delay: MOV R5,#25 ;5ms延时——MOV指令占用1机器周期时间 Delay1: MOV R6,#200 ;200ms延时 Delay2: MOV R7,#250 ;1ms延时常数 Delay3: ;NOP ;空指令,什么都不做,停留1机器周期时间 DJNZ R7,Delay3 ;R7减1赋值给R7,如果此时R7不等于零,转到Delay3执行。——2机器周期时间 DJNZ R6,Delay2 DJNZ R5,Delay1 此时时间总计:250*200*25*4μs+200*25*6μs+25*6μs=5030150μs。时间占用误差反而比未改进的时候大,可修正,将R7-30150/(25*200*4)=248(因为R7=250循环1次占用2个机器周期,4μs,计算等于R7-1.5075,将时间减小到小于5ms,剩余时间另补,取248)。则:时间总计:248*200*25*4μs+200*25*6μs+25*6μs=4990150μs,需要补:5000000-4990150=9850μs,9850/2=4925机器周期。补一个MOV R4,#200,4个NOP,还需4920机器周期,将其约分,得到24*205=4920。如何建立函数根据实际代码调整,如下: Delay: MOV R5,#25 ;5ms延时——MOV指令占用1机器周期时间 Delay1: MOV R6,#200 ;200ms延时 Delay2: MOV R7,#250 ;1ms延时常数 Delay3: ;NOP ;空指令,什么都不做,停留1机器周期时间 DJNZ R7,Delay3 ;R7减1赋值给R7,如果此时R7不等于零,转到Delay3执行。——2机器周期时间 DJNZ R6,Delay2 DJNZ R5,Delay1 NOP NOP NOP NOP MOV R3,#6 Delayadd: MOV R4,#205 MOV R2,#0H DJNZ R3,Delayadd 解析205*24调整为205*6——这是因为Delay循环为4机器周期代码,因此将24/4=6。请计算:205*6*4=4920;4920+5=4925。时间补充正好。此时时间计算:248*200*25*4μs+200*25*6μs+25*6μs=4990150μs+4925*2μs=5000000μs合计5ms。 理论上1μs都不差(仅为科学探讨,具体晶振频率的误差多大作者并不明确)。
|