🟥振荡周期:为单片机提供定时信号的振荡源的周期(晶振周期或外加振荡周期),振荡周期又称时钟周期。
🟧状态周期:2个振荡周期为一个状态周期,用S表示。
🟨机器周期:1个机器周期含6个状态周期,12个振荡周期。
🟩指令周期:完成1条指令所占用的全部时间,它以机器周期为单位。
定时值存储寄存器[存储定时器的计数值]
标准的51单片机内部有T0和T1两个定时器。
TH0/TL0用于T0,TH1/TH1用于T1
名称 | 描述 | SFR地址 | 复位值 |
---|---|---|---|
TH0 | 定时器0高字节 | 0x8C | 0x00 |
TL0 | 定时器0低字节 | 0x8A | 0x00 |
TH1 | 定时器1高字节 | 0x8D | 0x00 |
TL1 | 定时器1低字节 | 0x8B | 0x00 |
TCON-定时器控制寄存器的位分配(地址0x88、可位寻址)
位 | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
---|---|---|---|---|---|---|---|---|
符号 | TF1 | TR1 | TF0 | TR0 | IE1 | IT1 | IE0 | IT0 |
复位值 | 0 | 0 | 0 | 0 | 0 | 0 | 0 | 0 |
TCON-定时器控制寄存器的位描述
位 | 符号 | 描述 |
---|---|---|
7 | TF1 | 定时器1溢出标志。一旦定时器1发生溢出时硬件置1。清零有两种方式:软件清零或者进入定时器中断时硬件清零 |
6 | TR1 | 定时器1运行控制位。软件置位/清零来进行启动/停止定时器 |
5 | TF0 | 定时器0溢出标志。一旦定时器0发生溢出时硬件置1。清零有两种方式:软件清零或者进入定时器中断时硬件清零 |
4 | TR0 | 定时器0运行控制位。软件置位/清零来进行启动/停止定时器 |
3 | IE1 | 外部中断部分,与定时器无关 |
2 | IT1 | 外部中断部分,与定时器无关 |
1 | IE0 | 外部中断部分,与定时器无关 |
0 | IT0 | 外部中断部分,与定时器无关 |
TMOD-定时器模式寄存器的位分配(地址0x89、不可位寻址)
位 | 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 |
TMOD-定时器模式寄存器的位描述
符号 | 描述 |
---|---|
T1/T0 | T1 表示控制定时器1的位,T0 表示控制定时器0的位 |
GATE | 该位被置1时为门控位。仅当INTx 引脚为高并且TRx 控制位被置1时使能定时器x,定时器开始计时,当该位被清零时,只要TRx 位被置1,定时器x就使能开始计时,不受到单片机引脚INTx 外部信号的干扰,常用来测量外部信号脉冲宽度 |
C/T | 定时器或计数器选择位。该位被清零时用作定时器功能(内部系统时钟),被置1用作计数器功能 |
TMOD-定时器模式寄存器M1/M0工作模式
M1 | M0 | 工作模式 | 描述 |
---|---|---|---|
0 | 0 | 0 | 兼容8048单片机的13位定时器,THn 的8位和TLn 的5位组成一个13位定时器 |
0 | 1 | 1 | THn 和TLn 组成一个16位的定时器 |
1 | 0 | 2 | 8位自动重装模式,定时器溢出后THn 重装到TLn 中 |
1 | 1 | 3 | 禁用定时器1,定时器0变成两个8位定时器 |
⭕使用定时器的时候,需要以下几个步骤:
第一步:设置特殊功能寄存器TMOD
,配置好工作模式
第二步:设置计数寄存器TH0
和TL0
的初值
第三步:设置TCON
,通过TR0
置1来让定时器开始计数
第四步:判断TCON
寄存器的TF0
位,监测定时器溢出情况
计算如何用定时器定时:
例如晶振是11.0592MHz,那时钟周期就是1/11059200,机器周期是12/11059200,假如要定时20ms,也就是0.02秒,要经过x个机器周期得到0.02秒,则计算公式为:x*12/11059200=0.02,解得x=18432。
16位定时器的溢出值为65536(因65535再加1才是溢出),于是先给TH0
和TL0
一个初始值,让它们经过18432个机器周期后刚好达到65536,也就是溢出,溢出后可以通过检测TF0
的值可知,就刚好是0.02秒。那么初值y=65536-18432=47104,转成16进制便是0xB800,也就是TH0=0xB8,TL0=0x00。
/*单个led灯闪烁,延时一秒*/
#include "reg52.h"
typedef unsigned char u8;
sbit led=P0^0;
void main()
{
u8 cnt = 0; //定义一个计数变量,记录T0溢出次数
TMOD = 0x01; //设置T0为模式1
TH0 = 0xB8; //为T0赋初值 0xB800
TL0 = 0x00;
TR0 = 1; //启动T0
while(1)
{
if(TF0 == 1) //判断T0是否溢出
{
TF0 = 0; //T0溢出后,清0中断标志
TH0 = 0xB8; //并重新赋初值
TL0 = 0x00;
cnt++; //计数值自加1
if(cnt >= 50) //判断T0溢出是否达到50次
{
cnt = 0; //达到50次后计数值清0
led = ~led;
}
}
}
}
/*定时器0实现流水灯左右移动*/
#include "reg52.h"
typedef unsigned char u8;
typedef unsigned int u16;
unsigned char water_led1[8]={0xfe,0xfd,0xfb,0xf7,0xef,0xdf,0xbf,0x7f};
unsigned char water_led2[8]={0x7f,0xbf,0xdf,0xef,0xf7,0xfb,0xfd,0xfe};
void timer()
{
TMOD = 0x01;
TH0 = 0xB8;
TL0 = 0x00;
TR0 = 1;
}
void main()
{
u8 i = 0;
u8 cnt = 0;
timer();
while(1)
{
if(TF0 == 1)
{
TF0 = 0;
TH0 = 0xB8;
TL0 = 0x00;
cnt++;
if(cnt >= 50)
{
cnt = 0;
if(i < 8)
P1 = water_led1[j]; //正向流动
if(i >= 8)
P1 = water_led2[j-8]; //反向流动
i++;
if(i == 16)
i = 0;
}
}
}
}
/*静态数码管,每隔一秒显示一个数字*/
#include "reg52.h"
typedef unsigned char u8;
typedef unsigned int u16;
unsigned char smg[16]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,0x88,0x83,0xc6,0xa1,0x86,0x8e};
void timer()
{
TMOD = 0x01;
TH0 = 0xB8;
TL0 = 0x00;
TR0 = 1;
}
void main()
{
u8 i = 0;
u8 cnt = 0;
timer();
while(1)
{
if(TF0 == 1)
{
TF0 = 0;
TH0 = 0xB8;
TL0 = 0x00;
cnt++;
if(cnt >= 50)
{
cnt = 0;
P0 = smg[i];
i++;
if(i >= 16)
{
i = 0;
}
}
}
}
}