5.1  定时器简单介绍

STC89C52 是一款基于 8051 架构的单片机,由 STC 微电子(STC Microelectronics)生产。它具有多个定时器/计数器模块,用于实现各种定时、计数和时间相关的功能。以下是关于 STC89C52 定时器的简要介绍:

5.1.1 定时器模块

STC89C52 单片机通常具有以下定时器模块:

  1. 定时器 0 和定时器 1:STC89C52 有两个可编程的 16 位定时器/计数器,类似于标准的 8051 架构。它们可以用于生成延时、产生周期性中断、计数外部事件等。
  2. 定时器 2:此单片机还附带一个额外的定时器 2,它是一个 8 位定时器,同时具有 PWM(脉宽调制)输出功能,可用于产生 PWM 波形,例如驱动电机。

5.1.2 工作模式

STC89C52 定时器的工作模式与标准 8051 架构的工作模式类似,包括以下几种:

  1. 工作方式 0(模式 0):16 位定时器/计数器,可配置为 8 位自动重装载模式,计数器溢出时会重新加载初值,可用于生成精确的定时。
  2. 工作方式 1(模式 1):16 位定时器/计数器,类似于模式 0,但可以由外部事件触发。
  3. 工作方式 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 作为串口波特率发生器

以下是计算波特率发生器初值的一般公式:

定时器初值 = (65536 - (波特率分频 * T2工作时钟周期)) + 预分频值

其中:

  • 波特率分频 是一个与波特率相关的常数。对于常见的值如 9600 波特率,波特率分频为 32。
  • T2工作时钟周期 是定时器 2 的时钟周期,对于 STC89C52 单片机,它与晶振频率有关。
  • 预分频值 是在 T2CON 寄存器中设置的预分频值,用于进一步分频。

以下是一个计算波特率发生器初值的示例:

假设您的晶振频率为 11.0592 MHz,要设置波特率为 9600 bps,预分频为 1(T2CON 中的预分频位设置为 0),则计算过程如下:

  1. 计算波特率分频:9600 bps 对应的波特率分频为 32。
  2. 计算 T2 工作时钟周期:T2 的时钟周期是晶振频率的倒数,即 1 / 11059200。
  3. 计算定时器初值:
定时器初值 = (65536 - (32 * (1 / 11059200))) + 0 = 65464

因此,在这种情况下,您应该将 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  定时器的重要性分析

  1. 精确的时间控制: 定时器允许程序员精确地控制时间间隔,这对于许多应用非常关键。无论是实现精确的延时、定时任务还是时间测量,定时器都是不可或缺的。
  2. 定时中断: 定时器可以生成中断,允许程序在特定时间点执行特定的代码。这对于实时任务、数据采集和处理等应用非常重要。通过中断,可以及时响应外部事件或执行周期性任务。
  3. PWM(脉冲宽度调制)控制: 定时器可以用于生成PWM信号,用于控制电机、LED亮度、音频输出等。这种精确的信号控制在嵌入式系统中广泛应用。
  4. 计数器功能: 定时器可以用作计数器,用于计算外部事件的频率、脉冲数量等。这对于测量和监控应用非常有用。
  5. 节省能源: 定时器可以用于定时唤醒或休眠单片机,以节省能源。这对于电池供电的应用和功耗敏感的系统至关重要。
  6. 多定时器的多任务支持: 大多数51单片机都配备了多个定时器,允许同时管理多个定时任务,提高系统的多任务处理能力。

发表回复

后才能评论