重点学习51单片机定时器1工作在模式2的应用。
在51单片机中,定时器1工作在模式2,TL1占8位,用作计数器寄存器,TH1占8位,用作预装载寄存器,向上计数。当TL1溢出时,会自动将TH1中数据装载到TL1中,继续计数。
1、定时器1工作在模式2,且定时器0没有工作在模式3,可以用作独立的定时器,计数器,或波特率发生器的输入时钟源。
1)、定时器1工作在模式2框图如下:
2)、定时器1输入时钟:
①、TMOD寄存器的bit6(C/T)=0,定时器输入时钟为CPU时钟经过12分频后得到的。
②、TMOD寄存器的bit6(C/T)=1,定时器输入时钟为来自T1引脚(P3.5),我们也可以理解为计数脉冲。
3)、定时器1启动:
①、当TMOD寄存器的bit7(GATE)=0时,将TR1=1,则会启动定时器1;
②、当TMOD寄存器的bit7(GATE)=1时,给INT1引脚(P3.3)施加高电平,同时TR1=1,则会启动定时器1;
4)、定时器1溢出标志TF1建立的条件
TH1和TL1从装载的初始值开始计数,直到TH1和TL1从0xFF变成0x100时产生溢出,此时定时器1的溢出标志TF1=1;
5)、定时器1产生中断条件
定时器1的溢出标志TF1=1
定时器1的中断使能位ET1=1
总中断使能位EA=1
只有这3个条件同时满足,定时器1才会进入到中断服务程序。
6)、定时器1工作在模式2(8位定时器)
#define T1_Load_Value (256-200) //配置定时器1为200us中断一次;
//函数功能: 定时器1工作在模式2的初始化;
void timer1_initializtion(void)
{ TMOD = 0x0F;TMOD |= 0x20;
//TMOD寄存器的bit6(C/T)=0,定时器输入时钟为CPU时钟经过12分频后得到的。
//配置Timer1为方式2(8位自动重装载定时器)
//设置GATE1=0,即不允许外部INT1脚控制Timer1;
TH1=T1_Load_Value; //手动装载TH1;
TL1=T1_Load_Value; //初始化计数器的初始值
TR1=1; //当GATE1=0时,TR1=1,表示启动T1开始工作;
ET1=1; //允许Timer1中断;
EA=1; //开总中断允许位;
}
//函数功能: Timer1的中断服务函数,每200us中断一次;
void timer1_interrupt_program() interrupt 3 using 1
{
///其它处理程序///
}
7)、定时器1工作在模式2(波特率发生器的输入时钟)
①、定时器1用作波特率发生器时,T1引脚(P3.5)只能作为通用IO口使用。
②、波特率加倍:波特率 = (2÷32)×((11.0592×1000000/12)/(256-TH1))
TH1 = 256 - 11.0592×1000000/192/波特率
当TH1=250,波特率为9600bps,可以用来验证计算。
注意:11.0592表示晶振频率,单位:MHz
③、波特率不加倍:波特率 = (1÷32)×((11.0592×1000000/12)/(256-TH1))
TH1 = 256 - 11.0592×1000000/384/波特率
当TH1=253,波特率为9600bps
注意:11.0592表示晶振频率,单位:MHz
unsigned char SendBuffer[10];
unsigned char SendBuffer_Index;
unsigned char SendBuffer_Length;
#define OSC_FREQ 11059200L
#define BAUD_Time 1
#if(BAUD_Time==1)
//若波特率加倍,则使用下面参数;
#define BAUD_57600 256 - (OSC_FREQ/192L)/57600L //255
#define BAUD_28800 256 - (OSC_FREQ/192L)/28800L //254
#define BAUD_19200 256 - (OSC_FREQ/192L)/19200L //253
#define BAUD_14400 256 - (OSC_FREQ/192L)/14400L //252
#define BAUD_9600 256 - (OSC_FREQ/192L)/9600L //250
#define BAUD_4800 256 - (OSC_FREQ/192L)/4800L //244
#define BAUD_2400 256 - (OSC_FREQ/192L)/2400L //232
#define BAUD_1200 256 - (OSC_FREQ/192L)/1200L //208
#else
//若波特率不加倍,则使用下面参数;
#define BAUD_9600 256 - (OSC_FREQ/384L)/9600L
#define BAUD_4800 256 - (OSC_FREQ/384L)/4800L
#define BAUD_1200 256 - (OSC_FREQ/384L)/1200L
#endif
#define SYNC 0x33
//函数功能: 定时器1工作在模式2的初始化;
void timer1_initializtion(void)
{ TMOD &= 0x0F;//清除高4位
//TMOD寄存器的bit6(C/T)=0,定时器输入时钟为CPU时钟经过12分频后得到的
//设置GATE1=0,即不允许外部INT1脚控制Timer1;
TMOD |= 0x20;//配置Timer1为方式2(8位自动重装载定时器)
TH1=BAUD_9600; //手动装载TH1;
TL1=BAUD_9600; //初始化计数器的初始值
TR1=1; //当GATE1=0时,TR1=1,表示启动T1开始工作;
ET1=0; //不允许Timer1中断;
}
void Serial_Port_Initialization(void)
{ #if(BAUD_Time==1)
PCON &= 0x7F;PCON |= 0x80;//波特率翻倍
#else
PCON &= 0x7F;//波特率不加倍
#endif
SCON=0x50; //串行控制寄存器: SM0,SM1,SM2,REN,TB8,RB8,TI,RI
//SM1:SM0=01,选择方式1,SM2=0,表示非多机通讯,8-bit UART;
//REN=1,使能接收;
timer1_initializtion();
TI=1; //发送UART的第一个字节,为下次发送做准备;
RI=0;
ES=1; //使能串口接收和发送中断;
EA=1; //开总中断
SendBuffer_Index=0;
SendBuffer_Length=0;
}
//串口中断
void isr_UART(void) interrupt 4 using 1
{ unsigned char temp;
if (RI) //处理接收数据;
{
temp=SBUF; //从串口接收一个字节;
}
if (TI) //处理发送数据;
{
SendBuffer_Index++;
if(SendBuffer_Index<SendBuffer_Length)
{
SBUF=SendBuffer[SendBuffer_Index];
}
}
}
//函数功能:发送数据
void SendData(void)
{
SendBuffer_Index=0;
SendBuffer_Length=0;
SendBuffer[0]=SYNC;SendBuffer_Length++;
SendBuffer[1]='O';SendBuffer_Length++;
SendBuffer[2]='K';SendBuffer_Length++;
SBUF=SendBuffer[SendBuffer_Index];
}
2、定时器1工作在模式2,且定时器0工作在模式3,定时器1只能用作波特率发生器的输入时钟源。
其框图如下:
在定时器不够用时,我们通常会将定时器0工作在模式3,这样定时器0变成2个8位定时器,定时器1就只能工作在模式2,用作波特率发生的输入时钟源。前面已经介绍,就不再叙述了。