定时器(计时器)
(51单片机的定时器属于单片机内部资源,其电路的连接和运转均在单片机内部完成)
作用:
1.用于计时系统,可实现软件计时,或者使程序每隔一固定时间完成一项操作。
2.代替长时间Delay,提高CPU的运行效率和处理速度。
3.······(滴答定时器)
STC89C52定时器资源
定时器个数:
3个(T0、T1、T2),T0和T1与传统的51单片机兼容,T2是此型号单片机增加的资源。(timer)
注意:
定时器的资源与单片机的型号是联系在一起的。,不同的型号可能会有不同的定时器个数和操作方式,但一般来说,T0和T1的操作方式是所有551单片机所共有的。
定时器框图(工作原理)
在单片机内部像一个小闹钟,根据时钟输出信号,每隔“一秒”(一个时间间隔),计数单元的数值就会增加一,当计数单元数值增加到“设定的闹钟提醒时间”时,计数单元就会向中断系统发出中断申请,产生“响铃提醒”,使程序跳转到中断服务函数中执行。
时钟(提供计数单元的时钟脉冲) >> 计数单元(时钟计数) >> 中断系统(产生中断,执行定时任务)
STC89C52的T0和T1均有四种工作模式(不同的模式连接方式不同),常用的就是模式1(16位定时器/计数器。)
定时器时钟
SYSclk:系统时钟,即晶振周期,本开发板上的晶振为12MHz
中断系统
中断系统是为使CPU具有对外界紧急事件的实时处理能力而设置的。
当中央处理机CPU正在处理某件事的时候外界发生了紧急事件的请求,要求CPU暂停当前的工作,转而去处理这个紧急事件,处理完以后,再回到原来被中断的地方,继续原来的工作,这样的过程称为中断。实现这种功能的部件成为中断系统,请示CPU中断的请求源称为中断源。微型机的中断系统一般允许多个中断源,当几个中断源同时向CPU请求中断,要求为它服务的时候,这就存在CPU优先响应哪一个中断源请求的问题。通常根据中断源的轻重缓急排队,优先处理最紧急事件的中断源请求,即规定每一个中断源有一个优先级别。CPU总是先响应优先级别最高的中断请求。
当CPU正在处理一个中断源请求的时候(执行相应的中断服务程序),发生了另外一个优先级比他还高的中断源请求。如果CPU能够暂停对原来中断源的服务程序,转而去处理优先级更高的中断请求源,处理完以后,再回到原低级中断服务程序,这样的过程成为中断嵌套。这样的中 断系统称为多级中断系统,没有中断嵌套功能的中断系统称为单级中断系统。
中断系统流程
主程序 >> 中断请求(断点) >> 中断响应(执行中断处理程序) >> 中断返回(回到断点) >> 继续执行主程序
STC89C52中断资源
注意:
中断的资源和单片机的型号是关联在一起的,不同的型号可能会有不同的中断资源,例如中断源个数不同、中断优先级个数不同等等。
定时器和中断系统
定时器相关寄存器
·寄存器是链接软硬件的媒介
·在单片机中寄存器就是一段特殊的RAM存储器。一方面,寄存器可以存储和读取数据,另一方面,每一个寄存器背后连接了一根导线(比喻),控制着电路的连接方式
·寄存器相当于一个复杂机器的“操作按钮”
定时器0和1的相关寄存器
1.定时器控制寄存器TCON (Timer Control)
2.定时器工作模式寄存器TMOD (Timer Model)
中断寄存器
写代码
配置寄存器(子函数)
#include <REGX52.H>
void Timer0Init() //Init 初始化
{
TMOD = 0x01; //0000 0001 (定时器/计数器工作模式寄存器TOMD)
//定时器/计数器控制寄存器TCON,配置TF0,TR0
TF0 = 0;//(中断溢出标志位,清零防止刚配置好就产生中断)
TR0 = 1;//(确定定时器是否开启)
//赋初值:定时器计数范围0~65535us,每隔1us计数加一,总共计数时间65535us,赋初值64535(离计数器溢出差值为1000),所以计数时间为1ms
TH0 = 64535 / 256;//高八位
TL0 = 64535 % 256;//低八位 (小了1us)
//配置中断
ET0 = 1;
EA = 1;
PT0 = 0;
}
void main()
{
Timer0Init()
while(1)
{
}
}
//"闹钟响后跳转到该函数中执行中断任务"
void Timer0Routine() interrupt 1
{
}
不可位寻址 / 可位寻址
不可位寻址的寄存器只能整体赋值,可位寻址的寄存器可以对每一位单独赋值
不可位寻址的寄存器常用操控方法(不影响高四位而配置低四位,同时使用定时器1和定时器0时):
//TMOD = 0x01
TMOD = TMOD & 0xF0 //把TMOD的低四位清零,高四位保持不变 1010 0011 & 1111 0000 = 1010 0000
TMOD = TMOD | 0x01 //把TMOD的最低位置1,高四位保持不变 1010 0000 | 0000 0001 = 1010 0001
/*可简写为:
TMOD &= 0xF0;
TMOD |= 0X01;
*/
stc - isp 定时器计算器直接生成c代码
void Timer0Init(void) //1毫秒@12.000MHz
{
//89C52没有该寄存器,需要删掉 AUXR &= 0x7F; //定时器时钟12T模式
TMOD &= 0xF0; //设置定时器模式
TMOD |= 0x01; //设置定时器模式
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
//还需加上中断的配置
ET0 = 1;
EA = 1;
PT0 = 0;
}
独立按键控制LED流水灯模式
#include <REGX52.H>
#include "Timer0.h"
#include "Key.h"
#include <INTRINS.H>
unsigned char KeyNum,LEDMode;
void main()
{
P2 = 0xFE;
Timer0Init();
while(1)
{
KeyNum = Key();
if (KeyNum)
{
if(KeyNum == 1)
{
LEDMode++;
if(LEDMode >= 2)LEDMode = 0;
}
}
}
}
void Timer0_Rountine() interrupt 1
{
static unsigned int T0Count;//static 静态变量(函数结束之后变量不清零)
TL0 = 0x18; //设置定时初值
TH0 = 0xFC; //设置定时初值
T0Count ++;
if(T0Count >= 500)
{
T0Count = 0;
if(LEDMode==0)
P2=_crol_(P2,1);// crol 循环左移
if(LEDMode == 1)
P2=_cror_(P2,1);// crorr 循环右移
}
}
定时器时钟
#include <REGX52.H>
#include "Delay.h"
#include "LCD1602.h"
#inlcude "Timer0.h"
unsigned char Sec, Min, Hour;
void main()
{
LCD_Init();
Timer0Init();
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_Rountine() interrupt 1
{
static unsigned int T0Count;
TL0 = 0x18; //设置定时初值
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;
}
}
}
}
}