定时器与数码管之定时器
时钟周期(T):是时序最小的时间单位,具体的计算方法是 1/时钟源频率
例如:我们单片机开发板上的晶振是11.0592M,那么对于我们这个单片机系统来说,时钟周期=1/11059200秒
机器周期:我们单片机完成一个操作的最短时间
机器周期主要是针对汇编语言而言,在汇编语言下程序的每一条语句执行所使用的时间都是机器周期的整数倍,而且语句占用的时间是可以计算出来的
而C语言一条语句是的时间是不确定的,受到诸多因素影响
51单片机系列,在其标准架构下一个机器周期是12个时钟周期
定时器和计数器是单片机内部的同一个模块,通过配置SFR(特殊功能寄存器)可以实现两种不同的功能
定时器就是用来定时的。
定时器内部有一个寄存器,我们让它开始计数后,这个寄存器的值没经过一个机器周期就会自动加1,因此,我们可以把机器周期理解为定时器的计数周期
溢出:钟表加到60之后,秒就会自动变成0
对于51单片机而言,溢出后,这个值会直接变成0
定时:从某一个初值开始,经过确定的时间后溢出
定时器的寄存器
标准的51单片机内部有T0和T1两个定时器(T是Timer的缩写)
对于单片机的每一个功能模块,都是由它的SFR,也就是特殊功能寄存器来控制
名称 | 描述 | SFR地址 | 复位值 |
TH0 | 定时器0高字节 | 0x8C | 0x00 |
TL0 | 定时器0低字节 | 0x8A | 0x00 |
TH1 | 定时器1高字节 | 0x8D | 0x00 |
TL1 | 定时器1低字节 | 0x8B | 0x00 |
TH0\TL0用于T0
TH1\TL1用于T1
位 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
符号 | TF1 | TR1 | TF0 | TR0 | IE1 | IT1 | IE0 | IT0 |
值 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
位 | 符号 | 描述 |
7 | TF1 |
定时器1溢出标志。 一旦定时器1发生溢出时硬件置1。 清零方式有两种: 软件清零,或者进入定时器中断时硬件清零 |
6 | TR1 |
定时器1运行控制位。 软件置位/清零来进行启动/停止定时器 |
5 | TF0 |
定时器0溢出标志。 一旦定时器0发生溢出时硬件置1。 清零方式有两种: 软件清零,或者进入定时器中断时硬件清零 |
4 | TR0 |
定时器0运行控制位。 软件置位/清零来进行启动/停止定时器 |
3 | IE1 | 外部中断部分,与定时器无关 |
2 | IT1 | |
1 | IE0 | |
0 | IT0 |
只要写到硬件置1或清0的,就是指一旦符合条件,单片机将自动完成动作。
只要写到软件置1或清0的,是指我们必须程序去完成这个动作。
对于TCON这个SFR
当我们在程序中写 TR1 = 1 以后,定时器就会每经过一个周期自动加1
当我们在程序中写 TR1 = 0 以后,定时器就会停止加1,其值会保持不变
TF1是一个标志位,它的作用是告诉我们定时器溢出了,仅仅只是给我们一个信号,让我们知道定时器溢出了,它不会对定时器是否继续运行产生任何影响
定时器有多种工作模式,工作模式的选择就由TMOD来控制
位 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
符号 | GATE(T1) | C/T(T1) | M1(T1) | M0(T1) | GATE(T0) | C/T(T0) | M1(T0) | M0(T0) |
复位值 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
符号 | 描述 |
T1/T0 |
在上表中 标T1的表示控制定时器1的位 标T0的表示控制定时器0的位 |
GATE |
该位被置1时为门控位。仅当“INTx”脚为高并且“TRx”控制位被置1时使能定时器“x”,定时器开始计时 当该位被清0时,只要“TRx”位被置1,定时器“x”就使能开始计时,不受到单片机引脚“INTx”外部信号干扰,常用来测量外部信号脉冲宽度。 |
C/T |
定时器或计数器选择位 该位被清0时用作定时器功能(内部系统时钟) 被置1时用作计时器功能 |
M1 | M0 | 工作模式 | 描述 |
0 | 0 | 0 |
兼容8084单片机的13位定时器 THn的8位和TLn的5位组成一个13位定时器 |
0 | 1 | 1 | THn和TLn组成一个16位定时器 |
1 | 0 | 2 |
8位自动重装模式 定时器溢出后THn重装到TLn中 |
1 | 1 | 3 | 禁用定时器1,定时器0变成2个8位定时器 |
TCON可位寻址,TMOD不可位寻址:
TCON有一个位叫TR1,我们可以在程序中直接进行 TR1 = 1 的操作
但是对TMOD里的位,比如 (T1)M1 = 1 这样的操作就是错误的,我们要操作就必须一次操作这整个字节,也就是必须一次性对TMOD所有位操作,不能对其中某一位单独进行操作
定时器有4种工作模式:
模式0
是为了兼容老的8048系列单片机而设计的,现在的51几乎是不会用到这种模式
模式3
该模式的功能模式2可完全取代
模式1
是THn和TLn组成了一个16位的定时器,计数范围是0-65535,溢出后,只要不对THn和TLn重新赋值,则从0开始计数
模式2
是8位自动重装在模式,只有TLn做加1计数,计数范围0-255,THn的值并不变化,而是保持原值,TLn溢出后,TFn就直接置1了,并且把THn原先的值赋值给TLn,然后TLn从新赋值的这个数字开始计数
这个功能可以用来产生串口的通信波特率
原理图分析
模式0
模式1
OSC框表示时钟频率,因为一个机器周期等于12个时钟周期,所以该示意图中 d 等于12
下边的 GATE 右边的那个门是一个非门电路,再右侧是一个或门,再往右是一个与门电路
下边的电路控制上边部分
TRn和下边的或门电路的结果进行与运算,若TRn为0,不管或门结果是啥,与运算结束都是0,所以如果要让定时器工作,则TRn必须置1
TRn置1后,与运算结果要想是1,则或门结果必须是1
GATE置0时,经过非门电路,则变成了1,此时不管INTn脚是什么值,经过或门结果都是1,定时器就会工作
GATE置1时,经过非门电路,则变成了0,此时INTn脚必须是1,或门结果才是1,定时器才能工作
要想让定时器工作,就是自动加1,从图上看有两种方式:
- 开关打到C/T=0的时候,一个机器周期TL就会加1一次[定时器功能]
- 开关打到C/T=1的时候,Tn引脚来一个脉冲,TL就加1一次[计数器功能]
模式2
模式3
定时器的应用
在使用定时器的时候,需要以下几个步骤:
- 设置特殊功能寄存器TMOD,配置好工作模式
- 设置计数寄存器THn和TLn的初值
- 设置TCON,通过TRn置1来让定时器开始计数
- 判断TCON寄存器的TFn位,检测定时器溢出的情况
计算定时器初值
板子的晶振的11.0592M
时钟周期:1/11059200
机器周期:12*时钟周期=12/11059200
假设定时20ms,即0.02秒
假设需要经过x个机器周期达到0.02秒,则x*(12/11059200)=0.02,则x=18432
16位定时器的溢出值是65536(65535时未溢出,+1才溢出,所以是65536)
初值+18432=65536,则初值为65536-18432=47104=0xB800
即THn=0xB8,TLn=0x00
示例代码
#include <reg52.h>
sbit LED = P0^0;
sbit ADDR0 = P1^0;
sbit ADDR1 = P1^1;
sbit ADDR2 = P1^2;
sbit ADDR3 = P1^3;
sbit ENLED = P1^4;
void main()
{
unsigned char cnt = 0; //定义一个计数变量,记录 T0 溢出次数
ENLED = 0; //使能 U3,选择独立 LED
ADDR3 = 1;
ADDR2 = 1;
ADDR1 = 1;
ADDR0 = 0;
TMOD = 0x01; //设置 T0 为模式 1
TH0 = 0xB8; //为 T0 赋初值 0xB800
TL0 = 0x00;
TR0 = 1; //启动 T0
while (1)
{
if (TF0 == 1) //判断 T0 是否溢出
{
TF0 = 0; //T0 溢出后,清零中断标志
TH0 = 0xB8; //并重新赋初值
TL0 = 0x00;
cnt++; //计数值自加 1
if (cnt >= 50) //判断 T0 溢出是否达到 50 次
{
cnt = 0; //达到 50 次后计数值清零
LED = ~LED; //LED 取反:0-->1、1-->0
}
}
}
}
小灯以0.5Hz的频率进行闪烁
本文来自博客园,作者:EricsT,转载请注明原文链接:https://www.cnblogs.com/EricsT/p/18456204