5.1 定时器简单介绍
STC89C52 是一款基于 8051 架构的单片机,由 STC 微电子(STC Microelectronics)生产。它具有多个定时器/计数器模块,用于实现各种定时、计数和时间相关的功能。以下是关于 STC89C52 定时器的简要介绍:
5.1.1 定时器模块
STC89C52 单片机通常具有以下定时器模块:
- 定时器 0 和定时器 1:STC89C52 有两个可编程的 16 位定时器/计数器,类似于标准的 8051 架构。它们可以用于生成延时、产生周期性中断、计数外部事件等。
- 定时器 2:此单片机还附带一个额外的定时器 2,它是一个 8 位定时器,同时具有 PWM(脉宽调制)输出功能,可用于产生 PWM 波形,例如驱动电机。
5.1.2 工作模式
STC89C52 定时器的工作模式与标准 8051 架构的工作模式类似,包括以下几种:
- 工作方式 0(模式 0):16 位定时器/计数器,可配置为 8 位自动重装载模式,计数器溢出时会重新加载初值,可用于生成精确的定时。
- 工作方式 1(模式 1):16 位定时器/计数器,类似于模式 0,但可以由外部事件触发。
- 工作方式 2(模式 2):8 位定时器/计数器,可在定时器 2 中使用,还可以配置为产生 PWM 输出。
STC89C52 单片机的定时器模块为开发者提供了丰富的时间管理和控制能力。通过适当的编程,可以实现延时、周期性任务、PWM 生成等功能,满足不同应用场景的需求。定时器是嵌入式系统中重要的组成部分,为系统提供了时间相关的功能支持。
5.2 定时器寄存器分析
在 8051 单片机中,定时器 0 和定时器1是一个 16 位的定时器/计数器。以下是与 8051 单片机定时器 0 和定时器1相关的寄存器:
TMOD – Timer Mode Register
- 位 7-6 (GATE1, C/T1):用于选择定时器 1 的工作方式和计数源。
- 位 5-4 (GATE0, C/T0):用于选择定时器 0 的工作方式和计数源。
- 位 3-2 (M1T1, M1T0):定时器 1 的工作模式选择位。
- 位 1-0 (M0T1, M0T0):定时器 0 的工作模式选择位。
TL0 和 TH0 – Timer 0 Low Byte 和 High Byte
这两个寄存器组成定时器 0 的 16 位计数器。用于设置计数初值和获取计数结果。
TCON – Timer Control Register
- 位 7 (TF1):定时器 1 溢出标志。
- 位 6 (TR1):定时器 1 启停控制位。
- 位 5 (TF0):定时器 0 溢出标志。
- 位 4 (TR0):定时器 0 启停控制位。
- 位 3 (IE1):定时器 1 中断允许。
- 位 2 (IT1):外部中断 1 的触发方式选择。
- 位 1 (IE0):定时器 0 中断允许。
- 位 0 (IT0):外部中断 0 的触发方式选择。
IE – Interrupt Enable Register
- 位 7 (EA):总中断允许位。
- 位 4 (ET2):定时器 2 中断允许。
- 位 3 (ES):串口中断允许。
- 位 2 (ET1):定时器 1 中断允许。
- 位 1 (EX1):外部中断 1 允许。
- 位 0 (EX0):外部中断 0 允许。
IP – Interrupt Priority Register
用于设置各个中断的优先级。
在 8051 单片机中,定时器 2 是一个 8 位的定时器/计数器,同时也支持 PWM 输出功能。以下是与 8051 单片机定时器 2 相关的寄存器:
T2CON – Timer 2 Control Register
- 位 7 (TF2):定时器 2 溢出标志。
- 位 6 (EXF2):外部中断 2 标志。
- 位 5 (RCLK):串行数据输入选择。
- 位 4 (TCLK):串行数据输出选择。
- 位 3 (EXEN2):外部中断 2 控制。
- 位 2 (TR2):定时器 2 启停控制位。
- 位 1 (C/T2):定时器/计数器模式选择。
- 位 0 (CP/RL2):捕获/重装载模式选择。
RCAP2L 和 RCAP2H – Timer 2 Capture Registers Low Byte 和 High Byte
这两个寄存器用于设置定时器 2 的重载初值,控制计数范围。
TL2 和 TH2 – Timer 2 Low Byte 和 High Byte
这两个寄存器组成定时器 2 的 8 位计数器。
IE – Interrupt Enable Register
- 位 4 (ET2):定时器 2 中断允许。
IP – Interrupt Priority Register
用于设置各个中断的优先级。
使用定时器 2 作为串口波特率发生器
以下是计算波特率发生器初值的一般公式:
其中:
波特率分频
是一个与波特率相关的常数。对于常见的值如 9600 波特率,波特率分频为 32。T2工作时钟周期
是定时器 2 的时钟周期,对于 STC89C52 单片机,它与晶振频率有关。预分频值
是在 T2CON 寄存器中设置的预分频值,用于进一步分频。
以下是一个计算波特率发生器初值的示例:
假设您的晶振频率为 11.0592 MHz,要设置波特率为 9600 bps,预分频为 1(T2CON 中的预分频位设置为 0),则计算过程如下:
- 计算波特率分频:9600 bps 对应的波特率分频为 32。
- 计算 T2 工作时钟周期:T2 的时钟周期是晶振频率的倒数,即 1 / 11059200。
- 计算定时器初值:
因此,在这种情况下,您应该将 RCAP2L
设置为 0xE8,RCAP2H
设置为 0xFF,以实现 9600 bps 的波特率。
5.3 定时器0控制流水灯
/**********************************
包含头文件
**********************************/
#include <reg52.h>
#include <intrins.h> //因为要用到左右移函数_crol_(),所以加入这个头文件
/**********************************
参数定义
**********************************/
unsigned int time_1ms,time_1s; // 定义LED灯的初始状态,从最低位开始点亮
/**********************************
函数名: Time0init
传递参数: 无
返回参数: 无
函数作用: 定时器0初始化
**********************************/
void Time0init(void)
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0x66; //设置定时初始值
TH0 = 0xFC; //设置定时初始值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
EA = 1; //开启总中断
}
/**********************************
函数名: main
传递参数:无
返回参数:无
函数作用:主函数
**********************************/
void main(void)
{
char i=0;
Time0init();
P0=0xFE;
while(1)
{
if(time_1s<7) //变化七次之后跳出
{
if(time_1s!=i)
{
i=time_1s;
P0=_crol_(P0,1);//执行左移函数
}
}
else if(time_1s<14)//在变化其次跳出
{
if(time_1s!=i)
{
i=time_1s;
P0=_cror_(P0,1);//执行右移函数
}
}
else//清零归位
{
time_1s=0;
i=0;
}
}
}
/*定时器0中断服务函数*/
void Timer0_isr() interrupt 1
{
TL0 = 0x66; //设置定时初始值
TH0 = 0xFC; //设置定时初始值
time_1ms++;
if(time_1ms>500)
{
time_1ms=0;
time_1s++;
}
}
利用定时器0的中断函数来使得流水灯变化
5.4 数码管显示定时器的计数
/**********************************
包含头文件
**********************************/
#include "main.h"
#include "smgduan.h"
/**********************************
参数定义
**********************************/
unsigned int time_1ms=0,time_1s=0;
/**********************************
函数名: Time0init
传递参数: 无
返回参数: 无
函数作用: 定时器0初始化
**********************************/
void Time1init(void)
{
TMOD = 0x10; //设置定时器模式
TH1=0XFC; //给定时器赋初值,定时1ms
TL1=0X18;
TR1 = 1;
ET1 = 1;
EA = 1; //开启总中断
}
/**********************************
函数名: usleep
传递参数: ms
返回参数: 无
函数作用: 延时1ms函数
**********************************/
void usleep(unsigned int ms)
{
unsigned int m,n;
for(m=ms;m>0;m--)
for(n=110;n>0;n--);
}
/**********************************
函数名: main
传递参数:无
返回参数:无
函数作用:主函数
**********************************/
void main(void)
{
Time1init();
while(1)
{
ThereDisplay(time_1s);
}
}
/*定时器0中断服务函数*/
void Timer1_isr() interrupt 3
{
TH1=0XFC; //给定时器赋初值,定时1ms
TL1=0X18;
time_1ms++;
if(time_1ms>1000)
{
time_1ms=0;
time_1s++;
}
}
利用定时器1的16位计数器撰写的程序。
5.5 定时器产生PWM
/**********************************
包含头文件
**********************************/
#include <reg52.h>
#include <intrins.h> //因为要用到左右移函数_crol_(),所以加入这个头文件
/**********************************
定义引脚
**********************************/
sbit LED=P3^4;
/**********************************
参数定义
**********************************/
unsigned int led_light=0; // 计数变量
unsigned char light=0; // 亮度一共10级
/**********************************
函数名: Time0init
传递参数: 无
返回参数: 无
函数作用: 定时器0初始化
**********************************/
void Time0init(void)
{
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0x66; //设置定时初始值
TH0 = 0xFC; //设置定时初始值
ET0 = 1; //清除TF0标志
TR0 = 1; //定时器0开始计时
EA = 1; //开启总中断
}
/**********************************
函数名: main
传递参数:无
返回参数:无
函数作用:主函数
**********************************/
void main(void)
{
Time0init();
while(1)
{
light=1;
}
}
/*定时器0中断服务函数*/
void Timer0_isr() interrupt 1
{
TL0 = 0x66; //设置定时初始值
TH0 = 0xFC; //设置定时初始值
led_light++;
if(led_light >= 10) led_light = 0; //为LED灯PWM信号产生一个周期
LED = (led_light < light)?0:1; //三目运算符,确定LED状态
}
5.6 定时器的重要性分析
- 精确的时间控制: 定时器允许程序员精确地控制时间间隔,这对于许多应用非常关键。无论是实现精确的延时、定时任务还是时间测量,定时器都是不可或缺的。
- 定时中断: 定时器可以生成中断,允许程序在特定时间点执行特定的代码。这对于实时任务、数据采集和处理等应用非常重要。通过中断,可以及时响应外部事件或执行周期性任务。
- PWM(脉冲宽度调制)控制: 定时器可以用于生成PWM信号,用于控制电机、LED亮度、音频输出等。这种精确的信号控制在嵌入式系统中广泛应用。
- 计数器功能: 定时器可以用作计数器,用于计算外部事件的频率、脉冲数量等。这对于测量和监控应用非常有用。
- 节省能源: 定时器可以用于定时唤醒或休眠单片机,以节省能源。这对于电池供电的应用和功耗敏感的系统至关重要。
- 多定时器的多任务支持: 大多数51单片机都配备了多个定时器,允许同时管理多个定时任务,提高系统的多任务处理能力。
暂无评论内容