一、定时器的基本原理
1、寄存器
(1) TMOD
(2)TCON
TCON为控制寄存器,作用是控制定时器的启、停,标志定时器溢出和中断情况。位0~位3为T0定时/计数器的设置;位4~位7为T1定时/计数器的设置。
GATE:为门控位,GATE=0时,只要在编写程序时,使TCON中的TR0或TR1为1,就可以启动定时器/计数器工作。GATE=1时,不仅要在编写程序时,使TCON中的TR0或TR1为1,且需要外部引脚也为高电平,才能工作。
C/T:定时/计数模式切换,C/T=0时为定时模式,C/T=1时为计数模式。
M1/M0:用来选择定时计/计数器的工作方式,一般使用都是采用16位的计时计数器。
(3)模式1
以定时器0为例——
(4)定时器操作步骤
1.选择工作方式(设置M0,M1的值)
2.选择控制方式GATE(为0是只要软件设定好参数即可,为1则需要软件设定参数,且定时器/计数器的中断引脚需要为高电平)
3.确定定时器的工作模式,是定时模式还是计数模式 C/T
4.给定时器设初值(设置THX与TLX)
5.开启定时器中断(设置ET0或ET1)
6.开启总中断(设置EA的值)
7.定时器/计数器的选择T0/T1(设置TR1或TR0的值)
二、定时器的应用
1、定时器T0模式1
实现每隔1s,L1闪烁一次,即亮0.5s,灭0.5s;每隔10s,L8闪烁一次,即亮5s,灭5s。
代码:
#include <reg52.h>
sbit L1 = P0^0;
sbit L8 = P0^7;
//LED灯
void Select_HC573(unsigned char channel){
switch(channel)
{
case 4:
P2 = (P2 & 0x1f)|0x80;break;
case 5:
P2 = (P2 & 0x1f)|0xa0;break;
case 6:
P2 = (P2 & 0x1f)|0xc0;break;
case 7:
P2 = (P2 & 0x1f)|0xe0;break;
}
}
//================================
void Init_T0()
{
TMOD = 0x01; //模式1,16位无自动重装
/* TMOD只能高四位控制T1,此处不需要,所以全部置0
低四位控制T0,且使用模式1*/
TH0 = (65535-50000) / 256; //高8位
TL0 = (65535-50000) % 256; //低8位
ET0 = 1; //T0的中断允许
EA = 1; //总中断
TR0 =1; //定时器0运行控制
}
unsigned char count = 0;
unsigned char count1 = 0;
//中断
void Service_T0() interrupt 1
{
Select_HC573(4);
TH0 = (65535-50000) / 256; //模式1无自动重装,中断服务函数需重新赋初始值
TL0 = (65535-50000) % 256;
count++;
count1++;
if(count == 10)
{
L1 = ~L1;
count = 0;
}
if(count1 == 100)
{
L8 = ~L8;
count1 = 0;
}
}
//=================================
void Init_System()
{
Select_HC573(5);
P0 = 0x00;
Select_HC573(4);
P0 = 0xff;
}
void main()
{
Init_T0();
Init_System();
while(1)
{
}
}
2、实现分、秒和毫秒的显示
当按下S4时,开始计时,再按一下S4,暂停计时;按下S5,计时清零。
代码:
#include <reg52.h>
sbit S4 = P3^3;
sbit S5 = P3^2;
unsigned char SMG_duanma[12]={
0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90,
0xbf,0x7f};
unsigned char min;
unsigned char sec;
unsigned char msec;
void Select_HC573(unsigned char channel)
{
switch(channel)
{
case 4:
P2 = (P2 & 0x1f) | 0x80;
break;
case 5:
P2 = (P2 & 0x1f) | 0xa0;
break;
case 6:
P2 = (P2 & 0x1f) | 0xc0;
break;
case 7:
P2 = (P2 & 0x1f) | 0xe0;
break;
}
}
void SMG_bit(unsigned char pos,unsigned char dat)
{
Select_HC573(6);
P0 = 0x01 << pos;
Select_HC573(7);
P0 = dat;
}
void SMG_Delay(unsigned int t)
{
while(t--);
}
void SMG_Display()
{
SMG_bit(7,SMG_duanma[msec%10]);
SMG_Delay(500);
SMG_bit(6,SMG_duanma[msec/10]);
SMG_Delay(500);
SMG_bit(5,SMG_duanma[10]);
SMG_Delay(500);
SMG_bit(4,SMG_duanma[sec%10]);
SMG_Delay(500);
SMG_bit(3,SMG_duanma[sec/10]);
SMG_Delay(500);
SMG_bit(2,SMG_duanma[10]);
SMG_Delay(500);
SMG_bit(1,SMG_duanma[min%10]);
SMG_Delay(500);
SMG_bit(0,SMG_duanma[min/10]);
SMG_Delay(500);
}
//==========定时器相关函数================
void Init_Time0()
{
TMOD = 0x01; //模式1,16位无自动重装
TH0 = (65535-50000) / 256; //高8位
TL0 = (65535-50000) % 256; //低8位
ET0 = 1; //T0的中断允许
EA = 1; //总中断
TR0 =1; //定时器0运行控制
}
void Service_Time0() interrupt 1
{
TH0 = (65535-50000) / 256;
TL0 = (65535-50000) % 256;
msec++;
if(msec == 20)
{
sec++;
msec = 0;
if(sec == 60)
{
min++;
sec = 0;
}
if(min == 99)
min = 0;
}
}
//=================================
void Key_Delay(unsigned int t)
{
while(t--);
}
void Key_fun()
{
if(S4 == 0)
{
Key_Delay(100); //延时消抖
if(S4 == 0)
{
TR0 = ~TR0; //暂停或启动
while(S4 == 0) //松手检测,数码管仍动态显示
{
SMG_Display();
}
}
}
if(S5 == 0)
{
Key_Delay(100); //延时消抖
if(S5 == 0)
{
min = sec = msec = 0; //复位
while(S5 == 0)
{
SMG_Display();
}
}
}
}
void Init_System()
{
Select_HC573(5);
P0 = 0x00;
Select_HC573(4);
P0 = 0xff;
}
void main()
{
Init_Time0();
Init_System();
while(1)
{
SMG_Display();
Key_fun();
}
}