目的:利用定时器,解决软件延迟不精准问题。
实现定时功能的几种方法:
1.软件定时:软件定时不占用硬件资源,但占用了CPU时间,降低了CPU利用率。
2.采用时基电路定时:例如采用555电路。
3.采用可编程芯片定时:这种定时芯片的定时值及定时范围很容易用软件来确定和修改,此时芯片定时功能强,使用灵活。
4.单片机定时器、扩展定时器芯片。(单片机内部集成有定时器的芯片)
IAP15F2K60S2:定时器0、1、2与89C52系列单片机一致
IAP15W4K58S4:定时器0、1、2、3、4
STC8A8K64S4A2:定时器0、1、2、3、4
定时器/计数器实质是加1的16位计数器,由高8位和低8位两个寄存器组成。
定时器/计数器的使用:
1.配置AUXR辅助寄存器;2.配置TMOD工作方式寄存器;3.装载计数初值,高八位装载在TH0,低八位装载在TL0;4.配置TCON控制寄存器;5.配置中断允许寄存器IE
具体每位所代表的内容见说明书:
AUXR辅助寄存器:用于是否兼容传统8051单片机,不可位寻址。
TMOD工作方式寄存器:确定工作方式和功能,低四位用于T0,高四位用于T1,不可位寻址。
计数器/定时器-计数(定时)寄存器:用于计数器/定时器的计数或者定时。定时器0:TL0定时器低八位寄存器,TH0定时器0高八位寄存器。
模式0:16位自动重装载模式(一般使用模式0)
定时器模式时有:N=t/Tcy(Tcy为机器周期)(t为所需计时时间)
计数初值计算的公式为:X=2的16次方(即65536)-N
即每次给定时器的计数初值为X,从X往上依次计数,直到计数到65536时计满溢出,向CPU发送信息,定时结束,重新装载计数初值X再次计数。其中X的值要化作二进制,装载在TH0(高八位)和TL0(低八位)中。
TCON控制寄存器:控制T0、T1的启动和停止及设置溢出标志,可位寻址。
IE中断允许寄存器:是否允许中断,可位寻址
15系列单片机的晶振周期等于机器周期
注:可位寻址,是说在单片机头文件中对该寄存器的位有定义,否则则是不可位寻址。说明书与头文件是相对应的,参照说明书即可。
定时器的配置方法:
1.根据说明书进行配置,注意区分可位寻址和不可位寻址的寄存器。
2.使用下载器进行生成,具体如下图:
注:无论使用哪种方法,都需要再配置中断允许寄存器EA=1;ET0=1;
示例程序如下:
1.使用定时器0(以5ms为例,根据说明书配置),LED1 1s闪烁1次
#include<STC15F2K60S2.H>
unsigned char tt=0;
void main(void)
{
P2=0XA0;P0=0X00;P2=0X80;P0=0XFF; //初始化程序
//以下配置程序为对照说明书进行,定时时间以5ms为例
AUXR=0X80; //对照说明书,定时器0速度控制位置1,速度是传统8051的12倍,不分频
TMOD=0XF0; //选择使用定时器0,16位自动重装载模式
TH0=0X28; //装载计数初值对应的二进制数的高八位
TL0=0x00; //装载计数初值对应的二进制数的低八位
TF0=0; //清零定时器0的溢出中断标志位,一般使用前先进行清零操作
TR0=1; //定时器0开始计数,若TR0=0则禁止T0计数
EA=1;ET0=1; //允许中断
while(1)
{
}
}
void Timer0(void) interrupt 1 //定时器0一定使用中断1
{
tt++;
if(tt==200) //200次也就是1s
{
tt=0;
P00=~P00;
}
}
2.使用定时器0(以5ms为例,使用下载器配置)数码管正计时1s变化1次)
#include<STC15F2K60S2.H>
unsigned char tt=0;
unsigned char num=0;
unsigned char tab[]={0XC0,0XF9,0XA4,0XB0,0X99,0X92,0X82,0XF8,0X80,0X90,0X88,0X83,0XC6,0XA1,0X86,0X8E};
void Timer0Init(void);
void main(void)
{
P2=0XA0;P0=0X00;P2=0X80;P0=0XFF; //初始化程序
P2=0XC0;P0=0X01;P2=0XFF;P0=0XFF; //数码管初始化程序,打开第一个数码管
Timer0Init();
EA=1;ET0=1;
while(1)
{
}
}
//下面这个函数由下载器生成,只需要在前面调用即可
void Timer0Init(void) //5毫秒@11.0592MHz
{
AUXR |= 0x80; //定时器时钟1T模式
TMOD &= 0xF0; //设置定时器模式
TL0 = 0x00; //设置定时初值
TH0 = 0x28; //设置定时初值
TF0 = 0; //清除TF0标志
TR0 = 1; //定时器0开始计时
}
void Timer0(void) interrupt 1
{
tt++;
if(tt==200)
{
tt=0;
P0=tab[num];
num++;
if(num==16)num=0; //num=16后,超出数组范围,归0重计时
}
}
两个程序中while循环内部均为空,程序只执行中断1中的命令。定时器0对应的是中断1。