单片机-89C51部分:8、定时器

飞书文档https://x509p6c8to.feishu.cn/wiki/IUiswrNZpij2jpkbU6UcmCBpn9b

一、简介

定时器,顾名思义,是用来控制时间的。它可以根据设定的时间间隔,准时产生触发信号,用于控制程序的执行流程。

我们为什么要使用定时器呢?

回想一下之前写的程序,在实现延时这一功能时,我们使用了delay() 函数,这个函数并没有采用任何外设,只是写了两个循环嵌套,让cpu计数,当计数完成也就代表延时结束,简单点说就是让cpu通过不停的计数来消耗时间,所以这种方式有个很大的弊端,就是当cpu “死跑” 延时的时候,是做不了其他事情的,如果这个时候需要一个工具来帮助cpu完成计时,这就是定时器的作用。

51单片机有两个定时器,T0和T1。这两个定时器可以通过寄存器进行配置,可实现定时和计数功能。

定时器的本质原理是,每经过一个机器周期,计数器的值就加1。当计数器的值达到设定的值时,就会产生一个中断信号,通知CPU进行相应的处理。
在定时器模式下,计数器的输入信号是机器周期。因此,当配置为定时器使用时,每经过1个机器周期,计数存储器的值就加1。这种方式可以用来产生定时信号,以控制时间间隔或者实现定时操作。比如在工厂自动化生产线、智能家居控制、网络通信等场景中,都需要定时器来进行精准的时间控制。

而在计数器模式下,计数器的输入信号是外部信号。当配置为计数器时,每来一个负跳变信号就加1,以此达到计数的目的。这种方式可以用来对外部事件进行计数或者脉冲测量。如统计按键按下的次数,统计电机编码器转的圈数。

我们可以根据具体的需求来选择使用定时器还是计数器。比如,在需要精确控制程序执行时间的情况下,我们可以选择使用定时器;而在需要对某些事件进行计数时,则可以选择使用计数器。

二、定时/计数器相关的寄存器

模式选择

 STC89C52RCT0T1均有4种工作模式:

  • 模式0:13位定时器/计数器
  • 模式116位定时器/计数器 (常用)13位适用于短时间计时,16位适用于较长时间计时
  • 模式2:8位自动重装模式时器/计数器 此模式下,计时到设定值后会自动重新开始计时,实现周期性计时功能
  • 模式3:两个8位计数器(禁用定时器1,把定时器2设置为两个8位计数器)


 

TMOD这个寄存器是不可位寻址的,
如要想让M0这位置一的话,直接 M0=1;这个写法是错误的,因为它不能位寻址。
只能 TMOD = 0x01(00000001)

例如初始化定时器0的模式为模式1,
设置TMOD寄存器的第0位M0为1,第1位M1为0 
0b0000 0001
TMOD=0x01;                //设置16bit定时器模式

如果是初始化定时器1的模式为模式1
0b0001 0000
TMOD=0X10;

模式1:时钟源选择

0b 0000 0001

TMOD = 0x01

C/T寄存器:时钟来源选择

来源一:SYSclk,系统时钟,作为定时模式(常用)

来源二:外部脉冲输入引脚T0,也就是P3.4引脚,作为计数模式

两个定时器的C/T寄存器对应TMOD寄存器的第2位和第6位
这里设置定时器0时钟源为系统时钟,则设置TMOD第2位为0
0b0000 0001
TMOD=0x01;

系统时钟:12T/6T 分频模式选择

上面的开关是选择分频器,选择12分频,假设芯片时钟是12Mhz进行12分频就是1Mhz(1MHz=1000kHz,1kHz=1000Hz每秒钟计数100万次),每个计数一次就是1us,这样配置通这条线路送到计数器,每隔1us就要记1次数。

在烧录时设置,默认为12T模式

开关控制

非门:输入1,输出0,输入0,输出1

或门:输入任意一个为1,输出都为1

与门:输入两个都为1,输出才是1,其它都是0

GATEINT0TR0一起作为定时器开关的控制寄存器

GATE

INT0

TR0

定时器状态

0

/

1

使能

/

1

1

使能

当GATE为0时,经过非门变为1,再与INT0通过或门,此时无论INT0为0/1,都会输出1,然后与TR0经过与门,TR0也要为1,最终才能输出1。

当INT0为1时,不管GATE是0/1,通过或门都输出1,然后与TR0经过与门,TR0也要为1,最终才能输出1。

GATE门控位;GATE=0,设置软件启动;

INT0INT0=1 设置为硬件启动,INT0对应外部中断0,也就是可以通过外部中断0可以控制定时器开关。

这里我们设置为软件启动
两个定时器的GATE寄存器对应TMOD寄存器的第3位和第7位
这里设置定时器0使能,则设置TMOD第3位为0
0b0000 0001
TMOD=0x01;

TR0 运行控制位

可位寻址

TR0 = 1;     //使能定时器0开始计时

最终

TMOD=0x01;  //设置定时器0为:模式1、系统时钟源、软件启动
TR0 = 1;     //使能定时器0开始计时

预装载值

TL0 TH0:定时器预装载值

16位=TL0寄存器的8bit+TH0寄存器的8bit

可以看到,计数器里有两个时基单元,TL0(低8位)和 TH0(高8位)总共16位,所以叫16位定时/计数器,它最多可以计数 2^16=65535次,也就是定时器增加到65536时,会触发一次溢出。

单片机系统时钟是11.0592MHz时,在12T模式,定时器频率为11.0592MHz除12为921600Hz,就是一秒计数921600次,10ms计数9216次。 20ms 9216*2

如果我们需要定时器10ms溢出一次,我们可以设置定时器的预装载值为65536-9216,这样,计算9216次后达到65536就会溢出一次。

//10ms定时器
TIMS=65536-9216;
TL0=TIMS;
TH0=TIMS>>8;

溢出中断

TF0:溢出标志位

ET0=1; //使能定时器0中断
EA=
1;  //使能总中断

所以,下方是使能定时器0定时10ms的完整程序

#include <reg52.h>

#define TIMS (65536-9216)
                    
void main()
{
        TMOD = 0x01;                    //配置定时器0为16位定时器,TH0、TL0全用
        TH0 = TIMS >> 8;                //设置定时初值高8位
        TL0 = TIMS;                     //设置定时初值低8位
        ET0 = 1;  //开启定时器0中断                                         
        EA  = 1;  //开启全局中断                                                     
        TR0 = 1;  //定时器0开始计数       
        while(1);
}

//10ms执行一次
void Timer0() interrupt 1
{
        //每次产生中断后重新设置下次定时器初值
        TH0 = TIMS >> 8;
        TL0 = TIMS;
        //这里可以写中断函数要执行的操作
}

如果我们想让LED间隔1s闪烁,我们可以添加指示灯操作,添加变量count,每次触发定时器中断时加1,加到1000ms,也就是1s时,改变LED的状态,就可以实现啦。

#include <reg52.h>

#define TIMS (65536-9216)
sbit led = P2^7;
unsigned int count = 0;
                    
void main()
{
        TMOD = 0x01;                    //配置定时器0为16位定时器,TH0、TL0全用
        TH0 = TIMS >> 8;                //设置定时初值高8位
        TL0 = TIMS;                     //设置定时初值低8位
        ET0 = 1;  //开启定时器0中断                                         
        EA  = 1;  //开启全局中断                                                     
        TR0 = 1;  //定时器0开始计数       
        while(1);
}

//10ms执行一次
void Timer0() interrupt 1
{
        //每次产生中断后重新设置下次定时器初值 - 10毫秒产生1次中断
        TH0 = TIMS >> 8;
        TL0 = TIMS;
        //1000毫秒执行一次P1电平反转
        count++;
        if(count >= 100)
        {
                led = ~led;
                count = 0;
        }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值