PIC单片机16F84的内部硬件资源(五)
7 延时和定时在设计单片机应用系统时,经常会遇到需要使某一过程(如加温、加压等)持续一段时间的情况,如连续加压 1 分钟,通电 2 分钟等。单片机如何正确确定这段时间呢?这里可通过两种方式,即延时和定时来实现。试看下例。 在应用系统中要求 PIC16F84 的 RAO 端控制一个发光二极管按一定频率闪亮,可通过右图的电路来实现。同时还必须为 16F84 编制一个程序。由电路图可知,要使发光二极管 LED 按一定的频率闪亮,只要使 RAO 端输出一个变化的高→低→高……电平即可。
由此设计出如下的源程序(清单 1): list P=16F84,F=INHX8M;…… ORG 0 MOVLW 0;主程序开始 TRIS 5;置 RA 口为输出 BCF 5,0;RA 口 0 位清零 LOOP:CALL DELAY;闪动延时 COMF 5;RA 口求反,亮—灭交替 GOTO LOOP;循环;…… DELAY;以下为延时子程序 MOVLW D′50 MOVWF 8 LOOP1:MOVWF 9 LOOP2:DECFSZ 9,F GOTO LOOP2 DECFSZ 8,F GOTO LOOP1 RETLW 0 由清单 1 可知,当主程序开始时,首先将工作寄存器 W 清零,然后将 W 寄存器的内容送 TRISA 寄存器,使其清零,以设置 RA 口为输出。
接着又将 RA 口的第 5 位清零,使 LED 开始时处于熄灭状态。随之持续一段时间,即执行延时子程序,再将 RA 口取反,变为高电平输出,LED 发光,再延时,又使 RA 口取反,LED 熄灭……。这样,LED 就一暗一亮,持续交替进行。 在这里,使 LED 亮、暗持续一段时间是通过单片机执行延时子程序 DELAY 来实现的。此延时程序的核心就是让单片机的 CPU 反复执行使寄存器内容减 1 的指令 DECFSZ。即将十进制数 50 分别装入通用寄存器 F8、F9,以进行 50×50=2500 次的减 1 操作。
如果执行一次 DECFSZ 指令需 1 个指令周期(跳转时需 2 个周期),若设振荡频率为 100kHz,即指令周期为 40μs,则延时时间为 2500×40=100000μs=100ms,即 0?1 秒。实际上还略为大些。此延时时间已超过人眼的视觉保留时间。因而能看清 LED 的明、暗交替变化。 如果我们需要更长的延时时间,可仿照上例,装入更大的数或引入多重循环。因此,在原则上,延时时间可根据需要任意延长。
不过,采用延时程序来持续某一过程的方式有缺陷。延时就是使 CPU 在某几条指令上“转圈”,延时越长,“转圈”数越多,这时,CPU 不能再去执行其它操作,如监视温度、湿度等。这在某些实时控制系统中,不允许这样做。为此,在单片机 16F84 中,专门设置了一个“闹钟”——定时器 TMR0。需要某过程延续多长时间,可将其“拨入”TMR0,到时它会发生“中断”,告诉 CPU 定时时间到。要 CPU 暂停其它工作,转过来执行“中断子程序”,完成输出开、关信号之类的任务后,再回去执行其中断的工作。
这样,就使 CPU 的工作效率提高。因而,延时的使用有局限性,采用定时器 TMR0 则可用于各种场合中。