在我们DIY的电子钟中,我们需要使用单片机定时器来显示秒数。 说是显示,其实就是实现数码管上“:”点的闪烁。 这里初步的定义是每秒亮一次,亮0.5秒,灭0.5秒。 实现显示秒的功能。 这里也可以使用DS1302的第二个数据,但实现起来比较麻烦。 为了达到同样的效果,我们追求的是程序尽可能简单,所以这里我们使用单片机定时器来实现。
我们DIY时钟板上的微控制器是STC15W408AS。 该微控制器有自己的IRC可调时钟和可靠的复位。 为了降低功耗(工作频率越低,功耗越小),本时钟采用12M工作频率(编程程序在软件中选择),那么当定时器工作在12T模式时,一个机械周期是1us。
接下来我们应该看一下微控制器的数据表。 以下是我们今天需要关注的寄存器:
TCON是定时器T0和T1的控制寄存器,可以位寻址(直接操作位); TMOD是T0和T1工作模式控制寄存器,不能按位寻址(只能操作寄存器)。 高四位控制T1,低四位控制T0; 定时器的工作模式由TOMD寄存器中的M1和M0选择,如上图所示。
在本例中,我们希望使用T0来实现1秒的计时时间。 这里我们使用T0工作在模式0,即16位自动重装模式(传统51单片机只有8位自动重装,需要高精度计时时最好使用自动重装)。 我们不需要外部中断来启动定时器,所以GATE位=0,T0工作在定时模式,CT=0,所以我们的TMOD寄存器的值为0x00; TCON寄存器中与T0相关的位是TF0和TR0; TF0 =0:T0中断标志位,当定时器中断发生时,TF0自动置位,CPU相应中断后硬件自动清零; TR0=1:打开定时器,相当于定时器开关。
除了这些寄存器之外,定时器溢出后也会产生中断,所以还需要设置中断部分:
EA=1:,打开主中断,相当于主中断开关; ET0=1; 打开定时器T0中断,相当于中断的分开关。 只有当主中断开关和相应的子开关打开时,CPU才能进行相应的中断。 信号,详细信息请参见中断部分数据表。 我们使用的STC15W系列单片机是增强型单片机。 为了兼容传统的51单片机,它还有一个寄存器AUXR。 该寄存器可以设置T0工作在1T或12T模式。 这里我们让T0工作在12T模式。 辅助=0x00。 最后是定时器的初值寄存器。 我们需要计时的时间是500ms。 16位定时器在12M频率下的最大时间为65535us。 我们需要的是500ms,这显然是达不到的,所以我们需要采用组合计时的方法,这里我们将定时器的中断频率设置为10ms,然后我们在中断一次后将中断函数中的某个变量加1。 当变量加到50时,时间为500ms,当变量加到100时,时间为1s。 这就是我们实现1s计时的思路。
具体实施流程如下:
如上图程序所示,定时器初始化时,将T0位设置为16位自动重载模式,工作在12T模式,初始值为10ms,开启定时器,开启中断。 这样,定时器就工作了; 在定时器中断函数中,我们每次进入中断后都会将变量T_a加1。 当变量小于50(小于500ms)时,让D=1(D是我们电路中控制第二个显示的两个点,高电平有效),当大于50且小于100时,D=0,第二显示器关闭。 这样,第二个显示屏将在 1 秒内打开 500ms,关闭 50ms。 上图中中断函数名后面的中断1是中断函数的入口地址,在C语言中称为中断号(初学者解释,有经验的驱动会跳过)。 具体中断对应的入口地址对照表如下(部分):