当前位置: 首页 > news >正文

单片机-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;}
}

相关文章:

  • Leetcode 3534. Path Existence Queries in a Graph II
  • 每日一道leetcode(不会做学习版,多学一题)
  • 【Redis】缓存|缓存的更新策略|内存淘汰策略|缓存预热、缓存穿透、缓存雪崩和缓存击穿
  • chatshare.xyz激活码使用说明和渠道指南!
  • JavaScript 中深拷贝浅拷贝的区别?如何实现一个深拷贝?
  • mybatis传递多个不同类型的参数到mapper xml文件
  • 本地大模型编程实战(28)查询图数据库NEO4J(1)
  • 苍穹外卖心得体会
  • 笔试专题(十二)
  • 【动态导通电阻】 GaN PiN二极管电导调制对动态 RON 的影响
  • PDF编辑器:Foxit PDF Editor Pro 版功能解析
  • Ubuntu如何查看硬盘的使用情况,以及挂载情况。
  • 浏览器自动化工具:Selenium 和 Playwright
  • 什么是全景相机?
  • 机器人--相机
  • 学习海康VisionMaster之线圆测量
  • stm32wb55rg (4) 启用usart串口
  • OpenAI Embedding 和密集检索(如 BERT/DPR)进行语义相似度搜索有什么区别和联系
  • transformer-实现单层Decoder 层
  • 【探寻C++之旅】第十二章:异常
  • TCL科技一季度净利增超三倍,去年半导体显示业务营收创新高
  • 游客曝九寨沟打网约车被出租车围堵,景区回应:当地无合规网约车
  • 腾讯重构混元大模型研发体系:成立大语言和多模态模型部,提升AI长期技术作战能力
  • 商务部新闻发言人就波音公司飞回拟交付飞机答记者问
  • 一季度我国服务进出口总额19741.8亿元,同比增长8.7%
  • 当AI开始深度思考,人类如何守住自己的慢思考能力?