一、定时器相关
1.定时原理
51单片机有两个定时/计数器T0和T1,为16位加法计数器,由低8位TLx和高8位THx两个寄存器组成,最大计数值为65535个计数脉冲。 当计数器接收到一个计数脉冲时,计数器就会加1,当计数值累计至全为1时(16位65535),再输入一个计数脉冲,计数器便会溢出回零,同时向内核提出中断请求。 单片机的外部晶振为12MHz,那么,经过12分频后输入计数器的计数脉冲为1MHz,即每个脉冲的周期为1us。因此定时器T0的16位工作模式最大的定时时间为65535us,65.5ms。 也就是说如果要定时1ms的话,计数器就应该从64535(65535-1000)开始计数,我们将这个数称为计数器初值,
2.相关寄存器
特殊功能寄存器TMOD
特殊功能寄存器TMOD用于选择定时器/计数器T0.T1的工作模式和工作方式,该寄存器不可位寻址, GATE 为门控位: 当GATE = 0时,定时器是否计数,由控制位TRx(0.1),来控制; 当GATE = 1时,定时器是否计数,由外中断引脚INTx上的电平与运行控制位TRx共同控制。 M1.M0为工作方式选择位: C/T为计数器模式和定时器模式选择位: 当C/T = 0 时,为定时器模式,对系统时钟12分频后的脉冲进行计数; 当C/T = 1时,为计数器模式,计数器对外部输入引脚T0(P3.4),或T1(P3.5)的外部脉冲计数。
定时器/计数器控制寄存器TCON
定时器/计数器控制寄存器TCON为可位寻址寄存器 其中第四位与上一节的外部中断有关,这里只介绍高四位: (1) TF1、TFO为计数溢出标志位: 当计数器计数溢出时,该位置1。使用查询方式时,此位可供CPU查询,但应注意查询后,用软件及时将该位置0。使用中断方式时,作为中断请求标志位,进入中断服务程序后由硬件自动置0。
(2)TR1、TRO—计数运行控制位: TR1位(或TR0)=1,启动计数器计数的必要条件。TR1位(或TRO)=0,停止计数器计数。 该位可由软件置“1”或清“0”。
二、定时器的程序配置
(1)设置TMOD寄存器
T0工作在方式1,应使TMOD寄存器的M1、M0=01;应设置C/T*=0,为定时器模式;对T0的运行控制仅由TR0来控制,应使相应的GATE位为0。定时器T1不使用,各相关位均设为0。所以,TMOD寄存器应初始化为0x01。
(2)计算定时器T0的计数初值
当计数器接收到一个计数脉冲时,计数器就会加1,当计数值累计至全为1时(16位65535),再输入一个计数脉冲,计数器便会溢出回零,同时向内核提出中断请求。 每个脉冲的周期为1us, 若要定时1ms 则计数器的重装载值应该为65535-1000 = 64535 若要定时50ms,则计数器的重装载值(初值)应该为65535-50000 = 15535 若要定时1s,则可以设置一个变量value,定时器周期为50ms,每次产生50ms中断后让value的值+1,则当value=20时,则代表时间经过了1s。
(3)定时器T0初始化程序
void TIM0_Init()
{
TMOD = 0x01;
TH0 = (65535 - 10000)/256;
TL0 = (65535 - 10000)%256;
TR0 = 1;
ET0 = 1;
EA = 1;
}
三、代码
#include <reg52.h>
#include <intrins.h>
sbit hc138_A=P2^5;
sbit hc138_B=P2^6;
sbit hc138_C=P2^7;
unsigned char shuzi[10]={0xc0,0xf9,0xa4,0xb0,0x99,0x92,0x82,0xf8,0x80,0x90};
unsigned char shuzi1[10]={0x40,0x79,0x24,0x30,0x19,0x12,0x02,0x78,0x00,0x10};
#define uchar unsigned char
uchar sec = 55;
uchar min = 59;
uchar hour = 23;
void HC138(unsigned int n)
{
switch(n)
{
case 4:
hc138_A=0 ; hc138_B=0 ; hc138_C=1; break;
case 5:
hc138_A=1 ; hc138_B=0 ; hc138_C=1; break;
case 6:
hc138_A=0 ; hc138_B=1 ; hc138_C=1; break;
case 7:
hc138_A=1 ; hc138_B=1 ; hc138_C=1; break;
}
}
void delay(unsigned int k)
{
while(k--);
}
void Display()
{
char x = 0x01;
int i = 0;
for(i = 1;i<=8 ;i++)
{
HC138(6);
P0 = x;
x = _crol_(x,1);
HC138(7);
P0 = 0xff;delay(50);
switch (i)
{
case 1 :P0 = shuzi[hour/10]; break;
case 2 :P0 = shuzi[hour%10]; break;
case 3 :P0 = 0xbf; break;
case 4 :P0 = shuzi[min/10]; break;
case 5 :P0 = shuzi[min%10]; break;
case 6 :P0 = 0xbf; break;
case 7 :P0 = shuzi[sec/10]; break;
case 8 :P0 = shuzi[sec%10]; break;
}
delay(500);P0 = 0xff;
}
}
void TIM0_Init()
{
TMOD = 0x01;
TH0 = (65535 - 10000)/256;
TL0 = (65535 - 10000)%256;
TR0 = 1;
ET0 = 1;
EA = 1;
}
unsigned int time = 0;
void TIM0_work() interrupt 1
{
TH0 = (65535 - 10000)/256;
TL0 = (65535 - 10000)%256;
time++;
if(time == 100)
{
sec++;
time = 0;
}
}
void main()
{
HC138(5);
P0=0x00;
HC138(4);
P0= 0xff;
TIM0_Init();
while(1)
{
if(sec == 60)
{
min++;
sec = 0;
}
if(min == 60)
{
hour++;
min = 0;
}
if(hour == 24)
{
hour = 0;
}
Display();
}
}
|