一、定时器:
1.介绍:
单片机内部实现的计时系统。
作用:代替长时间Daley,提高cpu效率。
数量:至少2个,T0,T1,T2等。其中T0,T1为所有51单片机共有,T2等为不同单片机特化。
工作模式:(只讲模式1)
模式0:13位定时器,计数器; 模式1:16位定时器,计数器(常用);
模式2:8位自动重装模式; 模式3:两个8位计数器
2.模式1原理:
时钟每一秒释放一个脉冲,使计数单元加一,计数单元到达最大值2^16,再加一变为0,且TF0变为1,使中断系统执行中断。
(1)时钟:
本单片机晶振周期12MHz,如果链接12分频(即+12),变为1MHz,每一微秒记一次数。
(2)控制系统:
1为取反,2为y按位或(同为0才为0),3为按位与(同为1才为1)。
本节我们将GATE置为0,则接通与否只由TR0控制,1连通,0断开。(自己推一下)
(3)中断系统:
为cpu处理紧急事件设置,如果出现紧急事件,中断系统会中断当前行动,优先处理紧急事件。
本节令 ET0 = EA = 1,PT0 = 0 即可。(只有一个中断,无所谓优先级)
什么是中断资源?
中断资源是指需要中断时,根据不同的中断源,进入不同的函数,这些函数称为中断资源。
其中,函数内部进行什么操作需自己实现。
注:不同单片机中断资源不同。
本单片机中断资源:
(4)寄存器介绍:(需要哪一个来这里找)
TMOD:定时器模式寄存器
M1,M0为控制模式的,我们运用模式1,令 M1,M0 为 0,1 即可。
TCON:定时器控制寄存器
TL0,TH0,TL1,TH1:计时系统寄存器。
(5)计时原理:
TL0,TH0共16位可计 0 - 65535,每隔1us计数+1。
需通过给TL0,TH0赋初始值,来控制计时时长。
3.定时器模块化:
//定时器0初始化
void Time0_Init()
{
TMOD &= 0xF0;
TMOD |= 0x01;//可使前4位保持不变,只改变定时器0对应的后4位
TF0 = 0;
TR0 = 1;
//控制计时时长,1ms计一次
TH0 = 64535 / 256;
TL0 = 64535 % 256 + 1;
//中断系统
ETO = 1;
EA = 1;
PT0 = 0;
}
//定时器模板1s
/*
unsigned int T0Count = 0;
void Timer0_Routine() interrupt 1
{
T0Count++;
TH0 = 64535 / 256;
TH0 = 64535 % 256;
if (T0Count >= 1000)//计到1s执行一次
{
T0Count = 0;
//需执行的操作
}
}
*/
二、实战:按键控制LED流水灯
1.循环左移和右移的库函数:
包含头文件 <INTRINS.H>
函数 _crol_ :unsigned char _crol_(unsigned char a , unsigned char num);
循环左移,将变量a左移num位,到达最高位后返回最低位。
函数 _cror_ :循环右移。
2.设置变量:
unsigned char KeyNum,LEDMode;
//KeyNum --- 检测独立按键状态
//LEDMode --- 控制流水灯模式
3.根据LEDMode控制流水灯:(中断)
//定时器模板1s
void Timer0_Routine() interrupt 1
{
static unsigned int T0Count = 0;
T0Count++;
TH0 = 64535 / 256;
TL0 = 64535 % 256 + 1;
if (T0Count >= 1000)//计到1s执行一次
{
T0Count = 0;
//需执行的操作
if (LEDMode == 0)P2 = _crol_(P2, 1);
if (LEDMode == 1)P2 = _cror_(P2, 1);
}
}
4.根据独立按键改变LEDMode:
while (1)
{
KeyNum = Key();
if (KeyNum)
{
if (KeyNum == 1)
{
if (LEDMode == 1)LEDMode = 0;
}
if (KeyNum == 2)
{
if (LEDMode == 0)LEDMode = 1;
}
}
}
5.组合成品:
#include <REGX52.h>
#include"51singlechip.h"
#include<INTRINS.H>
unsigned char KeyNum,LEDMode;
void main()
{
P_2 = 0xFE;//初始化
Time0_Init();
while (1)
{
KeyNum = Key();
if (KeyNum)
{
if (KeyNum == 1)
{
if (LEDMode == 1)LEDMode = 0;
}
if (KeyNum == 2)
{
if (LEDMode == 0)LEDMode = 1;
}
}
}
}
//定时器模板1s
void Timer0_Routine() interrupt 1
{
static unsigned int T0Count = 0;
T0Count++;
TH0 = 64535 / 256;
TL0 = 64535 % 256 + 1;
if (T0Count >= 1000)//计到1s执行一次
{
T0Count = 0;
//需执行的操作
if (LEDMode == 0)P2 = _crol_(P2, 1);
if (LEDMode == 1)P2 = _cror_(P2, 1);
}
}