51单片机 第七节 定时器

本节包含以下内容:7-1 定时器、7-2 按键控制LED流水灯模式&定时器时钟,时钟基于LCD1602显示

本笔记默认学习者已拥有:
1.Keil5和stc烧写工具 等各种软件、驱动、环境;
2.有一个属于自己的 51单片机开发板及相关零件 ;
3.认识C语言的语法;
本人使用的51开发板为 郭天祥C51 TX-1C增强版开发板 ;
本笔记根据B站up主:江科大自化协的教学视频 整理得到ヾ(•ω•)




7-1 定时器

之前我们使用的 按键、数码管、LCD1602都是 单片机I/O控制的 外设,
但定时器的电路在单片机内部,它是单片机的内部设备;
(3)操作系统的任务切换,像一些高级的单片机,它里面就有一个专门的系统的 滴答定时器,
它可以用来计时,让操作系统来执行多任务;

可以参考 STC89C52.pdf(提取码:ncst) 中的 第7章定时器/计数器;
T为Timer的缩写,即定时器;




原理分析

本节只分析 模式1 的 工作模式;




原理——计数系统

TL=Timer_Low,TH=Timer_High,计数系统能 记两个字节,高字节为TH,低字节为TL,
0代表它是 定时器0,计数系统 可以存[0,65535]这个范围内的数

1.时钟每给 计数系统 提供一个脉冲,16位计数器 中的值就会+1;
2.当 16位计数器 已经加到65535时,再给其脉冲,就会产生溢出,计数器就会回到0的位置;
\(65535+1=0\),而其溢出时会置一个 标志位,即TF0(Timer_Flag 0),有标志位,它就会向中断系统申请中断;




原理——时钟

TX-1C开发板的晶振为11.0592MHz;

1.时钟有两个来源,一个为SYSclk(system_clock),另一个为T0 Pin,T0 Pin是单片机的外部接口;

2.时钟可以由 系统时钟提供,也可以由外部引脚来提供,当它由 外部引脚 来提供时钟时,定时器 即为 计数器;

本节不介绍其 计数器 的功能,只介绍 时钟 由 系统时钟 来提供 计数脉冲;

3.12M 的脉冲一般会进行 分频,默认的 12T模式 会将 12M脉冲 进行 12分频,则输出频率为 1MHz;
1Mhz 一周期为 1微秒,即计数单元每隔 1微秒 就会记一次数;

4. \(C / \overline{T}\) 是一种选择开关,\(\overline{T}\)代表寄存器中的一位,这种开关是控制时钟的提供来源的,
如果这一位配置为1,就会执行\(C(counter 计数器 )\)的功能,
如果这一位配置为0,就会执行\(T(Timer定时器)\)的功能;

本节使用 12T模式,\(C / \overline{T}\)配置为1,使用系统时钟为 时钟 提供脉冲;




原理——中断系统

中断 相当于 程序可以同时执行两项任务;

外部中断2、外部中断3是 STC89C52型号增加的中断源,新型号单片机对于老型号单片机 功能上是向下兼容的;
PPT中 中断源 少了一个 定时器2中断;

RX、TX也是串口中断;

1.单片机通过配置寄存器来控制内部线路的连接
2.开关到底处于哪一位置,是由寄存器来控制的;
3.M1/M0是控制其处于哪种模式,GATE是门控端,TR0(Timer_Ready)控制定时器是否启动;
4.TCON(Timer_Control),TMOD(Timer_Mode);
5.IE是中断使能端;
6.在定时器电路中,GATE连接着 非门(一个三角形连接着一个圆圈,即 左侧给1 右侧为0);
非门 前面有个 弯月芽形状 为 或门(有1即1+);
再往前 半圆弧方块 为 与门(有0即0);

相关知识的详细 请参考 STC89C52.pdf(提取码:ncst)




7-2 按键控制LED流水灯模式&定时器时钟

如下为定时器0的模块



Timer0.c

#include<reg51.h>

/**
  * @brief  定时器0初始化,1毫秒@11.0592MHz
	* @param  无
	* @retval 无
	*/
void Timer0_Init(void){ //定时器初始化 
	//TMOD=0x01; //0000 0001 设置模式
	TMOD&=0xF0; //把TMOD的低四位清零,高四位保持不变
	TMOD|=0x01; //把TMOD的最低位置1,高四位保持不变
	//不可位寻址寄存器 不能 将每一位单独赋值
	//  可位寻址寄存器   能 将每一位单独赋值
	TF0=0; //中断溢出标志位 TF0=1 表示 产生中断
	TR0=1; //定时器是否开启
	TL0=0x66;		
	TH0=0xFC;
	ET0=1;
	EA=1;
	PT0=0;
}

/*
定时器中断函数模板
void Timer0_Routine() interrupt 1{
	static unsigned int T0Count;
	TL0=0x66;		
	TH0=0xFC;
	++T0Count;
	if(T0Count>=1000){
		T0Count=0;
		led1=~led1;
	}
}
*/



Timer0.h

#ifndef __TIMER0_H__
#define __TIMER0_H__

void Timer0_Init(void);

#endif

以下为独立按键的模块



Key.c

#include<reg51.h>
#include<Delayms.h>

/** 
	* @brief  获取独立按键键码
	* @param  无
	* @retval 按下按键的键码,范围:0~4,无按键按下时返回值为0
	*/
unsigned char Key(){
	unsigned char KeyNumber=0;
	
	if(T0==0){ Delayms(20);while(T0==0);Delayms(20); KeyNumber=1; }
	if(T1==0){ Delayms(20);while(T1==0);Delayms(20); KeyNumber=2; }
	if(WR==0){ Delayms(20);while(WR==0);Delayms(20); KeyNumber=3; }
	if(RD==0){ Delayms(20);while(RD==0);Delayms(20); KeyNumber=4; }
	
	return KeyNumber;
}



Key.h

#ifndef __KEY_H__
#define __KEY_H__

unsigned char Key(void);

#endif



按键控制LED流水灯模式.c

#include<reg51.h>
#include<Timer0.h>
#include<Key.h>
#include<INTRINS.h>
unsigned char KeyNum;
unsigned int LEDMode;

void main(){
	P1=0xFE;
	Timer0_Init();
	while(1){
		KeyNum=Key();
		if(KeyNum==1) LEDMode=(LEDMode+1)%2;
	}
}

void Timer0_Routine() interrupt 1{
	static unsigned int T0Count;
	TL0=0x66;		
	TH0=0xFC;
	++T0Count;
	if(T0Count>=500){
		T0Count=0;
		if(LEDMode==0) P1=_crol_(P1,1);
		else P1=_cror_(P1,1);
		//_crol_ 循环左移
		//_cror_ 循环右移
	}
}

运行结果如下




定时器时钟.c

#include<reg51.h>
#include<Delayms.h>
#include<LCD1602.h>
#include<Timer0.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;
	if(T0Count>=1000){
		T0Count=0;
		++Sec;
		if(Sec>=60){
			Sec=0;
			++Min;
			if(Min>=60){
				Min=0;
				++Hour;
				if(Hour>=24) Hour=0;
			}
		}
	}
}

运行结果如下




相关知识

一般晶振上会标有数字,表示其为 x MHz,我的开发板 晶振 为 11.0592MHz;

原文地址:https://www.cnblogs.com/Potrem/p/51_7.html