简述
51单片机有两个定时器T0和T1,而我们经常使用的单片机型号是STC89C52,比51多了一个定时器T2.定时器可以用来定时和计数。除了步进电机、超声波等比较特殊的用到定时器外,还可以用定时器进行倒计时、计数、对灯或蜂鸣器或其他的元器件进行状态的反转等。其实有的时候会用定时器体现“延时”的功能,但是用延时函数的话,会使整个程序停止运行,程序就会卡死,那用定时器就会解决这个问题。
1,工作方式
定时器是溢出中断的,定时器T0和T1有四种工作方式,T2有一种工作方式。工作方式是寄存器TMOD控制的,这个寄存器共有8位,高四位是控制定时器T1的,第四位是控制定时器T0的。
D7 | D6 | D5 | D4 | D3 | D2 | D1 | D0 |
GATE | C/ | M1 | M0 | GATE | C/ | M1 | M0 |
对T0和T1来说,M0和M1是设置工作方式的,其他通常置0,
0000 | 使用工作方式0 | 13位定时/计数器 |
0001 | 使用工作方式1 | 16位定时/计数器 |
0010 | 使用工作方式2 | 8位重装载定时/计数器 |
0011 | 使用工作方式3 | T0分成两个独立的8位定时/计数器,T1是停止计数 |
2,初值的计算
如果晶振是11.0592MHz的,内部的时钟频率是外部的12分频,所以内部就是12/11059200,那机械周期为 1/(12/11059200)=921600,加入定时1ms,循环1000次为1s,921600/1000=921.6,所以初值为
TH0=(65536-921)/256;
TL0=(65536-921)%256;
因为用的是方式1,是16位的,2的16次方是62236,2的8次方是256,又因为是溢出中断,所以就得到了上面的初值。如果晶振是12MHz的,那就是括号里就是65535-1000了
3, 定时器初始化
这里定时器T0用的是定时模式。还用到了中断允许寄存器里的EA,ET0和定时器控制寄存器TR0.
void Timer0Init()
{
TMOD|=0X01;//选择为定时器0模式,工作方式1,仅用TR0打开启动。
// TH0=0XFC; //给定时器赋初值,定时1ms
// TL0=0X18;
//5ms / (1/(SYS/12)) SYS系统时钟
TH0 = (65536-1000)/256; //重新赋初值
TL0 = (65536-1000)%256;
ET0=1;//打开定时器0中断允许
EA=1;//打开总中断
TR0=1;//打开定时器
}
定时器1初始化,因为是计数模式,所以从右往左数第5位和第七位(16位计数)置1,所以TMOD|=0x50
void Timer1Init(void)
{
TMOD|=0X50;//选择为定时器1模式,工作方式1
ET1=1;//打开定时器0中断允许
EA=1;//打开总中断
TR1=1;//打开定时器
}
4,中断函数
中断名称不一样,那中断号也不一样
名称 | 终端号 |
/INT0 外部中断0 | 0 |
T0 定时器0中断 | 1 |
/INT1 外部中断1 | 2 |
T1 定时器1中断 | 3 |
TR/RI 串行口中断 | 4 |
uint i;
void Timer0() interrupt 1
{
TH0=0XFC; //给定时器赋初值,定时1ms
TL0=0X18;
i++;
if(i==1000)
{
i=0;
time_1s++;
}
}
void Timer1() interrupt 3
{
}
5,引脚和现象
由图可知定时器1对应的引脚是P3.5
所以每次按下按键后,前两位数码管的计数值+1.
定时器没加任何条件,所以上电之后每过1秒,后两位数码管+1。
6, 52单片机的定时器T2
T2是16位自动重装载的,和T0,T1的工作方式2一样,只是T0和T1是8位的,作为定时器时,只需要在初始化函数中写入初值就行了,中断函数里就不用写了,中断号是5,引脚是P1.0。但是当P1.0作为I/O口时,T2就只能定时或者作为串口时钟,不用用于计数。
初始化函数
sfr T2MOD=0XC9; //寄存器T2MOD定义
void Timer0Init()
{
//50微秒@11.0592MHz
T2MOD = 0; //---- --00 初始化模式寄存器 默认向上计数
T2CON = 0; //0000 0000 初始化控制寄存器 一个中断源,16位自动重装模式
TL2 = 0x00; //设置定时初值
TH2 = 0x4C; //设置定时初值
RCAP2L = 0x00; //设置定时重载值
RCAP2H = 0x4C; //设置定时重载值
TR2 = 1; //定时器2开始计时
IE=0XA0; //1010 0000 打开全局中断,定时器2中断
}
中断函数
void timer_T2() interrupt 5 //中断函数
{
static unsigned char count; //定义变量,记录中断次数
TF2=0; //软件清零定时器2溢出标志位
count++;
if(count==20) //时间为1秒
{
count=0; //清零
led=~led; //状态取反
}
}
现象也是LED灯闪烁。