
51单片机入门学习(三):定时器
51定时器
目录
(1)定时器/计数器工作方式寄存器TMOD 不可位寻址(就是不能对单独的位进行置0/1操作)
(2)定时器/计数器控制方式寄存器TCON 可位寻址(可以对单独的位定义)
(3)配置定时器/计数器的初值——高八位THx寄存器与低八位寄存器TLx
1.定时器寄存器
2.定时器两个重要的寄存器
(1)定时器/计数器工作方式寄存器TMOD 不可位寻址(就是不能对单独的位进行置0/1操作)
高四位是定时器1,低四位是定时器0;
GATE是门控制位,一般设置TMOD寄存器的GATE=0与TCON寄存器的TR0=1或者TR1=1来开启定时器/计数器。根据下面框图的逻辑电路可知道
当GATE=0,TR0=1时,才能够开启定时器/计数器的开关,
C/T是定时器和计数器选择位,C/T=0是定时器,对系统时钟12分频后的脉冲进行计数;
C/T=1是计数器,计数器对外部输入引脚T0(P3.4),或T1(P3.5)的外部脉冲计数;
M1M0是工作方式选择位,关系如下:
一般选择配置M1M0为01模式
综上所述:TMOD 的配置可以直接配置为
TMOD=0X01;
也可这样写:
当选择定时器0:
TMOD&=0XF0;//前四位保持不变,后四位清零,方便赋值
TMOD|=0X01;//前四位不变,后四位赋值01,即M1M0为01;
当选择定时器1:
TMOD&=0X0F;//后四位保持不变,前后四位清零,方便赋值
TMOD|=0X10;//后四位不变,前四位赋值01,即M1M0为01;
(2)定时器/计数器控制方式寄存器TCON 可位寻址(可以对单独的位定义)
这里寄存器的低四位与上一节的外部中断有关,定时器用到的是高四位,
TF0——定时器/计数器T0溢出中断标志位。我们要把它关闭置0,防止产生中断,即TF0=0;
TF1同理;
TR1、TRO—计数运行控制位:TR0=1开启定时器/计数器
综上所述,TCON寄存器需要配置的就是
TF0/TF1=0,TR0/TR1=1;
(3)配置定时器/计数器的初值——高八位THx寄存器与低八位寄存器TLx
定时器是一个16位的,十六进制的,由高八位寄存器THx,低八位TLx组成,计满65535(2*16-1)之后,再输入一个信号,计数器就会堆栈溢出了,溢出位置是TCON寄存器的TFx位置,同时向CPU请求中断。
定时器一旦启动,它便在原来的数值上开始加1计数,若在程序开始时,我们没有设置THO和 TLO,它们的默认值都是 0,假设时钟频为12MHz,机器周期=12个时钟周期,那么此时机器周期就是12*(1/12MHz)=1μs,计满THO和TL就需要2*16-1=65535个数,再来一个脉冲计数器溢出,随即向CPU申请中断。因此溢出一次共需65536μs,约等于65.5ms(1ms=1000μs),则时钟频为12MHz的定时器最多定时65.5ms,如果定时50ms,那么溢出一次共需50000μs,就要计数50000次,THx和TLx中应该装入的总数是65536-50000=15536,
把15536对256求模:15536/256=60装入THx中,
把15536对2556求余:15536%256=176装入TLx中。
当用定时器的方式1时,设定时器产生一次中断的时间为t,(即定时的时间),设机器周期为T,那么需要计数的个数N=t/T,装入THX和TLX中的数分别为
THx=(65536-N)/256
TLx=(65536-N)%256
若时钟频率为11.0592MHz,则机器周期T=12*(1/11.0592MHz)=1.09μs,根据N=t/T最多能够定时t=65535*1.09μs=71.4ms;
若要定时50ms,N=50ms/1.09μs=45872;
若时钟频率为12Mhz,定时50ms,N=50000;
当需定时1s(1000ms>65ms)时,20次50ms的定时器中断后便认为是1s,这样便可精确控.
如果觉得麻烦,可以用stc软件直接生成初值;
(4)配置定时器的中断
根据上一节的内容,我们要依次打开定时器中断,总中断,优先级:
ET0=1;EA=1;PT0=0;
3.定时器的初始化配置
通过上面的介绍,我们可以掌握初始化配置定时器的步骤:
TMOD寄存器 (选择定时器0/1,配置工作模式)
TCON寄存器(配置FTX,TRX)
THX/TLX寄存器(配置初值)
中断寄存器(配置中断标志位)
//*****时钟频率为11.0592MHz,配置一个工作模式为1,定时50ms的定时器0*****
void int0_init()
{
TMOD&=0XF0;\\高四位不变,后四位清零
TMOD|=0X01;\\选择定时器0,配置工作模式1
TF0=0;\\关闭中断溢出标志位,防止产生中断
TR0=1;\\开启定时器
TH0=(65535-45872)/256//配置初值 取模,数值放入高八位寄存器
TL0=(65535-45872)%256//配置初值 取余,数值放入低八位寄存器
ET0=1;\\打开定时器中断允许标志位
EA=1;\\开启总中断允许标志位
PT0=0;\\打开优先级
}
4.定时器的使用
定时器配置后,使用定时器要用到中断服务函数,上一节已经介绍了中断服务函数的格式,
void Int0_Routine(void) interrupt 0;
void Timer0_Rountine(void) interrupt 1;//定时器T0
void Int1_Routine(void) interrupt 2;
void Timer1_Rountine(void) interrupt 3;
void UART_Routine(void) interrupt 4;//串口
void Timer2_Routine(void) interrupt 5;
void Int2_Routine(void) interrupt 6;//外部中断
void Int3_Routine(void) interrupt 7
中断源是定时器T0,它的中断号为1,所以中断服务函数为:
void Timer0_Rountine(void) interrupt 1
{
执行语句;
}
举个简单的例子:用定时器实现LED以1s闪烁,这里用一个继电器控制LED。
#include <REGX52.H>
sbit LED=P0^0; //led
sbit SHAKE=P3^4;//P3^4是定时器T0的引脚,接继电器的信号口
void main()
{
Time0_init();//调用定时器
}
void Time0_init()
{
TF0=0;//关闭中断溢出标志位
TR0=1;//打开定时器
TMOD&=0XF0;//后四位清零,高四位不变
TMOD|=0x01; //选择定时器0,配置工作模式1
TL0 = 0x66; //设置定时初始值 用stc软件生成1ms的初值
TH0 = 0xFC; //设置定时初始值
ET0=1;//打开定时器中断
EA=1;//打开总中断
PT0=1;//设置优先级
}
void Timer0_Rountine(void) interrupt 1
{
unsigned int tim0count;//初始化一个数
TL0 = 0x66; //设置定时初始值 这里要赋初值,否则系统默认为0
TH0 = 0xFC; //设置定时初始值
tim0count++;
if(tim0count>=1000)//当循环到1000,就已经定时了1s,if语句就会执行
{
tim0count=0;//这里重新清零
LED=~LED;//led闪烁
}
}
这里定时器T0是P3^4引脚
更多推荐
所有评论(0)