控制/MCU
6.1 51单片机定时器概述
6.1.1 定时器的描述
要实现定时功能,除了利用单片机内部的定时/计数器,也可以采用下面三种方法:
(1)软件定时:软件定时不占用硬件资源,但占用了CPU时间,降低了CPU的利用率。
(2)采用时基电路定时:例如采用555电路,外接必要的元器件(电阻和电容),即可构成硬件定时电路。但在硬件连接好以后,定时值与定时范围不能由软件进行控制和修改,即不可编程。
(3)采用可编程芯片定时:这种定时芯片的定时值及定时范围很容易用软件来确定和修改,此种芯片定时功能强,使用灵活。在单片机的定时/计数器不够用时,可以考虑进行扩展。
定时/计数器的实质是加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。
6.1.2 51单片机定时器结构
6.1 定时器中断相关寄存器
6.1.1 工作模式寄存器TMOD
寄存器地址:0x89
Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
GATE | C/T | M1 | M0 | GATE | C/T | M1 | M0 |
Bit 7:定时器1门控
0:关闭门控,只要TR1为1,就可以启动定时/计数器工作
1:开启门控,此时只有当TR1为1且外部中断引脚为高电平时,才能够启动定时器工作
Bit 6:定时器1工作模式选择
0:定时模式,时钟源来自MCU内部
1:计数模式,时钟源来自T1引脚上
Bit 5~Bit 4:定时器1计数模式选择
00:数据寄存器使用13位
01:数据寄存器使用16位
10:8位自动重装定时/计数器
11:T1停止计数
Bit 3:定时器0门控
0:关闭门控,只要TR0为1,就可以启动定时/计数器工作
1:开启门控,此时只有当TR0为1且外部中断引脚为高电平时,才能够启动定时器工作
Bit 2:定时器0工作模式选择
0:定时模式,时钟源来自MCU内部
1:计数模式,时钟源来自T0引脚上
Bit 1~ Bit 0:定时器0计数模式选择
00:数据寄存器使用13位
01:数据寄存器使用16位
10:8位自动重装定时/计数器
11:T0分成两个独立的8位定时/计数器
6.1.2 定时器0数据寄存器高字节TH0
寄存器地址:0x8C
Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
定时器0计数值高八位 |
6.1.3 定时器0数据寄存器低字节TL0
寄存器地址:0x8A
Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
定时器0计数值低八位 |
6.1.4 定时器1数据寄存器高字节TH1
寄存器地址:0x8D
Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
定时器1计数值高八位 |
6.1.5 定时器1数据寄存器低字节TL1
寄存器地址:0x8B
Bit 7 | Bit 6 | Bit 5 | Bit 4 | Bit 3 | Bit 2 | Bit 1 | Bit 0 |
定时器1计数值低八位 |
6.2 例程分析
6.2.1 原理图
6.2.2 实现的功能
使用定时器0,控制LED以1Hz频率闪烁。
6.2.3 源代码
重点关注以下几行代码:
第20行:定义了一个unsigned char的变量,为什么要定义这样一个全局变量。首先定时器的数据寄存器只有16位,也就是说最大数据范围只有65535,超过这个数据后就会从0重新开始计时,根据单片机的计数周期设置在1us,最大定时时间只有65.535ms,而达到1s是远远不够的,所以定义一个全局变量来计算定时器产生中断的次数,假设我们设置定时器50ms中断一次,那么,当进入20次中断,则意味着定时器刚好定时1s。
第28行:这里用到了一条语句,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。
全部0条评论
快来发表一下你的评论吧 !