一、CPU 时序的有关知识(外接晶振为 12MHz )
①振荡周期:为单片机提供定时信号的振荡源的周期(晶振周期或外加振荡 周期)。振荡周期=1/12us。
②状态周期:2 个振荡周期为 1 个状态周期,用 S 表示。振荡周期又称 S 周期或时钟周期。状态周期=1/6us。
③机器周期:1 个机器周期含 6 个状态周期,12 个振荡周期。机器周期=1us。
④指令周期:完成 1 条指令所占用的全部时间,它以机器周期为单位。 指令周期=1~4us。
二、单片机中的定时器:
①51 单片机有两组定时器/计数器,因为既可以定时,又可以计数,故称之为定时器/计数器。
②定时器/计数器和单片机的 CPU 是相互独立的。定时器/计数器工作的过程 是自动完成的,不需要 CPU 的参与。
③51 单片机中的定时器/计数器是根据机器内部的时钟或者是外部的脉冲信号对寄存器中的数据加 1。
三、单片机定时器原理
STC89C5X 单片机内有两个可编程的定时/计数器 T0、T1 和一个特殊功能定时器 T2。
定时/计数器的实质是加 1 计数器(16 位),由高 8 位和低 8 位两个寄存器 THx 和 TLx 组成。
它随着计数器的输入脉冲进行自加 1,也就是每来一个脉冲,计数器就自动加 1,当加到计数器为全 1 时,再输入一个脉冲就使计数器回零,且计数器的溢出使相应的中断标志位置 1,向 CPU 发出中断请求(定时 /计数器中断允许时)。
如果定时/计数器工作于定时模式,则表示定时时间已到; 如果工作于计数模式,则表示计数值已满。可见,由溢出时计数器的值减去计数 初值才是加 1 计数器的计数值。
(1)51 单片机定时/计数器结构
上图中的 T0 和 T1 引脚对应的是单片机 P3.4 和 P3.5 管脚。
51 单片机定时/ 计数器的工作由两个特殊功能寄存器控制。
TMOD 是定时/计数器的工作方式寄存器,确定工作方式和功能。
TCON 是控制寄存器,控制 T0、 T1 的启动和停止及 设置溢出标志。
1,工作方式寄存器 TMOD
TMOD 用于设置定时/计数器的工作方式,低四位用于 T0,高四位用于 T1。其格式如下:
①GATE 是门控位。
GATE=0 时,用于控制定时器的启动是否受外部中断源信号的影响。只要用软件使 TCON 中的 TR0 或 TR1 为 1,就可以启动定时/计数器工作。
GATA=1 时,要用软件使 TR0 或 TR1 为 1,同时外部中断引脚 INT0/1 也为高电平时,才能启动定时/计数器工作。即此时定时器的启动条件,加上了 INT0/1 引脚为高电平这一条件。
②C/T :定时/计数模式选择位。C/T =0 为定时模式;C/T =1 为计数模式。
③ M1 M0:工作方式设置位。定时/计数器有四种工作方式。
2,控制寄存器 TCON
TCON 的低 4 位用于控制外部中断。TCON 的高 4 位用于控制定时/计数器的启动和中断申请。其格式如下:
TF1(TCON.7):T1 溢出中断请求标志位。T1 计数溢出时由硬件自动置 TF1 为 1。CPU 响应中断后 TF1 由硬件自动清 0。T1 工作时,CPU 可随时查询 TF1 的 状态。所以,TF1 可用作查询测试的标志。TF1 也可以用软件置 1 或清 0,同硬 件置 1 或清 0 的效果一样。
TR1(TCON.6):T1 运行控制位。TR1 置 1 时,T1 开始工作;TR1 置 0 时, T1 停止工作。TR1 由软件置 1 或清 0。所以,用软件可控制定时/计数器的启动 与停止。
TF0(TCON.5):T0 溢出中断请求标志位,其功能与 TF1 类同。
TR0(TCON.4):T0 运行控制位,其功能与 TR1 类同。
(2)定时/计数器的工作方式
1,方式 0
方式 0 为 13 位计数,由 TL0 的低 5 位(高 3 位未用)和 TH0 的 8 位组成。 TL0 的低 5 位溢出时向 TH0 进位,TH0 溢出时,置位 TCON 中的 TF0 标志,向 CPU 发出中断请求。
门控位 GATE 具有特殊的作用。
当 GATE=0 时,经反相后使或门输出为 1,此时仅由 TR0 控制与门的开启,与门输出1 时,控制开关接通,计数开始。
当 GATE=1时,由外中断引脚信号控制或门的输出,此时控制与门的开启由外中断引脚信号和TR0 共同控制。当 TR0=1 时,外中断引脚信号引脚的高电平启动计数,外中断引脚信号引脚的低电平停止计数。这种方式常用来测量外中断引脚上正脉冲的宽度。计数模式时,计数脉冲是 T0 引脚上的外部脉冲。计数初值与计数个数的关 系为:X=2(13)-N。其中 2(13)表示 2 的 13 次方
2,方式 1
方式 1 的计数位数是 16 位,由 TL0 作为低 8 位,TH0 作为高 8 位,组成了 16 位加 1 计数器。计数初值与计数个数的关系为:X=2(16)-N。
3,方式 2
方式 2 为自动重装初值的 8 位计数方式。方式 2 特别适合于用作较精确的脉冲信号发生器。计数初值与计数个数的关系为:X=2(8)-N。
4,方式 3
方式 3 只适用于定时/计数器 T0, 定时器 T1 处于方式 3 时相当于 TR1=0, 停止计数。工作方式 3 将 T0 分成为两个独立的 8 位计数器 TL0 和 TH0。
这几种工作方式中应用较多的是方式 1 和方式 2。定时器中通常使用定时器方式 1,串口通信中通常使用方式2。
四、定时器配置
①对 TMOD 赋值,以确定 T0 和 T1 的工作方式,如果使用定时器 0 即对 T0 配 置,如果使用定时器 1 即对 T1 配置。
②根据所要定时的时间计算初值,并将其写入 TH0、TL0 或 TH1、TL1。
③如果使用中断,则对 EA 赋值,开放定时器中断。
④使 TR0 或 TR1 置位,启动定时/计数器定时或计数。
机器周期是 CPU 完成一个基本操作所需要的时间。 其计算公式是:机器周期=1/单片机的时钟频率。
51 单片机内部时钟频率是外部 时钟的 12 分频,也就是说当外部晶振的频率输入到单片机里面的时候要进行 12 分频。比如说你用的是 12MHZ 晶振,那么单片机内部的时钟频率就是12/12MHZ, 当你使用 12MHZ 的外部晶振的时候,机器周期=1/1M=1us。
如果我们想定时 1ms的初值是1ms/1us=1000,也就是要计数 1000 个,初值=65535-1000+1 =2(16)-1000 =64536=FC18H,所以初值即为 THx=0XFC,TLx=0X18。 知道了如何计算定时/计数器初值,那么想定时多长时间都可以计算出,当然由于定时计数器位数有限,我们不可能直接通过初值定时很长时间,如果要实现很长时间的定时,比如定时 1 秒钟。可以通过初值设置定时 1ms,每当定时 1ms 结束后又重新赋初值,并且设定一个全局变量累计定时 1ms 的次数,当累计到 1000 次,表示已经定时 1 秒了。(delay函数光荣退休)
例子:
void Timer0Init()
{
TMOD|=0X01; //选择为定时器 0 模式,工作方式 1,仅用 TR0 打开启动。
ET0=1; //打开定时器 0 中断允许
EA=1; //打开总中断
TR0=1; //打开定时器
}
五、实例
现象:
D1 灭 灭 亮 亮 灭 灭
D2 灭 亮 灭 亮 灭 亮
(一个灭/亮字代表1s)
#include"reg52.h"
typedef unsigned int u16;
typedef unsigned char u8;
sbit led0=P2^0;
sbit led1=P2^1;
void timer0();
void timer1();
void main()
{
timer0();
timer1();
while(1);
}
void timer0() //打开定时器0
{
TMOD=TMOD|0X01;//方式1
ET0=1;
EA=1;
TR0=1;
}
void timer1() //打开定时器1
{
TMOD=TMOD|0X10; //方式1
ET1=1;
EA=1;
TR1=1;
}
void time0() interrupt 1 //计数完令led0翻转
{
static u16 i;//static变量默认初始值为0,不用赋值(百度说的)
TH0=0XFC; //设置定时1ms
TL0=0X18;
i++;
if(i==2000) //通过循环来定时2s
{
i=0;
led0=~led0;
}
}
void time1() interrupt 3 //计数完令led1翻转
{
static u16 j;//static变量默认初始值为0,不用赋值(百度说的)
TH1=0Xfc; //设置定时1ms
TL1=0X18;
j++;
if(j==1000) //通过循环来定时1s
{
j=0;
led1=~led1;
}
}