7-定时器

1.定时器介绍

定时器介绍:51单片机的定时器属于单片机的内部资源,其电路的连接和运转均在单片机内部完成

定时器作用:

(1)用于计时系统,可实现软件计时,或者使程序每隔一固定时间完成一项操作

(2)替代长时间的Delay,提高CPU的运行效率和处理速度

(…)

2.STC89C52定时器资源

定时器个数:3个(T0、T1、T2),T0和T1与传统的51单片机兼容,T2是此型号单片机增加的资源

注意:定时器的资源和单片机的型号是关联在一起的,不同的型号可能会有不同的定时器个数和操作方式,但一般来说,T0和T1的操作方式是所有51单片机所共有的

3.定时器工作原理

定时器在单片机内部就像一个小闹钟一样,根据时钟的输出信号,每隔“一秒”,计数单元的数值就增加一,当计数单元数值增加到“设定的闹钟提醒时间”时,计数单元就会向中断系统发出中断申请,产生“响铃提醒”,使程序跳转到中断服务函数中执行

image-20240102152902328

定时器工作模式:

STC89C52的T0和T1均有四种工作模式:

​ 模式0:13位定时器/计数器

模式1:16位定时器/计数器(常用)

模式2:8位自动重装模式

模式3:两个8位计数器

模式1框图:

image-20240102153221437

TL0,TH0一共有16个bit(16位计数器),总共可以计数从0-65535,每一个脉冲都会+1,加到最大值时就会申请中断,Interrupt是指中断

时钟来源:系统时钟(SYSclk),外部引脚(T0Pin)

系统时钟(SYSclk):即晶振周期,晶振在开发板上有显示。÷12表示进行十二分频,分频后的输出为1MHZ即1微秒计数一次

C/T非=0,接上面电路,=1,接下面电路。

非门:

image-20240105155835646

或门:

image-20240105155918738

与门:

image-20240105155957433

本次设计程序就是GATE直接给0,由TR0单独控制

4.中断系统

image-20240102161504299

image-20240102161521072

image-20240102161750921

5.中断资源

STC89C52

中断源个数:8个(外部中断0、定时器0中断、外部中断1、定时器1中断、串口中断、定时器2中断、外部中断2、外部中断3)

中断优先级个数:4个

中断号:

image-20240102162139175

中断的资源和单片机的型号是关联在一起的,不同的型号可能会有不同的中断资源,例如中断源个数不同、中断优先级个数不同等等

6.定时器和中断系统

image-20240102162953586

7.定时器相关寄存器

单片机通过配置寄存器控制内部电路的连接

image-20240102163325141

image-20240102163345036

寄存器是连接软硬件的媒介

在单片机中寄存器就是一段特殊的RAM存储器,一方面,寄存器可以存储和读取数据,另一方面,每一个寄存器背后都连接了一根导线,控制着电路的连接方式

寄存器相当于一个复杂机器的“操作按钮”

8.程序

配置TMOD

image-20240105161540482

使用定时器0,工作在16位定时器/计数器模式

故:GATE=0,C/T非=0,M1=0,M0=1(结合手册定时器部分进行理解),由TR0单独控制,所以GATE给0

image-20240115161916764

配置TCON:

image-20240115162615090

配置TL0和TH0

0-65535,每隔1us计数加一,总共定时时间为65535us,64535离计数器溢出差值为1000,所以计时时长为1ms

void Timer0_Init()
{
//	TMOD=0x01;//0000 0001
	TMOD &= 0xF0;			//设置定时器模式
	TMOD |= 0x01;			//设置定时器模式
	TF0=0;//不产生中断
	TR0=1;//定时器开始工作
	TH0=64535/256;//计算高位
	TL0=64535%256;//计算低位
	ET0=1;//根据中断电路图进行配置
	EA=1;//允许中断
	PT0=0;//低优先级
}

也可以通过ISP软件直接生成定时程序

image-20240115170650864

void Timer0_Init(void)		//1毫秒@11.0592MHz
{
	AUXR &= 0x7F;			//定时器时钟12T模式
	TMOD &= 0xF0;			//设置定时器模式
	TMOD |= 0x01;			//设置定时器模式
	TL0 = 0x66;				//设置定时初始值
	TH0 = 0xFC;				//设置定时初始值
	TF0 = 0;				//清除TF0标志
	TR0 = 1;				//定时器0开始计时
	ET0=1;					//定时器/计数器0中断允许位,设置为1,允许中断
	EA=1;					//全局中断允许位,设置为1,允许中断
	PT0=0;					//低优先级
}

中断程序

unsigned int T0count;
void Timer0_Routine() interrupt 1
{
//	P20=0;//检测程序是否进入中断
	TL0 = 0x66;				//设置定时初始值
	TH0 = 0xFC;				//设置定时初始值
	T0count++;//每有一次中断就++,1000次中断也就是1s(1次中断1ms)
	if(T0count>=1000)
	{
		T0count=0;
		P20=~P20;
	} 
}

main程序:

#include <STC89C5xRC.H>

void Timer0_Init(void)		//1毫秒@11.0592MHz
{
	AUXR &= 0x7F;			//定时器时钟12T模式
	TMOD &= 0xF0;			//设置定时器模式
	TMOD |= 0x01;			//设置定时器模式
	TL0 = 0x66;				//设置定时初始值
	TH0 = 0xFC;				//设置定时初始值
	TF0 = 0;				//清除TF0标志
	TR0 = 1;				//定时器0开始计时
	ET0=1;					//允许中断
	EA=1;					//允许中断
	PT0=0;					//低优先级
}

void main()
{
	Timer0_Init();
	while(1)
	{
				
	}
}

unsigned int T0count;
void Timer0_Routine() interrupt 1
{
//	P20=0;//检测程序是否进入中断
	TL0 = 0x66;				//变为0后,重新设置定时初始值
	TH0 = 0xFC;				//变为0后,重新设置定时初始值
	T0count++;//每有一次中断就++,1000次中断也就是1s(1次中断1ms)
	if(T0count>=1000)
	{
		T0count=0;
		P20=~P20;
	} 
	
}

9.定时器程序模块化

Timer0.c

#include <STC89C5xRC.H>

/**
  * @brief  定时器0初始化,1毫秒@11.0592MHz
  * @param  无
  * @retval 无
  */
  
void Timer0_Init(void)		//1毫秒@11.0592MHz
{
//	AUXR &= 0x7F;			//定时器时钟12T模式
	TMOD &= 0xF0;			//设置定时器模式
	TMOD |= 0x01;			//设置定时器模式
	TL0 = 0x66;				//设置定时初始值
	TH0 = 0xFC;				//设置定时初始值
	TF0 = 0;				//清除TF0标志
	TR0 = 1;				//定时器0开始计时
	ET0=1;					//允许中断
	EA=1;					//允许中断
	PT0=0;					//低优先级
}


//定时器中断函数模板
//void Timer0_Routine() interrupt 1
//{
//	static unsigned int T0count;//静态变量
//	TL0 = 0x66;				//设置定时初始值
//	TH0 = 0xFC;				//设置定时初始值
//	T0count++;//每有一次中断就++,1000次中断也就是1s(1次中断1ms)
//	if(T0count>=1000)
//	{
//		T0count=0;
//		P20=~P20;
//	} 	
//}

Timer0.h

#ifndef __Timer0_H__
#define __Timer0_H__

void Timer0_Init(void);

#endif

main.c

#include <STC89C5xRC.H>
#include "Timer0.h"

void main()
{
	Timer0_Init();
	while(1)
	{
				
	}
}


void Timer0_Routine() interrupt 1
{
//	P20=0;//检测程序是否进入中断
	static unsigned int T0count;//静态变量
	TL0 = 0x66;				//设置定时初始值
	TH0 = 0xFC;				//设置定时初始值
	T0count++;//每有一次中断就++,1000次中断也就是1s(1次中断1ms)
	if(T0count>=1000)
	{
		T0count=0;
		P20=~P20;
	} 
	
}

10.定时器实现流水灯

Timer0.c

#include <STC89C5xRC.H>

/**
  * @brief  定时器0初始化,1毫秒@11.0592MHz
  * @param  无
  * @retval 无
  */
  
void Timer0_Init(void)		//1毫秒@11.0592MHz
{
//	AUXR &= 0x7F;			//定时器时钟12T模式
	TMOD &= 0xF0;			//设置定时器模式
	TMOD |= 0x01;			//设置定时器模式
	TL0 = 0x66;				//设置定时初始值
	TH0 = 0xFC;				//设置定时初始值
	TF0 = 0;				//清除TF0标志
	TR0 = 1;				//定时器0开始计时
	ET0=1;					//允许中断
	EA=1;					//全局中断允许位,设置为1,允许中断
	PT0=0;					//低优先级
}


//定时器中断函数模板
//void Timer0_Routine() interrupt 1
//{
//	static unsigned int T0count;//静态变量
//	TL0 = 0x66;				//设置定时初始值
//	TH0 = 0xFC;				//设置定时初始值
//	T0count++;//每有一次中断就++,1000次中断也就是1s(1次中断1ms)
//	if(T0count>=1000)
//	{
//		T0count=0;
//		P20=~P20;
//	} 	
//}

Timer0.h

#ifndef __Timer0_H__
#define __Timer0_H__

void Timer0_Init(void);

#endif

key.c

#include <STC89C5xRC.H>
#include "Delay.h"

/**
  * @brief  获取独立按键键码 
  * @param  无
  * @retval 按下按键的键码,范围0-4,无按键按下时,返回值为0
  */
unsigned char key()
{
	unsigned char KeyNumber=0;
	
	if(P31==0){Delay(20);while(P31==0);Delay(20);KeyNumber=1;}
	if(P30==0){Delay(20);while(P30==0);Delay(20);KeyNumber=2;}
	if(P32==0){Delay(20);while(P32==0);Delay(20);KeyNumber=3;}
	if(P33==0){Delay(20);while(P33==0);Delay(20);KeyNumber=4;}
	
	return KeyNumber;
}

key.h

#ifndef __KEY_H__
#define __KEY_H__

unsigned char key();
	
#endif

main.c

#include <STC89C5xRC.H>
#include "Timer0.h"
#include "key.h"
#include <INTRINS.H>

unsigned char KeyNum,LEDMode;
void main()
{
	P2=0xFE;
	Timer0_Init();
	while(1)
	{
		KeyNum=key();
		if(KeyNum==1)//按一下改变一次方向
		{
			LEDMode++;
			if(LEDMode>=2) LEDMode=0;
		}
	}
}


void Timer0_Routine() interrupt 1
{
	static unsigned int T0count;//静态变量
	TL0 = 0x66;				//变为0后,重新设置定时初始值
	TH0 = 0xFC;				//变为0后,重新设置定时初始值
	T0count++;
	if(T0count>=500)//0.5s移位一次
	{
		T0count=0;
		if(LEDMode==0)
			P2=_crol_(P2,1);//循环左移
		if(LEDMode==1)
			P2=_cror_(P2,1);//循环右移
	} 
}

11.定时器时钟

main.c

#include <STC89C5xRC.H>
#include "Delay.h"
#include "Timer0.h"
#include "LCD1602.h"

unsigned char Sec=55,Min=59,Hour=23;
void main()
{
	LCD_Init();
	Timer0_Init();
	LCD_ShowString(1,1,"Clock:");
	LCD_ShowString(2,1,"  :  :");
	while(1)
	{
		LCD_ShowNum(2,1,Hour,2);
		LCD_ShowNum(2,4,Min,2);
		LCD_ShowNum(2,7,Sec,2);
	}
}

//定时器中断函数模板
void Timer0_Routine() interrupt 1
{
	static unsigned int T0count;//静态变量
	TL0 = 0x66;				//设置定时初始值
	TH0 = 0xFC;				//设置定时初始值
	T0count++;//每有一次中断就++,1000次中断也就是1s(1次中断1ms)
	if(T0count>=1000)
	{
		T0count=0;
		Sec++;
		if(Sec>=60)
		{
			Sec=0;
			Min++;
			if(Min>=60)
			{
				Min=0;
				Hour++;
				if(Hour>=24)
					Hour=0;
			}
		}
	} 	
}

所用到的程序文件有

Delay.c

Delay.h

LCD1602.c

LCD1602.h

Timer0.c

Timer0.h

posted @ 2024-01-16 21:23  Jinx8823  阅读(18)  评论(0编辑  收藏  举报