7-定时器
1.定时器介绍
定时器介绍:51单片机的定时器属于单片机的内部资源,其电路的连接和运转均在单片机内部完成
定时器作用:
(1)用于计时系统,可实现软件计时,或者使程序每隔一固定时间完成一项操作
(2)替代长时间的Delay,提高CPU的运行效率和处理速度
(…)
2.STC89C52定时器资源
定时器个数:3个(T0、T1、T2),T0和T1与传统的51单片机兼容,T2是此型号单片机增加的资源
注意:定时器的资源和单片机的型号是关联在一起的,不同的型号可能会有不同的定时器个数和操作方式,但一般来说,T0和T1的操作方式是所有51单片机所共有的
3.定时器工作原理
定时器在单片机内部就像一个小闹钟一样,根据时钟的输出信号,每隔“一秒”,计数单元的数值就增加一,当计数单元数值增加到“设定的闹钟提醒时间”时,计数单元就会向中断系统发出中断申请,产生“响铃提醒”,使程序跳转到中断服务函数中执行
定时器工作模式:
STC89C52的T0和T1均有四种工作模式:
模式0:13位定时器/计数器
模式1:16位定时器/计数器(常用)
模式2:8位自动重装模式
模式3:两个8位计数器
模式1框图:
TL0,TH0一共有16个bit(16位计数器),总共可以计数从0-65535,每一个脉冲都会+1,加到最大值时就会申请中断,Interrupt是指中断
时钟来源:系统时钟(SYSclk),外部引脚(T0Pin)
系统时钟(SYSclk):即晶振周期,晶振在开发板上有显示。÷12表示进行十二分频,分频后的输出为1MHZ即1微秒计数一次
C/T非=0,接上面电路,=1,接下面电路。
非门:
或门:
与门:
本次设计程序就是GATE直接给0,由TR0单独控制
4.中断系统
5.中断资源
STC89C52
中断源个数:8个(外部中断0、定时器0中断、外部中断1、定时器1中断、串口中断、定时器2中断、外部中断2、外部中断3)
中断优先级个数:4个
中断号:
中断的资源和单片机的型号是关联在一起的,不同的型号可能会有不同的中断资源,例如中断源个数不同、中断优先级个数不同等等
6.定时器和中断系统
7.定时器相关寄存器
单片机通过配置寄存器控制内部电路的连接
寄存器是连接软硬件的媒介
在单片机中寄存器就是一段特殊的RAM存储器,一方面,寄存器可以存储和读取数据,另一方面,每一个寄存器背后都连接了一根导线,控制着电路的连接方式
寄存器相当于一个复杂机器的“操作按钮”
8.程序
配置TMOD:
使用定时器0,工作在16位定时器/计数器模式
故:GATE=0,C/T非=0,M1=0,M0=1(结合手册定时器部分进行理解),由TR0单独控制,所以GATE给0
配置TCON:
配置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软件直接生成定时程序
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