• 【STM32】通用定时工作原理


    🐱作者:一只大喵咪1201
    🐱专栏:《STM32学习》
    🔥格言:你只管努力,剩下的交给时间!
    请添加图片描述

    🛸通用定时器TIMx简介

    STM32F1 的通用定时器是一个通过可编程预分频器(PSC)驱动的 16 位自动装载计数器(CNT)构成。 STM32 的通用定时器可以被用于:测量输入信号的脉冲长度(输入捕获)或者产生输出波形(输出比较和 PWM)等。

    使用定时器预分频器和 RCC 时钟控制器预分频器,脉冲长度和波形周期可以在几个微秒到几个毫秒间调整。

    STM32 的每个通用定时器都是完全独立的,没有互相共享的任何资源。

    STM3F1 的通用 TIMx (TIM2、 TIM3、 TIM4 和 TIM5)定时器特点包括:

    • 位于低速的APB1总线上
    • 16 位向上、向下、向上/向下自动装载计数器(TIMx_CNT)。
    • 16 位可编程(可以实时修改)预分频器(TIMx_PSC),计数器时钟频率的分频系数为 1~65535 之间的任意数值。
    • 4 个独立通道(TIMx_CH1~4),这些通道可以用来作为:
      A.输入捕获
      B.输出比较
      C. PWM 生成(边缘或中间对齐模式)
      D.单脉冲模式输出
    • 可使用外部信号(TIMx_ETR)控制定时器和定时器互连(可以用 1 个定时器控制另外一个定时器)的同步电路。
    • 如下事件发生时产生中断/DMA:
      A.更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发)
      B.触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)
      C.输入捕获
      D.输出比较
      E.支持针对定位的增量(正交)编码器和霍尔传感器电路
      F.触发输入作为外部时钟或者按周期的电流管理

    通用定时器占了4个,还有4个分别是俩个高级定时器(TIM1和TIM8),俩个基本定时器(TIM5和TIM6),它们各自的功能有所区别

    图

    🛸通用定时器功能模块组成

    图
    这是通用定时器的工作框图,下面本喵将其分为几个部分讲解。

    🚀时基单元

    时基单元包括:

    • 计数器寄存器(TIMx_CNT)
    • 预分频器寄存器 (TIMx_PSC)
    • 自动装载寄存器 (TIMx_ARR)
    1. 计数器寄存器(TIMx_CNT)

    它在框图中的
    图
    这个位置。

    寄存器是一个16位的寄存器

    图
    它的计数范围就是1~65535,超出这个范围就会发生溢出。

    计数器由预分频器的时钟输出CK_CNT驱动,仅当设置了计数器TIMx_CR1寄存器中的计数器使能位(CEN)时, CK_CNT才有效。

    图
    也就是控制寄存器CR1中的位0相当于时钟CK_CNT的开关,只有它使能也就是值位1的情况下CK_CNT才会驱动CNT寄存器进行计数。

    1. 预分频器寄存器 (TIMx_PSC)

    它在框图中的
    图
    这个位置。

    该寄存器同样是一个16位的寄存器,

    图
    它能存放值是范围也是1~65535,它的作用就是将驱动定时器的时钟(图中的CK_PSC)进行分频,该寄存器中的值是多少,就将CK_PSC的时钟进行(PSC[15:0]+1)的分频。至于为什么是加1,是因为预分频计数器是从0开始计数的。

    它是基于一个(在TIMx_PSC寄存器中的)16位寄存器控制的16位计数器,这个控制寄存器带有缓冲器,它能够在工作时被改变。新的预分频器参数在下一次更新事件到来时被采用。
    图
    PSC的分频系数会在它的值的基础上加1,所以将它的值由0改为1,也就是将分频系数由1改到2。由时许图中可以清除的看到,在更新事件产生以后,CNT计数器计数的频率改变了。

    预分频计数器中的值此时也从0加到1,然后再到0,如此往复循环,控制着CK_CNT的频率。

    1. 自动装载寄存器 (TIMx_ARR)

    它在框图中的图
    这个位置。

    该寄存器同样是一个16位的寄存器

    图
    它能存放值是范围也是1~65535,它作用就是给计数器寄存器CNT设置一个参照,CNT中的计数值总是在和ARR中的值比较。

    自动装载寄存器是预先装载的,写或读自动重装载寄存器将访问预装载寄存器。根据在TIMx_CR1寄存器中的自动装载预装载使能位(ARPE)的设置,预装载寄存器的内容被立即或在每次的更新事件UEV时传送到影子寄存器。

    当计数器达到溢出条件(向下计数时的下溢条件)并当TIMx_CR1寄存器中的UDIS位等于’0’时,产生更新事件。更新事件也可以由软件产生。

    图

    在框图中可以看到,自动重装载寄存器ARR的后面是有影子的,这个影子也是一个寄存器,就叫做影子寄存器。

    自动重装载器中的值是影子寄存器给它的,我们都是通过修改影子寄存器中的值,然后影子寄存器再将值给到ARR寄存器中才实现设置计数值的目的的。

    将控制寄存器CR1的位7,也就是ARPE位图
    使能以后,就相当于打开了影子寄存器。

    影子寄存器打开和关闭的区别:

    • 打开:当我们在定时器工作的过程中修改了ARR寄存器中的值后,寄存器ARR中的值不会立马改变,而是在每次的更新事件(UEV)时,将改变后的值传送到影子寄存器,进而改变ARR中的值,也就是改变值的时候是有一个缓冲的。
      图
      UEV是否被允许由CR1寄存器的位1控制。
    • 关闭:当我们在定时器工作的过程中修改了ARR寄存器中的值后,会立刻将改变的值传送到影子寄存器,立刻改变ARR中的值,也就是改变值的时候是没有缓冲的

    图
    在ARPE位为0的时候,ARR中的值从0XFF改变为0X36以后,计数器CNT在计数到36以后就产生了计数器溢出,产生更新事件,发生更新中断。

    图
    在ARPE位为0的时候,ARR中的值从0XF5改变为0X36以后,计数器仍然是在计数到0XF5以后才产生计数器溢出,并没有立刻改变。在计数到0XF5后产生了更新事件后,改变后的值0X36才被传送到影子寄存器,也就是才放在了ARR中,下一次CNT计数到0X36就会产生溢出事件。

    🚀计数模式

    它在框图的
    图
    这个位置。

    计数模式有三种:

    • 向上计数模式
    • 向下计数模式
    • 中央对齐计数模式
    1. 向上计数模式

    在向上计数模式中,计数器从0计数到自动加载值(TIMx_ARR计数器的内容),然后重新从0开始计数并且产生一个计数器溢出事件。

    每次计数器溢出时可以产生更新事件(UEV),在TIMx_EGR寄存器中(通过软件方式或者使用从模式控制器)设置UG位也同样可以产生一个更新事件。

    图
    将该位由软件置1后,并且中断是开启,就可以强制进入中断服务程序。

    内部时钟分频因子不一样时,计数的频率也会不一样。

    下图是当TIMx_ARR=0x36时计数器在不同时钟频率下的动作。

    图
    内部时钟分频因子是1的时候,时钟CK_CNT的频率和内部时钟CK_INT的一样。

    图
    内部时钟分频因子是2的时候,时钟CK_CNT的频率是CK_INT的一半。

    1. 向下计数模式

    在向下模式中,计数器从自动装入的值(TIMx_ARR计数器的值)开始向下计数到0,然后从自动装入的值重新开始并且产生一个计数器向下溢出事件。每次计数器溢出时可以产生更新事件,TIMx_EGR寄存器中(通过软件方式或者使用从模式控制器)设置UG位,也同样可以产生一个更新事件。

    只是计数的方向不一样,其他都和向上计数模式一样。

    1. 中央对齐计数模式

    在中央对齐模式,计数器从0开始计数到自动加载的值(TIMx_ARR寄存器)−1,产生一个计数器
    溢出事件,然后向下计数到1并且产生一个计数器下溢事件;然后再从0开始重新计数。在这个模式,不能写入TIMx_CR1中的DIR方向位。它由硬件更新并指示当前的计数方向。
    图
    此时CR1寄存器中的位4,DIR位是不能用来设置计数方向的,只能由读取现在是处于哪个计数方向。

    图
    该模式和前俩种模式在时序图上的区别就是,CNT计数到ARR值后不变0,而是从ARR开始继续向下计数。

    图
    这是3种模式下CNT计数器寄存器中的值与时间之间的关系曲线,ARR中的值就是参照。

    🚀时钟选择

    时钟源有4个:

    • 内部时钟(CK_INT)
    • 外部时钟模式1:外部输入脚(TIx)
    • 外部时钟模式2:外部触发输入(ETR)
    • 内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频器,如可以配置一个定时
      器Timer1而作为另一个定时器Timer2的预分频器。
    1. 内部时钟源

    这是我们最常用的时钟源,绝大多数情况下使用的都是内部时钟源(CK_INT)。

    图
    这是它在框图中的路线。

    如果禁止了从模式控制器(TIMx_SMCR寄存器的SMS=000),则CEN、 DIR(TIMx_CR1寄存器)和UG位(TIMx_EGR寄存器)是事实上的控制位,并且只能被软件修改(UG位仍被自动清除)。只要CEN位被写成’1’,预分频器的时钟就由内部时钟CK_INT提供。

    SMCR位我们很少用到,本喵不再介绍,其余CEN、DIR、UG位前面都介绍过,我们直接看时序图。

    图
    内部时钟CK_INT是来源于RCC的TIMx的,然后CK_INT经过从模式寄存器处理后给CK_PSC提供时钟源,CK_PSC经过预分频寄存器PSC分频后给CK_CNT提供时钟源,所以在CEN使能以后,内部时钟进行了俩个时钟周期,CK_CNT才有了时钟信号。

    其他三种模式,由于用到的比较少,在涉及到的时候本喵会详细讲解。

    🚀输入捕获

    图
    每个通用寄存器都有4个通道,这个4个通道既能输入捕获也能输出比较。

    每一个捕获/比较通道都是围绕着一个捕获/比较寄存器(包含影子寄存器),包括捕获的输入部分(数字滤波、多路复用和预分频器),和输出部分(比较器和输出控制)。

    图
    捕获过程:

    1. 选择有效输入端: TIMx_CCR1必须连接到TI1输入,所以写入TIMx_CCMR1寄存器中的CC1S=01,只要CC1S不为’00’,通道被配置为输入,并且TM1_CCR1寄存器变为只读。

    图
    通过设置CCMR1寄存器中的CC1S位来设置通道的工作模式。只要不是00,就是输入捕获模式。

    1. 根据输入信号的特点,配置输入滤波器为所需的带宽(即输入为TIx时,输入滤波器控制位是TIMx_CCMRx寄存器中的ICxF位)。假设输入信号在最多5个内部时钟周期的时间内抖动,我们须配置滤波器的带宽长于5个时钟周期。因此我们可以(以fDTS频率)连续采样8次,以确认在TI1上一次真实的边沿变换,即在TIMx_CCMR1寄存器中写入IC1F=0011。

    图
    假设从TI1输入一个信号,我们想捕获它的上升沿,该信号我们知道它最多在5个内部时钟(CK_INT)周期内发生抖动,这些抖都可能会造成误捕获。所以通样以内部时钟(CK_INT)的频率连续采用8次,如果这8次都是高,说明我们捕获的信号是正确的,这样就可以过滤一些信号,所以也叫做滤波器。

    需要将CCMR1寄存器中的
    图
    位IC1F设置成0011。

    如此一来图滤波这一步就完成了,该信号被记作TI1F。

    1. 选择TI1通道的有效转换边沿,在TIMx_CCER寄存器中写入CC1P=0(上升沿)。

    图
    通过将CCER寄存器中的CC1P设为0,此时只有输入信号是高电平的时候才会捕获。此时边缘检测器也设置好了。

    图

    1. 通过设置CCMR1寄存器中的CC1S位,将此时的信号IT1FP1映射再TI1上。

    此时的TI1FP1不仅有一个去向,他可以映射到IC1上,也可以映射到其他通道,体现在图中的红色圈上。

    图
    这一位我们在前面讲解过。

    1. 配置输入预分频器。

    通设置CCMR1寄存器中的IC1PSC1设置预分频系数

    图
    也就是可以设置被捕获信号产生了几次会产生一次捕获事件,就比如捕获高电平,通过我们前面一系列设置后的信号,产生了几次高电平后会触发一次捕获事件。

    1. 设置TIMx_CCER寄存器的CC1E=1,允许捕获计数器的值到捕获寄存器中。

    图

    当捕获使能以后,发生捕获事件时,计数器CNT中的值就会被传送到寄存器CRR1中

    图
    通过该值,我们就可以计算出捕获信号的频率等。

    如果开启了中断,在发生捕获事件时就会进入捕获中断,执行中断服务函数。

    🚀输出比较

    图
    输出比较是框图中的这一部分。

    此项功能是用来控制一个输出波形,或者指示一段给定的的时间已经到时。

    输出比较模式的配置步骤:

    1. 选择计数器时钟(内部,外部,预分频器)

    通常都是选择内部时钟(CK_INT)作为时钟源的。

    1. 将相应的数据写入TIMx_ARR和TIMx_CCRx寄存器中

    ARR的值仍然是计数器CNT产生溢出事件的一个参考值,CRR是发生反转的参考值。

    图
    如上图,当计数器CNT中的值小于CRR中的参考值时,IO口输出的是低电平,当计数器CNT中的值大于CRR中的值并且小于ARR的值的时候,IO输出的是高电平。当然,具体是高电平和低电平是可以设置的。

    此时
    图
    捕获/比较寄存器就设置好了。

    1. 如果要产生一个中断请求和/或一个DMA请求,设置CCxIE位和/或CCxDE位。
    2. 选择输出模式,例如当计数器CNT与CCRx匹配时翻转OCx的输出引脚, CCRx预装载未用,开启OCx输出且高电平有效,则必须设置OCxM=’01 1’、 OCxPE=’0’、 CCxP=’0’和CCxE=’1’。

    图
    模式的选择需要配置的是CCMR1寄存器中的OC1M,具体要配置什么模式,在使用的时候本喵进行详细讲解。

    图
    至此,输出控制部分就配置完了

    1. 设置TIMx_CR1寄存器的CEN位启动计数器
      此时定时器就启动了,开始了输出比较模式。

    TIMx_CCRx寄存器能够在任何时候通过软件进行更新以控制输出波形,条件是未使用预装载寄
    存器(OCxPE=’0’,否则TIMx_CCRx影子寄存器只能在发生下一次更新事件时被更新)。

    图
    计数器CNT中的值一旦和CCR中的值匹配,IO口的电平状态就会发生一次反转。

    🛸总结

    是不是感觉很枯燥乏味?这篇文章一直都是在讲解通用定时器的原理,以及一些重要寄存器的配置。在后面本喵会介绍通用定时器具体使用的实验,这篇原理的介绍也是在为我们使用奠定一个基础。希望对大家有所帮助。

  • 相关阅读:
    JVM 内存设置大小(Xms Xmx PermSize MaxPermSize 区别)
    【秋季热身赛】No.2.数字朋友 -- Java Version
    使用docker-compose 实现发布本地的jar包
    【算法刷题】——美丽整数的最小增量
    docker的问题1
    windows 系统下 设置 redis开机自启动
    练习8:多重子查询
    Win32API操作文件
    【PID优化】基于头脑风暴算法PID控制器优化设计含Matlab源码
    赛桨PaddleScience v1.0 Beta:基于飞桨核心框架的科学计算通用求解器
  • 原文地址:https://blog.csdn.net/weixin_63726869/article/details/126292515