1单片机定时器概述:
要实现定时功能,除了利用单片机内部的定时/计数器,还可以采用以下三种方法:
- 软件定时:不占用硬件资源,但占用了CPU时间,降低了CPU的利用率。
- 采用时基电路定时:例如采用555电路,外接必要的元器件(电阻和电容),即可构成硬件定时电路。但在硬件连接好以后,定时值与定时范围不能由软件进行控制和修改,即不可编程。
- 采用可编程芯片定时:这种定时芯片的定时值及定时范围很容易用软件来确定和修改,此种芯片定时功能强,使用灵活。在单片机的定时/计数器不够用时,可以考虑进行扩展。
定时/计数器的实质是加1计数器(16位),由高8位和低8位两个寄存器组成。TMOD是定时/计数器的工作方式寄存器,确定工作方式和功能;TCON是控制寄存器,控制T0、T1的启动和停止及设置溢出标志。
加1计数器输入的计数脉冲有两个来源:一个是由系统的时钟振荡器输出脉冲经12分频后送来;另一个是 T0 或T1引脚输入的外部脉冲源。每来一个脉冲计数器加1,当加到计数器为全1时,再输入一个脉冲就使计数器回零,且计数器的溢出会使TCON中TF0或TF1置1,向CPU发出中断请求(定时/计数器中断允许时)。如果定时/计数器工作于定时模式,则表示定时时间已到;如果工作于计数模式,则表示计数值已满。可见,由溢出时计数器的值减去计数初值才是加1计数器的计数值。
设置为定时器模式时,加1计数器是对内部机器周期计数(1个机器周期等于12个振荡周期,即计数频率为晶振频率的1/12)。计数值乘以机器周期就是定时时间。
设置为计数器模式时,外部事件计数脉冲由T0或T1引脚输入到计数器。在每个机器周期的某个期间采样T0、T1引脚电平。当某周期采样到一高电平输入,而下一周期又采样到一低平时,则计数器加1,更新的计数值在下一个机器周期装入计数器。由于检测一个从1到0的下降沿需要2个机器周期,因此要求被采样的电平至少要维持一个机器周期。当晶振频率为12MHz 时,最高计数频率不超过6MHz(即计数脉冲的周期要大于2us)。
定时器0和定时器1是单片机中的两个定时器,它们可以用于产生定时中断。这两个定时器的控制寄存器(TCR和TCON)分别位于0x83和0x85。
6.1 定时器0和定时器1的控制寄存器:
* 定时器0的数据寄存器TH0和TL0位于0x8C和0x8A;
* 定时器1的数据寄存器TH1和TL1位于0x8D和0x8B。
6.2 例程分析:
本例程使用定时器0来控制LED以1Hz频率闪烁。首先,我们需要定义一个全局变量来计算定时器产生中断的次数。因为定时器的数据寄存器只有16位,最大数据范围只有65535,超过这个数据后就会从0重新开始计时。根据单片机的计数周期设置在1us,最大定时时间只有65.535ms。为了达到1s的闪烁时间,我们需要至少触发50次中断(假设每次中断间隔为1ms)。
6.2.1 原理图:
```
MCU +-------+ +-------+ +-------+
| | | | | |
| T0 |-------| LED |-------| | |
| | | | | |
+-------+------+ +-------+------+ +-------+------+
```
6.2.2 实现的功能:
使用定时器0,控制LED以1Hz频率闪烁。
6.2.3 源代码:
重点关注以下几行代码:
```c
// 第20行:定义了一个unsigned char的变量,为什么要定义这样一个全局变量。首先定时器的数据寄存器只有16位,也就是说最大数据范围只有65535,超过这个数据后就会从0重新开始计时,根据单片机的计数周期设置在1us,最大定时时间只有65.535ms,而达到1s是远远不够的,所以定义一个全局变量来计算定时器产生中断的次数,假设我们设置定时器50ms中断一次,那么,当进入20次中断,则意味着定时器刚好定时1s。
unsigned char count = 0; // 定义全局变量count,用于计算定时器产生中断的次数
```
这里用到了一条语句,LED = !LED。叹号代表取反,只能用于布尔型变量,所谓布尔型变量就是只有0和1两种状态,也就是1个二进制位。在C语言中,叹号代表二进制位取反,“~”则代表按位取反运算。例如有一个二进制位初值是1,取反的结果就是0。但是如果有一个字节0x8F,此时只能用按位取反运算,而不能用二进制位取反运算。0x8F按位取反的结果应该是0x70。例程中这条语句的含义就是LED二进制位取反后将结果重新赋值给LED变量。
第23行至第24行:这两行用于给定时器重新写入初值。因为51单片机的数据寄存器进入中断后就会从0开始重新计数。假设最开始设置的值是1000,进入中断后,定时的时间就是65535-1000+1=64536us。进入中断如果不设置初值,那么下一次进入中断时定时的时间就是65536us,与最初的时间误差是65536-64536=1000us。所以每次进入中断都需要给数据寄存器重新写入初值。
第42行至第43行:定时器在初始化的时候就要给写入初始值。为什么要写入这个初始值呢?首先数据寄存器是只能加1运算,从0加到65535。但是如果我们只想要定时50us就进入中断应该怎么处理呢?这就需要给定时器的数据寄存器先写入一个数,让定时器从这个数开始加1,加到65535刚好是50us。那么这个初值就是65535-50,这个定时的时间刚好就是50us。而/和%则是代表取整和取余。
注:取整与取余运算
(1)取整运算:用/表示,代表取除法运算中整数部分,例如2/3,得到的结果就是商为0且余数为2,此时取整运算得到的结果就是0;
(2)取余运算:用%表示,代表取除法运算中余数部分,例如2/3,得到的结果就是商为0且余数为2,此时取余运算得到的结果就是2。
更多信息可以来这里获取==>>电子技术应用-AET<<