前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >(六)51单片机基础——定时器

(六)51单片机基础——定时器

作者头像
小点点
发布2022-12-12 14:09:19
1K0
发布2022-12-12 14:09:19
举报
文章被收录于专栏:小点点

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

定时器主要作用:

  1. 用于计时系统,可实现软件计时,或者使程序每隔一固定时间完成一项操作。
  2. 替代长时间的Delay,提高CPU的运行效率和处理速度。

        需要注意的是:定时器的资源和单片机的型号是关联在一起的,不同的型号可能会有不同的定时器个数和操作方式,但一般来说,T0和T1的操作方式是所有51单片机所共有的(15w只有T0和T2两个计时器)。而我们的89C52RC的定时器个数有3个(T0、T1、T2),T0和T1与传统的51单片机兼容,T2是此型号单片机增加的资源。

下面介绍一下计时器的触发流程:

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

        就类似于我们睡午觉时候设置的闹钟一样,首先设定一个30分钟的闹钟(提供计数单元的时钟脉冲),闹钟每秒都会刷新一次,每一次刷新,我们能睡得时间就减少了(时钟计数),到了30分钟之后,闹钟就响了,这个时候你就知道:就要起来上课了(产生中断,执行定时任务)。

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

  • 模式0:13位定时器/计数器
  • 模式1:16位定时器/计数器(常用)
  • 模式2:8位自动重装模式
  • 模式3:两个8位计数器

在STC89C52RC中,模式一使用较多,所以我们着重讲解一下模式一。

计数器介绍:当计数器到了最大值(65535)之后,就会产生溢出,中断器就会产生一个标记位,就使程序跳转到中断服务函数中执行。

时钟介绍

SYSclk:系统时钟,即晶振周期,本开发板上的晶振为11.0592MHz。C/T那个开关,给高电平就是连接下面那个计数器,给低电平就是连接上面那个计时器。而上面那个开关是控制计时间隔的。

中断系统介绍:

        这个中断,和我们现实中的中断是一样的,比如你在写作业,突然有人发消息给你(一个中断),你就拿起手机来看,这个时候突然发现水烧开了(一个中断),又去关热水器,再回到写作业的状态。         你们看,这里面,出现了优先级不同的两个中断,就出现了优先级高的中断打断了优先级低的中断(中断嵌套),再回到原来的状态。

 中断程序流程

这个就是中断程序的电路图,就是通过给每个开关赋值来实现功能,比较抽象。

 寄存器

  • 寄存器是连接软硬件的媒介
  • 在单片机中寄存器就是一段特殊的RAM存储器,一方面,寄存器可以存储和读取数据,另一方面,每一个寄存器背后都连接了一根导线,控制着电路的连接方式
  • 寄存器相当于一个复杂机器的“操作按钮”

具体流程和内容就是这样,51单片机主要就是通过操控寄存器来实现功能的,下面结合代码来理解一下:

这个是主函数

代码语言:javascript
复制
#include <REGX52.H>
#include "Time0.h"
#include "Key.h"
#include <INTRINS.h>
//void Timer0_Init()
//{
// 定时器部分
	// 配置TMOD
//	TMOD = 0x01;
// 与或赋值法	
//	TMOD &= 0xF0;	// 把TMOD的低四位清零,高四位不变
//	TMOD |= 0xF0	// 把TMOD的最低位置1,高四位不变
//	 配置TMOD
//	TF0 = 0;	//T0溢出中断标志
//	TR0 = 1;	//定时器T1的运行控制位
	
	// 配置TH0
//	TH0 = 64535/256; // 取高位
	// 配置TL0
//	TL0 = 64535%256; // 取低位
// 中断部分	
//	ET0 = 1;
//	EA = 1;
//	PT0 = 0;
//	void Timer0Init(void)		//1毫秒@11.0592MHz
//{
//	AUXR |= 0x80;		//定时器时钟1T模式
//	TMOD &= 0xF0;		//设置定时器模式
//	TL0 = 0xCD;		//设置定时初始值
//	TH0 = 0xD4;		//设置定时初始值
//	TF0 = 0;		//清除TF0标志
//	TR0 = 1;		//定时器0开始计时
//	ET0 = 1;
//	EA = 1;
//	PT0 = 0;
//}


//}

unsigned char KeyNum, LEDMode;

void main(){
	P2 = 0xFE;    //初始化,让D1亮
	Timer0Init();
	while(1){
		KeyNum = Key();
		if(KeyNum){
			if(KeyNum == 1){
				LEDMode++;    //改变LED灯模式
				if(LEDMode >= 2)LEDMode = 0;	
			}
			
		}
	}
}


// 计时器0中断之后运行的函数
void Timer0_Routine() interrupt 1
{
	static unsigned int T0Count;
	TL0 = 0xCD;		//设置定时初始值
	TH0 = 0xD4;	
	T0Count++;
	if(T0Count >= 500){
	T0Count = 0;		
		if(LEDMode == 0){
			P2 = _crol_(P2, 1);   
//位移函数,在这个头文件里“#include <INTRINS.h>”,能够循环移位,比移位符好用,这个是向左移位(灯向右移)
		}
		if(LEDMode == 1){
			P2 = _cror_(P2, 1);
//向左移位
		}
		
	}
}

这个是定时器的函数,包含.c和.h文件

代码语言:javascript
复制
//.c代码
#include <REGX52.H>

/**
  * @brief 定时器0初始化, 1毫秒@11.0592MHz
  * @param  无
  * @retval 无
  */
void Timer0Init(void)		//1毫秒@11.0592MHz
{

	TMOD &= 0xF0;		//设置定时器模式
	TL0 = 0xCD;		//设置定时初始值
	TH0 = 0xD4;		//设置定时初始值
	TF0 = 0;		//清除TF0标志
	TR0 = 1;		//定时器0开始计时
	ET0 = 1;
	EA = 1;
	PT0 = 0;
}

/*
// 计时器0中断之后运行的函数
void Timer0_Routine() interrupt 1
{
	static unsigned int T0Count;
	TL0 = 0xCD;		//设置定时初始值
	TH0 = 0xD4;	
	T0Count++;
	if(T0Count >= 1000){
	T0Count = 0;		
	P2_0 = ~P2_0;
//	Delay(100);
		
	}
}
*/
代码语言:javascript
复制
//.h代码
#ifndef __TIMER0_H__
#define __TIMER0_H__
void Timer0Init(void);

#endif

控制键盘按下的函数

代码语言:javascript
复制
#include <REGX52.H>
#include "Delay.h"


/**
  * @brief  获取独立按键键码
  * @param  无
  * @retval 按下按键的键码,范伟:0~4,无按键按下时返回0
  */
unsigned char Key()
{
	unsigned char KeyNumber = 0;
	if(P3_1 == 0){Delay(20);while(P3_1 == 0);Delay(20);KeyNumber = 1;}
	if(P3_0 == 0){Delay(20);while(P3_0 == 0);Delay(20);KeyNumber = 2;}
	if(P3_2 == 0){Delay(20);while(P3_2 == 0);Delay(20);KeyNumber = 3;}
	if(P3_3 == 0){Delay(20);while(P3_3 == 0);Delay(20);KeyNumber = 4;}
	return KeyNumber;
}
代码语言:javascript
复制
#ifndef __KEY_H__
#define __KEY_H__
unsigned char Key();

#endif

延时函数之前介绍过,在此处就不做讲解。

 具体运行结果如下所示:

https://live.csdn.net/v/embed/210574

计时器3

接下来,运用我们所学知识,来设计一个时钟,具体代码如下所示:

代码语言:javascript
复制
#include <REGX52.h>
#include "Delay.h"
#include "LCD1602.h"
#include "Time0.h"

unsigned char Sec, Hour=23, Min = 59;
void main(){
	//初始化
	LCD_Init();
	Timer0Init();
	//LCD显示
	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); 
		
	}
}
// 计时器0中断之后运行的函数
void Timer0_Routine() interrupt 1
{
	static unsigned int T0Count;
	TL0 = 0x66;		//设置定时初始值
	TH0 = 0xFC;	
	//计时和进位
	T0Count++;
	if(T0Count >= 1000){
	T0Count = 0;		
	Sec++;
		if(Sec==60){
			Sec = 0;
			Min++;
			if(Min == 60){
				Min = 0;
				Hour++;
				if(Hour == 24){
					Hour=0;
				}
			}
		}		
	}
}

这里也运用到了计时器函数,因为在前面介绍了,就不再重复。

运行效果如下所示:

https://live.csdn.net/v/embed/210577

计时器46

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-05-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档