51单片机-定时器

定时器/计数器⏰

CPU时序的相关知识时间⌛

  • 振荡周期:为单片机提供定时信号的振荡源的周期(晶振周期或外加振荡周期)
  • 状态周期:2个振荡周期为1个状态周期,用S表示。振荡周期又称S周期或时钟周期。
  • 机器周期:1个机器周期含6个状态周期,12个振荡周期。
  • 指令周期:完成1条指令所占用的全部时间,它以机器周期为单位。

例如:外接晶振为12 MHz时,51单片机相关周期的具体值为:

  • Hz 是赫兹,频率单位, 1 MHz(兆赫) = 1000 KHz (千赫)= 1000000 HZ
  • 振荡周期=1/12 us;
  • 状态周期=1/6 us;
  • 机器周期=1 us;
  • 指令周期=1~4 us;

定时器介绍📃

  • 传统51单片机有两组定时器/计数器,因为既可以定时,又可以计数,故称之为定时器/计数器

  • 定时器/计数器和单片机的CPU是相互独立的。定时器/计数器工作的过程是自动完成的,不需要CPU的参与。

  • 51单片机中的定时器/计数器是根据机器内部的时钟 或者是外部的脉冲信号对寄存器中的数据加1。

  • 有了定时器/计数器之后,可以增加单片机的效率,一些简单的重复加1的工作可以交给定时器/计数器处理。CPU转而处理一些复杂的事情。同时可以实现精确定时作用。

  • 定时器作用:

    (1)用于计时系统,可实现软件计时,或者使程序每隔一固定时间完成一项操作

    (2)替代长时间的Delay,提高CPU的运行效率和处理速度

    (3)...

STC89C52定时器资源⛽

  • 定时器个数:3个(T0、T1、T2),T0和T1与传统的51单片机兼容,T2是此型号单片机增加的资源
  • 注意:定时器的资源和单片机的型号是关联在一起的,不同的型号可能会有不同的定时器个数和操作方式,但一般来说,T0和T1的操作方式是所有51单片机所共有的

定时器原理📳

  • 定时/计数器实质上是一个加1计数器。它随着计数器的输入脉冲进行自加1,也就是每来一个脉冲,计数器就自动加1,当加到计数器为全1时,再输入一个脉冲就使计数器回零,且计数器的溢出使相应的中断标志位置1,向CPU发出中断请求(定时/计数器中断允许时)。如果定时/计数器工作于定时模式,则表示定时时间已到;如果工作于计数模式,则表示计数值已满。

    可见,由溢出时计数器的值减去计数初值才是加1计数器的计数值。

  • 简单的说定时器在单片机内部就像一个小闹钟一样,根据时钟的输出信号,每隔"一秒",计数单元的数值就增加一,当计数单元数值增加到"设定的闹钟提醒时间"时,计数单元就会向中断系统发出中断申请,产生"响铃提醒",使程序跳转到中断服务函数中执行。

定时器的工作模式💼

STC89C52 的 T0 和 T1 均有四种工作模式:

  • 模式0:13位定时器/计数器
  • 模式1:16位定时器/计数器*(常用)*
  • 模式2:8位自动重装模式
  • 模式3:两个8位计数器

定时器的结构⚙

这里我分析一下定时器0最常用的模式1,关于其他模式可以再数据手册查看

定时器部分:

  • SYSclk是系统时钟就是晶振周期。
  • 定时器可以由 0Pin 外部计数脉冲触发,也可以通过通过机器周期来触发。

门控端部分:

  • 门控位GATE具有特殊的作用。

  • 当GATE=0时,经反相后使或门输出为1,此时仅由TR0控制与门的开启,与门输出1时,控制开关接通,计数开始;

  • 当GATE=1时,由外中断引脚信号控制或门的输出,此时控制与门的开启由外中断引脚信号和TR0共同控制。当TR0=1时,外中断引脚信号引脚的高电平启动计数,外中断引脚信号引脚的低电平停止计数。

    这种方式常用来测量外中断引脚上正脉冲的宽度。

  • 所以我们一般情况下将GATE配置为0,TR0配置为1

计数器部分:

  • 方式1的计数位数是16位,由TL0作为低8位,TH0作为高8位,组成了16位加1计数器 。
  • 计数个数与计数初值的关系为:X=2^16-N

中断系统部分:

  • 我们需要把ET和EA配置为1

相关寄存器📕

定时器控制寄存器TCON

定时器模式寄存器

M1、M0 :控制定时器模式。"00"为模式0,"01"为模式1,"10"为模式2,"11"为模式3

定时器初始化🚩

初始化程序应完成如下工作:

  • 对TMOD赋值,以确定T0和T1的工作方式。
  • 计算初值,并将其写入TH0、TL0或TH1、TL1。
  • 中断方式时,则对EA赋值,开放定时器中断。
  • 使TR0或TR1置位,启动定时/计数器定时或计数。

代码实例📝

c 复制代码
#include <REGX52.H>
/**
  * @brief  定时器0初始化,1毫秒@11.0592MHz
  * @param  无
  * @retval 无
  */
void Timer0Init(void)       
{   
    //TMOD = 0x01;   这种方式后面配定时器1的时候,定时器0就会受到影响
    TMOD &= 0xF0;       //设置定时器模式 与运算使得前四位保留,后四位清除
    TMOD |= 0x01;       //设置定时器模式 或运算使得前四位保留,最低位置1
    TL0 = 0x66;     //设置定时初始值
    TH0 = 0xFC;     //设置定时初始值
    TF0 = 0;        //清除TF0标志
    TR0 = 1;        //定时器0开始计时
    ET0=1;          //中断配置Timer0开关
    EA=1;           //中断配置总开关
    PT0=0;          //优先级
}
​
/*定时器中断函数模板
void Timer0_Routine() interrupt 1
{
    static unsigned int T0Count;
    TL0 = 0x66;     //设置定时初始值
    TH0 = 0xFC;     //设置定时初始值
    T0Count++;      //T0Count计次,对中断频率进行分频
    if(T0Count>=1000)//分频1000次,1000ms
    {
        T0Count=0;
        
    }
}
*/
相关推荐
谭光志16 分钟前
工具塞满上下文窗口怎么办?深度拆解 AI Agent Tool Search 按需加载实现原理
前端·后端·ai编程
她说..20 分钟前
Java 默认值设置方式
java·开发语言·后端·springboot
foggyprojects26 分钟前
从0开始,一句话启动AI DataAgent
后端·数据分析·ai编程
郡杰26 分钟前
一些基础和问题解决
后端
陈随易44 分钟前
前端项目部署只要30秒
前端·后端·程序员
YIAN1 小时前
从零手写文件读取 MCP 服务:一文吃透 Model Context Protocol 全链路通信原理
前端·后端·mcp
Imchendiana1 小时前
《狂人日记NO.9》— 前后端一把梭,我的全栈实录
前端·后端
学渣超1 小时前
记一次分布式事务数据不一致的排查之旅:从超时到索引,层层剥茧
java·后端·架构
北冥you鱼1 小时前
Go 语言读取链上数据:从基础到实战
开发语言·后端·golang
程序员cxuan2 小时前
Claude Code 为了封禁中国用户,竟然在代码里下毒
人工智能·后端·程序员