51单片机嵌入式开发:6、 STC89C52RC 定时器0-1-2-看门狗 操作

STC89C52RC 定时器0-1-2-看门狗 操作

  • [1 定时器介绍](#1 定时器介绍)
    • [1.1 定时器概述](#1.1 定时器概述)
    • [1.2 课程思路](#1.2 课程思路)
  • [2 定时器类型](#2 定时器类型)
    • [2.1 定时器0、1](#2.1 定时器0、1)
    • [2.2 定时器2](#2.2 定时器2)
    • [2.3 看门狗定时器](#2.3 看门狗定时器)
    • [2.4 中断介绍](#2.4 中断介绍)
  • [3 定时器操作](#3 定时器操作)
    • [3.1 定时器0操作](#3.1 定时器0操作)
    • [3.2 定时器1操作](#3.2 定时器1操作)
    • [3.3 定时器2操作](#3.3 定时器2操作)
    • [3.4 看门狗定时器操作](#3.4 看门狗定时器操作)
  • [4 定时器总结](#4 定时器总结)

1 定时器介绍

1.1 定时器概述

单片机定时器是一种在嵌入式系统中常见的硬件模块,用于生成精确的时间延迟和时间计数。它通常由一个计数器和一些相关的控制寄存器组成,可以用来实现各种定时和计时功能。

定时器在单片机中的应用非常广泛,包括测量时间间隔、产生精确的时间延迟、生成脉冲和周期性触发等。通过配置定时器的计数器和相关参数,可以满足各种实时应用的需求。

以下是单片机定时器的一般概述:

  1. 定时器计数器:定时器的核心是一个计数器,它可以递增或递减。计数器的值可以用来表示经过的时间或者计数的次数,取决于定时器的工作模式。
  2. 定时器工作模式:定时器可以以不同的工作模式运行,以满足不同的应用需求。常见的模式包括定时模式、计数模式、输入捕获模式和输出比较模式。
    • 定时模式:定时器按照设定的时间间隔进行计数,并在计数到一定值时触发中断或执行某个操作。
    • 计数模式:定时器按照外部事件的触发进行计数,可以用来计数外部信号的脉冲数量或频率。
    • 输入捕获模式:定时器可以捕获外部事件的时间戳,用于测量时间间隔或频率。
    • 输出比较模式:定时器可以与一个或多个输出引脚关联,当计数器的值与设定的比较值相等时,可以触发输出操作。
  3. 定时器预分频器:定时器通常具有一个可配置的预分频器,用于将系统时钟分频以降低计数速度。预分频器的设置可以影响定时器的分辨率和范围。
  4. 中断和事件触发:定时器可以配置为在计数达到某个特定值时触发中断,以便处理时间敏感的任务。此外,定时器还可以触发其他硬件或软件事件,以实现特定的功能。
  5. 寄存器配置:通过写入特定的寄存器,可以配置定时器的工作模式、计数器初始值、预分频器设置和比较值等参数。

1.2 课程思路

定时器章节我们围绕定时器不同的类型及用途,分别进行展开介绍。

2 定时器类型

2.1 定时器0、1

模式定义:

(1)模式0:

★模式0是选择定时器(T0或T1)高8位加低5位的---个13位定时器/计数器。

★在这种模式下,16寄存器(TH0和TL0)只用13位,其中TL0的高3位末用,其余位占整个13位的低5位,TH0占高8位。

★当TL0的低5位溢出时向TH0进位而TH0溢出时向中断标志位TF0进位(硬件置位TF0),并申请中断。

★ T0溢出否可查询TF0是否置位,以产生T0中断。

★ C/T=0时,控制开关接通振荡器十二分频输出端,就是定时工作方式。其定时时间为:

t=(213一T0初值)×振荡周期×12

★当C/T=1时,控制开关使引脚T0(P3.4)与13位计数器相连,外部计数脉冲由引脚T0〔P3.4〕输入,当外部信号电平发生"1"到"0"跳变时.计数器加1,这时,T0成为外部事件计数器。这就是计数工作方式。

★ GATE=0时,使或门输出A点电位为常"1",或门被封锁,于是,引脚INT0输入信号无效。这时或门输出的常"1"打开与门,B点电位取决于TR0状态,于是由TR0一位就可控制计数开关K开启或关断T0。

若软件使TR0置1,便接通计数开关K,启动T0在原值上加1计数,直至溢出。溢出时,13位寄存器清0,TF0置位,并申请中断,T0仍从0重新开始计数。

若TR0=0。则关断计数开关K,停止计数。

★当GATE =1时,A点电位取决于(P3.4)引脚的输入电平。仅当(P3.4)输入高电平时TR0=l时,B点才是高电平,计数开关K闭合T0开始计数,当INT0由1变0时,T0停止计数。这一特性可以用来测量在(P3.4)端出现的正脉冲的宽度。

(2)模式1

★该模式是一个16位定时器/计数器。

其结构与操作几乎与模式0完全相同,唯一的差别是:在模式1中,寄存器TH0和TL0是以全16位参与操作,

★用于定时工作方式时,定时时间为:

t=(216一T0初值) ×时钟周期×12

★用于计数工作方式时,计数长度为216=65536(个外部脉冲)

(3)模式2

★模式2把T0(或T1)配置成---个可以自动重装载的8位定时器/计数器。

★ TL0计数溢出时,不仅使溢出中断标志位TF0置1,而且还自动把TH0中的内容重装载到TL0中。

★这时16位的计数器被拆成两个8位;

TL0用作8位计数器,TH0用以保持初值。

★在程序初始化时,TL0和TH0由软件赋予相同的初值。

★---旦TL0计数溢出,置位TF0,并将TH0中的初值再自动装入TL0,继续计数,循环重复。

★用于定时器工作方式时,其定时时间(TF0溢出周期)为;

t=(28---TH0初值)×振荡周期×12

★用于计数器工作方式时,最大计数长度(TH0初值=0)为:

28=256(个外部脉冲)。

★这种工作方式可省去用户软件中重装常数的程序,并可产生相当精度的定时时间。特别适用作串行口波待率发生器。

(4)模式3

★操作模式3对T0和T1是大不相同的。

★若将T0设置为模式3,TL0和TH0被分成为两个互相独立的8位计数器。

其中TL0用原T0的各控制位、引脚和中断源。即C/T、GATE、TR0、TF0和T0 (P3.4)引脚、 (P3.2)引脚。

★ TL0除仅用8位寄存器外,其功能和操作与模式0(13位计数器)、模式1(16位计数器)完全相同。

TL0也可工作为定时器方式或计数器方式。

★ TH0只可用作简单的内部定时功能,它占用了定时器T1的控制位TR1和T1的中断标志位TF1,其启动和关闭仅受TRl的控制。

★ 定时器T1无操作模式3状态。

2.2 定时器2

定时器 2 定时器 2 是一个 16 位定时/计数器,它既可以做定时器,又可以做事件计数器。其工作 方式由特殊寄存器 T2CON 中的 C/T2 位选择(如表 2 所示)。定时器 2 有三种工作模式: 捕捉方式、自动重载(向下或向上计数)和波特率发生器。如表 3 所示,工作模式由 T2CON 中的相关位选择。定时器 2 有 2 个 8 位寄存器:TH2 和 TL2。在定时工作方式 中,每个机器周期,TL2 寄存器都会加 1。由于一个机器周期由 12 个晶振周期构成, 因此,计数频率就是晶振频率的 1/12。

2.3 看门狗定时器

2.4 中断介绍

TC89C52是一款常用的单片机型号,它基于8051内核,并具有一些扩展的功能和特性。以下是关于STC89C52中断的介绍:

  1. 中断源:STC89C52支持多种中断源,包括外部中断、定时器中断、串口中断和其他特定硬件中断。具体的中断源数量和类型取决于单片机的具体型号和配置。
  2. 中断向量表:STC89C52使用中断向量表来管理中断服务例程。中断向量表是一组特定的内存地址,每个地址对应一个中断源的中断服务例程入口点。当中断触发时,单片机会根据中断源的标识符查找相应的中断向量表地址,并跳转到对应的中断服务例程。
  3. 中断优先级:STC89C52支持中断优先级的设置,以决定各个中断源的触发顺序和优先级。具有更高优先级的中断源将在较低优先级的中断源之前得到处理。中断优先级可以通过设置特定的寄存器来实现,通常是通过IP(Interrupt Priority)寄存器来配置。
  4. 中断控制和使能:STC89C52提供了相关的寄存器用于控制和使能中断。例如,EA(全局中断使能)位用于启用或禁用所有中断,INT0、INT1等位用于控制特定外部中断的使能,定时器相关寄存器用于配置定时器中断等。
  5. 中断服务例程(ISR):对于每个中断源,需要编写相应的中断服务例程来处理中断事件。中断服务例程应位于中断向量表所指定的地址处,它们负责执行与中断相关的任务和操作。在中断服务例程中,可以执行特定的代码、读取和处理相关寄存器、更新状态等。
  6. 中断返回:在STC89C52中,中断服务例程的返回是通过执行中断返回指令(RETI)来实现的。RETI指令会将程序的执行流程返回到中断触发的地方,并继续执行主程序的下一条指令。
    中断寄存器介绍:

3 定时器操作

工程创建,在原有工程基础上,增加C51_TIMER.C和C51_TIMER.h,并在includes.h中引用头文件C51_TIMER.h。

借用流水灯程序需要将计时函数去掉。

c 复制代码
/********************************************************
函数名称:sys_led_test
函数功能:led流水灯
入口参数:
出口参数:
修    改:
内    容:
********************************************************/
void sys_led_test1(void)
{
//	delay(30000);//延时程序
	P1<<=1;      //左移一位 该语句等效于 P1=P1<<1
	P1|=0x01;    //最后一位补1,该语句等效于 P1=P1|0x01 符号"|"表示"或"
	if(P1==0xff) //检测是否移到最左端?"=="表示检测符号2端的值是否相等
	{ 
//		delay(30000);
		P1=0xfe; //重新赋值
	}
}

3.1 定时器0操作

根据定时器0的模式,我们选择16位寄存器模式:在主程序中引用初始化函数

C51_TIMER.C:

c 复制代码
#include "includes.h"


/*------------------------------------------------
                    定时器初始化子程序
------------------------------------------------*/
void sys_timer0_init(void)
{
	TMOD |= 0x01;	  //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响		     
	TH0=0x00;	      //给定初值,这里使用定时器最大值从0开始计数一直到65535溢出
	TL0=0x00;
	EA=1;            //总中断打开
	ET0=1;           //定时器中断打开
	TR0=1;           //定时器开关打开
}


/*------------------------------------------------
                 定时器中断子程序
------------------------------------------------*/
void Timer0_isr(void) interrupt 1 using 1
{
	TH0=0x00;		  //重新赋值
	TL0=0x00;

	sys_led_test1(); //流水灯操作
}

C51_TIMER.h中:

c 复制代码
#ifndef __C51_TIMER_H__
#define __C51_TIMER_H__

extern void sys_timer0_init(void);
extern void Timer0_isr(void);

#endif

protues仿真图,指示灯在闪烁:

3.2 定时器1操作

c 复制代码
操作同定时器0一样,不过我们选择模式2,TH重装在给TL。



#include "includes.h"


/*------------------------------------------------
                    定时器初始化子程序
------------------------------------------------*/
void sys_timer0_init(void)
{
	TMOD |= 0x01;	  //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响		     
	TH0=0x00;	      //给定初值,这里使用定时器最大值从0开始计数一直到65535溢出
	TL0=0x00;
	//EA=1;            //总中断打开 等最后一个中断打开
	ET0=1;           //定时器中断打开
	TR0=1;           //定时器开关打开
}

/*------------------------------------------------
                    定时器初始化子程序
------------------------------------------------*/
void sys_timer1_init(void)
{
	TMOD |= 0x20;	  //使用模式2,	     
	TH1=0x05;	      //给定初值,这里使用定时器最大值从5开始计数一直到255溢出
	TL1=0x00;
	EA=1;            //总中断打开
	ET1=1;           //定时器中断打开
	TR1=1;           //定时器开关打开
}



/*------------------------------------------------
                 定时器中断子程序
------------------------------------------------*/
void Timer0_isr(void) interrupt 1 using 1
{
	TH0=0x00;		  //重新赋值
	TL0=0x00;

	//sys_led_test1(); //流水灯操作
}


/*------------------------------------------------
                 定时器中断子程序
------------------------------------------------*/
void Timer1_isr(void) interrupt 3 using 1
{

	sys_led_test1(); //流水灯操作
	
}	![

Protues 仿真效果。

3.3 定时器2操作

c 复制代码
#include "includes.h"


/*------------------------------------------------
                    定时器初始化子程序
------------------------------------------------*/
void sys_timer0_init(void)
{
	TMOD |= 0x01;	  //使用模式1,16位定时器,使用"|"符号可以在使用多个定时器时不受影响		     
	TH0=0x00;	      //给定初值,这里使用定时器最大值从0开始计数一直到65535溢出
	TL0=0x00;
	//EA=1;            //总中断打开 等最后一个中断打开
	ET0=1;           //定时器中断打开
	TR0=1;           //定时器开关打开
}

/*------------------------------------------------
                    定时器初始化子程序
------------------------------------------------*/
void sys_timer1_init(void)
{
	TMOD |= 0x20;	  //使用模式2,	     
	TH1=0x05;	      //给定初值,这里使用定时器最大值从5开始计数一直到255溢出
	TL1=0x00;
	//EA=1;            //总中断打开
	ET1=1;           //定时器中断打开
	TR1=1;           //定时器开关打开
}


/*------------------------------------------------
                    定时器初始化子程序
------------------------------------------------*/
void sys_timer2_init(void)
{
  RCAP2H = 0/256;//
  RCAP2L = 0/256;
  ET2=1;                     //打开定时器中断
  EA=1;                      //打开总中断
  TR2=1;                     //打开定时器开关
}


/*------------------------------------------------
                 定时器中断子程序
------------------------------------------------*/
void Timer0_isr(void) interrupt 1 using 1
{
	TH0=0x00;		  //重新赋值
	TL0=0x00;

	//sys_led_test1(); //流水灯操作
}


/*------------------------------------------------
                 定时器中断子程序
------------------------------------------------*/
void Timer1_isr(void) interrupt 3 using 1
{

	//sys_led_test1(); //流水灯操作
	
}	




/*------------------------------------------------
                 定时器中断子程序
------------------------------------------------*/
void Timer2_isr(void) interrupt 5 using 1//定时器2中断
{
    TF2=0;
    sys_led_test1(); //流水灯操作
}

3.4 看门狗定时器操作

根据看门狗寄存器的说明:

手册中有介绍:

看门狗用protues无法仿真,所以我在开发板上验证可以成功,根据自己的需要配置PS0、1、2即可。

c 复制代码
void sys_wdog_init(void)
{ 
	WDT_CONTR = 0x35;
}

void clr_wdg(void)
{
	WDT_CONTR = 0x35;
}
c 复制代码
看门狗用protues无法仿真,所以我在开发板上验证可以成功,根据自己的需要配置PS0、1、2即可。
void sys_wdog_init(void)
{ 
	WDT_CONTR = 0x35;
}

void clr_wdg(void)
{
	WDT_CONTR = 0x35;
}

4 定时器总结

单片机定时器在嵌入式系统中有广泛的应用,以下是一些常见的用途:

  1. 时间测量和延时:定时器可以用于测量时间间隔或产生指定的时间延迟。例如,可以使用定时器来测量外部事件的持续时间,或者生成精确的时间延迟,用于控制设备的动作或执行特定的任务。
  2. 脉冲和频率计数:定时器可以用于计数外部信号的脉冲数量或频率。这对于测量传感器信号、计算输入信号的频率或周期以及进行频率调制等应用非常有用。
  3. 定时中断:定时器可以配置为在计数到达指定值时触发中断。这对于实现实时任务和时间敏感的操作非常重要。例如,可以使用定时中断来定期执行某个任务、更新显示或进行数据采集等。
  4. 脉冲宽度调制(PWM):定时器可以用于生成脉冲宽度调制信号。PWM 技术常用于控制电机速度、调光、音频合成和通信协议等应用。通过调整定时器的计数值和比较值,可以生成具有不同占空比的脉冲信号。
  5. 输入捕获和输出比较:定时器可以用于输入捕获和输出比较功能。输入捕获允许定时器记录外部事件的时间戳,用于测量时间间隔或频率。输出比较允许定时器与一个或多个输出引脚关联,当计数器的值与设定的比较值相等时触发输出操作。
  6. 软件定时器:除了硬件定时器,单片机还可以使用软件实现定时器功能。通过编写相应的软件代码,可以模拟定时器的计数和中断功能,实现定时和计时的需求。
    这些只是单片机定时器的一些常见用途,实际上,其灵活性和可编程性使得定时器可以应用于许多其他领域和应用中。具体使用定时器的方式和配置取决于具体的嵌入式系统设计和应用需求。在使用定时器之前,请仔细阅读单片机的技术文档和相关资料,了解其具体的定时器功能和使用方法。
    请注意,此处提供的是单片机定时器的一般概述,具体的实现和应用细节可能因单片机型号和厂商而异。
相关推荐
闲晨2 小时前
C++ 继承:代码传承的魔法棒,开启奇幻编程之旅
java·c语言·开发语言·c++·经验分享
scan16 小时前
单片机串口接收状态机STM32
stm32·单片机·串口·51·串口接收
DARLING Zero two♡7 小时前
关于我、重生到500年前凭借C语言改变世界科技vlog.16——万字详解指针概念及技巧
c语言·开发语言·科技
Qingniu017 小时前
【青牛科技】应用方案 | RTC实时时钟芯片D8563和D1302
科技·单片机·嵌入式硬件·实时音视频·安防·工控·储能
QAQ小菜鸟7 小时前
一、初识C语言(1)
c语言
何曾参静谧8 小时前
「C/C++」C/C++ 之 变量作用域详解
c语言·开发语言·c++
互联网打工人no18 小时前
每日一题——第一百二十一题
c语言
深圳市青牛科技实业有限公司9 小时前
【青牛科技】应用方案|D2587A高压大电流DC-DC
人工智能·科技·单片机·嵌入式硬件·机器人·安防监控
朱一头zcy9 小时前
C语言复习第9章 字符串/字符/内存函数
c语言
此生只爱蛋9 小时前
【手撕排序2】快速排序
c语言·c++·算法·排序算法