前言
51单片机定时计数器使用简介
TMOD
工作方式控制寄存器
TMOD
是一个8位寄存器,不支持位寻址,地址为0xA8
,每一位的定义如下:
名称 | 地址 | 说明 |
---|---|---|
GATE1 | B7 | 定时计数器1门控位,为0时T1只受TR1控制,为1时同时受INT1引脚电平和TR1控制 |
C/T1 | B6 | 定时计数方式选择位,为0时为定时器,为1时为计数器 |
M1 | B5 | T1工作方式选择位,联合M0使用,支持4种工作方式 |
M0 | B4 | 同上 |
GATE0 | B3 | 定时计数器0门控位,为0时T0只受TR0控制,为1时同时受INT0引脚电平和TR0控制 |
C/T2 | B2 | 定时/计数方式选择位,为0时为定时器,为1时为计数器 |
M1 | B1 | T0工作方式选择位,联合M0使用,支持3种工作方式 |
M0 | B0 | 同上 |
TMOD
不支持位寻址,只能8位一起赋值
例如,需要将T1设为定时器,工作方式设为2,代码为TMOD = 0x60
(0110 0000)
下面的
x
代表1或者0
GATEx
说明:- 为0时:当
TRx
为1时,定时计数器Tx
启动,当TRx
为0时定时计数器Tx
停止 - 为1时:当
TRx
为1并且INTx
引脚为高电平时,定时计数器Tx
启动,其余情况定时计数器Tx
停止
*C/Tx
说明:
- 为0时,
Tx
为定时器,每经过一个机器周期,数据寄存器加1,数据寄存器保存的数值溢出时,由硬件将TFx
置1,产生Tx
中断 - 为0时,
Tx
为计数器,每当引脚P3.4
(T0),和引脚P3.5
(T1)收到一次负脉冲信号(1->0->1)时,数据寄存器加1,数据寄存器保存的数值溢出时,由硬件将TFx
置1,产生Tx
中断
机器周期:与外部时钟频率有关,等于外部时钟频率的1/12。例如外部时钟为12MHz,那一个机器周期就为1μs,此时如果
T0
在工作方式2下,只需把TH0
设为0XFC
,把TL0
设为0x17
,即可每1ms(1000μs)产生一次T0
中断。
M0
,M1
说明:
这两个位用来设置定时计时器Tx
的工作方式
M1 | M0 | 工作方式 | 说明 |
---|---|---|---|
0 | 0 | 方式0 | 13位定时器/计数器 |
0 | 1 | 方式1 | 16位定时器/计数器 |
1 | 0 | 方式2 | 8位定时器/计数器,自动重载 |
1 | 1 | 方式3 | 8位定时器/计数器,T0被拆成两个独立的8位的定时计数器,T1没有工作方式3 |
TH0
TL0
TH1
TL1
数据寄存器
TH0
TL0
TH1
TL1
都是8位寄存器,不支持位寻址,H
代表高,L
代表低,当合并使用的时候,THx
做前8位,TLx
做后8位。- 因为硬件会在数据寄存器产生溢出时将
TFx
置1,所以只要控制THx
和TLx
的初始值,就能控制定时时间,或者计数次数。 - 在工作方式0和工作方式1中,
THx
和TLx
被拼起来当做一个更大的寄存器使用,优点是计时或者计数的范围更大了,缺点是需要在中断服务子程序里手动为THx
和TLx
赋值。 - 在工作方式2中,
THx
存放一个常量,当产生Tx
中断时,THx
会自动赋值给TLx
,这就是自动重载
,优点是不用手动为THx
和TLx
赋值,缺点是计时或者计数范围非常小 - 在工作方式3中,
T0
被切分成TH0
和TL0
2个独立的8位计数器,TR0
和TF0
分配给TL0
,TR1
和TF1
分配给TH0
,T1
停止工作,TH1
和TL1
保持其中的数据。
例程,使用T0
输出方波
#include <AT89X51.h>
//初始化T0的函数,51单片机时钟频率设为12MHz
void initT0(void)
{
TMOD = 0x01; //0000 0001,T0为计时器,工作方式1
TH0 = 0x27; //设定定时器周期为10ms
TL0 = 0x10; //0x2710 = 65535 - 10000
EA = 1;
ET0 = 1; //开启T0中断
TR0 = 1; //启动T0
}
//T0中断服务子函数
void Timer0Interrupt(void) interrupt 1
{
TH0 = 0x27; //重新设定数据寄存器的初始值
TL0 = 0x10;
P2 = ~P2; //P2引脚电平翻转
}
//主程序
int main(void)
{
initT0(); //初始化T0
for (;;) //让主线程死循环
{
}
}
本文链接:https://blog.chrxw.com/archives/2020/04/07/1180.html
转载请保留本文链接,谢谢
2 条评论
楼主,T1为定时器不应该是TMOD = 0X20(0010 0000)吗?
确实写错了……