精华内容
下载资源
问答
  • STM32定时器

    2013-08-31 15:40:02
    直接寄存器控制STM32定时器,控制一个led的闪烁,简单的介绍了STM32定时器的控制方法
  • stm32 定时器

    2012-10-13 13:46:59
    stm32定时器定时周期采集测距传感器采集的距离的值,并通过显示屏显示
  • stm32定时器

    2018-12-09 11:04:03
    对于stm32定时器部分的几个重要概念记录一下。 死区插入这个概念还不是很清楚,先记录在此,以后注释。

    对于stm32定时器部分的几个重要概念记录一下。
    在这里插入图片描述
    在这里插入图片描述
    PWM中一个通道捕获周期,一个捕获计数值
    增量式编码器可以直接接到此接口
    死区插入这个概念还不是很清楚,先记录在此,以后注释。

    展开全文
  • STM32 定时器

    千次阅读 2017-03-21 12:19:30
    STM32定时器的预装载寄存器与影子寄存器之间的关系(整理)   (2016-08-05 01:48:43) 转载▼     在STM32F10xxx系列的32位MCU上,定时器资源十分丰富,包括高级控制定时器,通用...

    STM32定时器的预装载寄存器与影子寄存器之间的关系(整理)

     (2016-08-05 01:48:43)
       

    在STM32F10xxx系列的32位MCU上,定时器资源十分丰富,包括高级控制定时器,通用定时器和基本定时器。此外,还有能够实现定时功能的系统滴答定时器,实时时钟以及看门狗。关于这些定时器的介绍,占据了STM32F10xxx参考手册1/5的篇幅,可见其功能的强大。

    在低容量和中容量的STM32F103xx产品,以及互联型产品STM32F105xx和STM32F107xx中,只有一个高级控制定时器TIM1。而在高容量和超大容量的STM32F103xx产品中,有两个高级控制定时器TIM1和TIM8。

    在所有STM32F10xxx系列产品中,都有通用定时器TIM2~TIM5,除非另有说明。除此之外,在超大容量产品中,还有通用定时器TIM9~TIM14。

    在高容量和超大容量的STM32F101xx和STM32F103xx产品,以及互联型产品STM32F105xx和STM32F107xx中,有两个基本定时器TIM6和TIM7。

    其中,高级控制定时器的功能最为强大,可以实现所有其他定时器的所有功能。TrailBreaker开发板使用的是高容量的STM32F103ZE,因此有两个高级控制定时器TIM1和TIM8。下面我们就着重介绍这两个高级控制定时器。

    TIM1和TIM8简介

    高级控制定时器(TIM1和TIM8)由一个16位的自动装载计数器组成,它由一个可编程的预分频器驱动。它适合多种用途,包含测量输入信号的脉冲宽度(输入捕获),或者产生输出波形(输出比较、PWM、嵌入死区时间的互补PWM等)。使用定时器预分频器和RCC时钟控制预分频器,可以实现脉冲宽度和波形周期从几个微秒到几个毫秒的调节。
    关于实验中用到的LED部分原理图和GPIO跑马灯实验所用到的相同,在此不再多做介绍。
    TIM1和TIM8定时器的功能包括:
    16位向上、向下、向上/下自动装载计数器
    16位可编程(可以实时修改)预分频器,计数器时钟频率的分频系数为1~65535之间的任意数值
    多达4个独立通道: ─ 输入捕获 ─ 输出比较 ─ PWM生成(边缘或中间对齐模式) ─ 单脉冲模式输出
    死区时间可编程的互补输出
    使用外部信号控制定时器和定时器互联的同步电路
    允许在指定数目的计数器周期之后更新定时器寄存器的重复计数器
    刹车输入信号可以将定时器输出信号置于复位状态或者一个已知状态
    如下事件发生时产生中断/DMA:
    ─ 更新:计数器向上溢出/向下溢出,计数器初始化(通过软件或者内部/外部触发)
    ─ 触发事件(计数器启动、停止、初始化或者由内部/外部触发计数)
    ─ 输入捕获
    ─ 输出比较
    ─ 刹车信号输入
    支持针对定位的增量(正交)编码器和霍尔传感器电路
    触发输入作为外部时钟或者按周期的电流管理

    高级定时器框图和时钟简介

    STM32定时器的预装载寄存器与影子寄存器之间的关系(整理)

    STM32定时器的预装载寄存器与影子寄存器之间的关系(整理)

    如框图中的红框所示,红框中的部分,也是时基单元(Time-base unit),对时基单元进行设置,就可以完成基础的定时器的使用设置。

    计数器时钟可由下列时钟源提供:
    ● 内部时钟(CK_INT)
    ● 外部时钟模式1:外部输入引脚
    ● 外部时钟模式2:外部触发输入ETR
    ● 内部触发输入(ITRx):使用一个定时器作为另一个定时器的预分频器。如可以配置一个定时器Timer1而作为另一个定时器Timer2的预分频器。详见数据手册的通用定时器部分。

    内部时钟源(CK_INT):

    如果禁止了从模式控制器(SMS=000),则CEN、DIR(TIMx_CR1寄存器)和UG位(TIMx_EGR寄存器)是事实上的控制位,并且只能被软件修改(UG位仍被自动清除)。只要CEN位被写成’1’,预分频器的时钟就由内部时钟CK_INT提供。下图显示控制电路和向上计数器在一般模式下,不带预分频器时的操作。

    外部时钟源模式1

    当TIMx_SMCR寄存器的SMS=111时,此模式被选中。计数器可以在选定输入端的每个上升沿或下降沿计数。下图为TI2外部时钟连接例子

    例如,要配置向上计数器在T12输入端的上升沿计数,使用下列步骤:
    1.配置TIMx_CCMR1寄存器CC2S=01
    2.配置通道2检测TI2输入的上升沿
    3.配置TIMx_CCMR1寄存器的IC2F[3:0],选择输入滤波器带宽(如果不需要滤波器,保持IC2F=0000)
    4.配置TIMx_CCER寄存器的CC2P=0,选定上升沿极性
    5.配置TIMx_SMCR寄存器的SMS=111,选择定时器外部时钟模式1
    6.配置TIMx_SMCR寄存器中的TS=110,选定TI2作为触发输入源
    7.设置TIMx_CR1寄存器的CEN=1,使能计数器
    注: 捕获预分频器不用作触发,所以不需要对它进行配置
    当上升沿出现在TI2,计数器计数一次,且TIF标志被设置。在TI2的上升沿和计数器实际时钟之间的延时,取决于在TI2输入端的重新同步电路。
    下图为外部时钟模式1下的控制电路

    外部时钟源模式2

    选定此模式的方法为:令TIMx_SMCR寄存器中的ECE=1。
    计数器能够在外部触发ETR的每一个上升沿或下降沿计数。
    下图是外部触发输入的框图

    设置从模式控制寄存器的ETP位选择选择是用ETR还是ETR的反相来作为触发操作
    例如,要配置在ETR下每2个上升沿计数一次的向上计数器,使用下列步骤:
    1.本例中不需要滤波器,置TIMx_SMCR寄存器中的ETF[3:0]=0000
    2.设置预分频器,置TIMx_SMCR寄存器中的ETPS[1:0]=01
    3.选择ETR的上升沿检测,置TIMx_SMCR寄存器中的ETP=0
    4.开启外部时钟模式2,写TIMx_SMCR寄存器中的ECE=1
    5.启动计数器,写TIMx_CR1寄存器中的CEN=1
    计数器在每2个ETR上升沿计数一次。
    在ETR的上升沿和计数器实际时钟之间的延时取决于在ETRP信号端的重新同步电路。
    下图为外部时钟模式2下的控制电路


    如图,该图为STM32的时钟树,结合高级控制定时器框图,我们可以看出,高级定时器的时钟不是直接来自APB2,而是来自于输入为APB2的一个倍频器。
    当APB2的预分频系数为1时,这个倍频器不起作用,定时器的时钟频率等于APB2的频率;当APB2的预分频系数为其它数值(即预分频系数为2、4、8或16)时,这个分频器起作用,定时器的时钟频率等于APB2的频率相应倍数。
    假定AHB=36MHz,因为APB2允许的最大频率为72MHz,所以APB2的预分频系数可以取任意数值;当预分频系数=1时,APB2=72MHz,TIM1和TIM8的时钟频率=72MHz(分频器不起作用);当预分频系数=2时,APB1=36MHz,在倍频器的作用下,TIM1和TIM8的时钟频率=72MHz。
    有人会问,既然需要TIM1和TIM8的时钟频率为72MHz,为什么不直接取APB2的预分频系数=1?答案是:APB2不但要为TIM1和TIM8提供时钟,而且还要为其它外设提供时钟;设置这个倍频器可以在保证其它外设使用较低时钟频率时,TIM1和TIM8仍能得到较高的时钟频率。
    再举个例子:当AHB=72MHz时,APB2因为其他设备需要,时钟为36MHZ,因为这个倍频器,TIM1和TIM8仍然能够得到72MHz的时钟频率。能够使用更高的时钟频率,无疑提高了定时器的分辨率,这也正是设计这个倍频器的初衷。

    高级定时器寄存器简介

    可编程高级控制定时器的主要部分是一个16位计数器和与其相关的自动装载寄存器。这个计数器可以向上计数、向下计数或者向上向下双向计数。此计数器时钟由预分频器分频得到。计数器、自动装载寄存器和预分频器寄存器可以由软件读写,即使计数器还在运行读写仍然有效。
    时基单元,也就是决定了定时器的基本功能的模块包含:
    1.计数器寄存器(Counter register,简写为TIMx_CNT)
    2.预分频器寄存器 (Prescaler register,简写为TIMx_PSC)
    3.自动装载寄存器 (Auto-reload register,简写为TIMx_ARR)
    4.重复次数寄存器 (Repetition counter register,简写为TIMx_RCR)

    1.影子寄存器

    这张图是高级定时器框图的一部分,细心的人可以发现预分频器寄存器、自动重载寄存器和捕捉/比较寄存器下面有一个阴影,其他的寄存器有些也有阴影。
    这表示在物理上这个寄存器对应2个寄存器:一个是我们可以可以写入或读出的寄存器,称为预装载寄存器,另一个是我们看不见的、无法真正对其读写操作的,但在使用中真正起作用的寄存器,称为影子寄存器.
    数据手册介绍预装载寄存器的内容可以随时传送到影子寄存器,即两者是连通的(permanently),或者在每一次更新事件(UEV)时才把预装载寄存器的内容传送到影子寄存器。
    原文如下:
    The auto-reload register is preloaded. Writing to or reading from the auto-reload register accesses the preload register. The content of the preload register are transferred into the shadow register permanently or at each update event (UEV), depending on the auto-reload preload enable bit (ARPE) in TIMx_CR1 register. The update event is sent when the counter reaches the overflow (or underflow when downcounting) and if the UDIS bit equals 0 in the TIMx_CR1 register. It can also be generated by software. The generation of the update event is described in detailed for each configuration.
    在图中的,表示对应寄存器的影子寄存器可以在发生更新事件时,被更新为它的预装载寄存器的内容;而图中的部分,表示对应的自动重载寄存器可以产生一个更新事件(U)或更新事件中断(UI)。
    设计预装载寄存器和影子寄存器的好处是,所有真正需要起作用的寄存器(影子寄存器)可以在同一个时间(发生更新事件时)被更新为所对应的预装载寄存器的内容,这样可以保证多个通道的操作能够准确地同步。如果没有影子寄存器,软件更新预装载寄存器时,则同时更新了真正操作的寄存器,因为软件不可能在一个相同的时刻同时更新多个寄存器,结果造成多个通道的时序不能同步,如果再加上例如中断等其它因素,多个通道的时序关系有可能会混乱,造成是不可预知的结果。


    2.预分频寄存器

    预分频器可以将计数器的时钟频率按1到65536之间的任意值分频。它是基于一个在TIMx_PSC寄存器中的16位寄存器控制的16位计数器。因为这个控制寄存器带有缓冲器,它能够在运行时被改变。新的预分频器的参数在下一次更新事件到来时被采用。
    下面给出了在预分频器运行时,更改计数器参数的例子
    当预分频器的参数从1变到2时,计数器的时序图如下:

    当预分频器的参数从1变到4时,计数器的时序图如下:

    预分频寄存器各位的描述如下:


    位15:0 PSC[15:0]:预分频值
    计数器的时钟频率(CK_CNT)等于fCK_PSC / (PSC[15:0] + 1)。
    PSC的值保存在预分频寄存器的预装载寄存器中,在每次更新事件时加载至影子寄存器.

    3.计数器寄存器

    高级定时器计数模式:在向上计数模式中,计数器从0计数到自动加载值(TIMx_ARR计数器的内容),然后重新从0开始计数并且产生一个计数器溢出事件。
    如果使用了重复计数器功能,在向上计数达到设置的重复计数次数(TIMx_RCR)时,产生更新事件(UEV);否则每次计数器溢出时才产生更新事件。
    在事件产生寄存器寄存器中(通过软件方式或者使用从模式控制器)设置UG位也同样可以产生一个更新事件。设置TIMx_CR1寄存器中的UDIS位,可以禁止更新事件;这样可以避免在向预装载寄存器中写入新值时更新影子寄存器。在UDIS位被清’0’之前,将不产生更新事件。但是在应该产生更新事件时,计数器仍会被清’0’,同时预分频器的计数也被请0(但预分频器的数值不变)。此外,如果设置了TIMx_CR1寄存器中的URS位(选择更新请求),设置UG位将产生一个更新事件UEV,但硬件不设置UIF标志(即不产生中断或DMA请求)。这是为了避免在捕获模式下清除计数器时,同时产生更新和捕获中断。
    当发生一个更新事件时,所有的寄存器都被更新,硬件同时(依据URS位)设置更新标志位(TIMx_SR寄存器中的UIF位)。
    ● 重复计数器被重新加载为TIMx_RCR寄存器的内容。
    ● 自动装载影子寄存器被重新置入预装载寄存器的值(TIMx_ARR)。
    ● 预分频器的缓冲区被置入预装载寄存器的值(TIMx_PSC寄存器的内容)。
    下面给出一些例子,当TIMx_ARR=0x36时计数器在不同时钟频率下的动作。
    内部时钟分频因子为1 时的计数器时序图如下:

    内部时钟分频因子为2 时的计数器时序图如下:

    内部时钟分频因子为4时的计数器时序图如下:

    内部时钟分频因子为N时的计数器时序图如下:

    当ARPE=0时的更新事件(TIMx_ARR没有预装入) 时的计数器时序图如下:

    当ARPE=1时的更新事件(TIMx_ARR预装入) 时的计数器时序图如下:

    在向下模式中,计数器从自动装入的值(TIMx_ARR计数器的值)开始向下计数到0,然后从自动装入的值重新开始并且产生一个计数器向下溢出事件。
    如果使用了重复计数器,当向下计数重复了重复计数寄存器(TIMx_RCR)中设定的次数后,将产生更新事件(UEV),否则每次计数器下溢时才产生更新事件。
    在TIMx_EGR寄存器中(通过软件方式或者使用从模式控制器)设置UG位,也同样可以产生一个更新事件。
    设置TIMx_CR1寄存器的UDIS位可以禁止UEV事件。这样可以避免向预装载寄存器中写入新值时更新影子寄存器。因此UDIS位被清为0之前不会产生更新事件。然而,计数器仍会从当前自动加载值重新开始计数,并且预分频器的计数器重新从0开始(但预分频系数不变)。
    此外,如果设置了TIMx_CR1寄存器中的URS位(选择更新请求) ,设置UG位将产生一个更新事件UEV但不设置UIF标志(因此不产生中断和DMA请求),这是为了避免在发生捕获事件并清除计数器时,同时产生更新和捕获中断。
    当发生更新事件时,所有的寄存器都被更新,并且(根据URS位的设置)更新标志位(TIMx_SR寄存器中的UIF位)也被设置。
    ● 重复计数器被重置为TIMx_RCR寄存器中的内容
    ● 预分频器的缓存器被加载为预装载的值(TIMx_PSC寄存器的值)。
    ● 当前的自动加载寄存器被更新为预装载值(TIMx_ARR寄存器中的内容)。
    注:自动装载在计数器重载入之前被更新,因此下一个周期将是预期的值。
    下面是一些当TIMx_ARR=0x36时,计数器在不同时钟频率下的动作。
    内部时钟分频因子为1 时的计数器时序图如下:


    内部时钟分频因子为2 时的计数器时序图如下:

    内部时钟分频因子为4时的计数器时序图如下:

    内部时钟分频因子为N时的计数器时序图如下:

    当没有使用重复计数器时的更新事件时的计数器时序图:

    中央对齐模式(up/down counting) 在中央对齐模式,计数器从0开始计数到自动加载的值(TIMx_ARR寄存器)−s211,产生一个计数器溢出事件,然后向下计数到1并且产生一个计数器下溢事件;然后再从0开始重新计数。
    在此模式下,不能写入TIMx_CR1中的DIR方向位。它由硬件更新并指示当前的计数方向。
    可以在每次计数上溢和每次计数下溢时产生更新事件;也可以通过(软件或者使用从模式控制器)设置TIMx_EGR寄存器中的UG位产生更新事件。然后,计数器重新从0开始计数,预分频器也重新从0开始计数。
    设置TIMx_CR1寄存器中的UDIS位可以禁止UEV事件。这样可以避免在向预装载寄存器中写入新值时更新影子寄存器。因此UDIS位被清为0之前不会产生更新事件。然而,计数器仍会根据当前自动重加载的值,继续向上或向下计数。此外,如果设置了TIMx_CR1寄存器中的URS位(选择更新请求) ,设置UG位将产生一个更新事件UEV但不设置UIF标志(因此不产生中断和DMA请求),这是为了避免在发生捕获事件并清除计数器时,同时产生更新和捕获中断。
    当发生更新事件时,所有的寄存器都被更新,并且(根据URS位的设置)更新标志位(TIMx_SR寄存器中的UIF位)也被设置。
    ● 重复计数器被重置为TIMx_RCR寄存器中的内容
    ● 预分频器的缓存器被加载为预装载(TIMx_PSC寄存器)的值。
    ● 当前的自动加载寄存器被更新为预装载值(TIMx_ARR寄存器中的内容)。注:如果因为计数器溢出而产生更新,自动重装载将在计数器重载入之前被更新,因此下一个周期将是预期的值(计数器被装载为新的值)。
    下面是一些计数器在不同时钟频率下的操作的例子:
    内部时钟分频因子为1,TIMx_ARR=0x6时的计数器时序图:

    内部时钟分频因子为2时的计数器时序图:

    内部时钟分频因子为4,TIMx_ARR=0x36时的计数器时序图:

    注:在此无论是中心对齐模式2或3都是在溢出时与UIF标志一起使用
    内部时钟分频因子为N,计数器时序图如下:

    ARPE=1时的更新事件(计数器下溢),计数器时序图如下:

    计数器寄存器各位的描述如下:

    位15:0 ARR[15:0]: 自动重装载的值 (Prescaler value)
    ARR包含了将要装载入实际的自动重装载寄存器的值。 详细参考数据手册13.3.1节:有关ARR的更新和动作。当自动重装载的值为空时,计数器不工作。

    4.重复计数器

    前面解释了计数器上溢/下溢时更新事件(UEV)是如何产生的,然而事实上它只能在重复计数达到0的时候产生。这个特性对产生PWM信号非常有用。
    这意味着在每N次计数上溢或下溢时,数据从预装载寄存器传输到影子寄存器(TIMx_ARR自动重载入寄存器,TIMx_PSC预装载寄存器,还有在比较模式下的捕获/比较寄存器TIMx_CCRx),N是TIMx_RCR重复计数寄存器中的值。
    重复计数器在下述任一条件成立时递减:
    ● 向上计数模式下每次计数器溢出时,
    ● 向下计数模式下每次计数器下溢时,
    ● 中央对齐模式下每次上溢和每次下溢时。虽然这样限制了PWM的最大循环周期为128,但它能够在每个PWM周期2次更新占空比。在中央对齐模式下,因为波形是对称的,如果每个PWM周期中仅刷新一次比较寄存器,则最大的分辨率为2xTck。
    重复计数器是自动加载的,重复速率是由TIMx_RCR寄存器的值定义。当更新事件由软件产生(通过设置TIMx_EGR 中的UG位)或者通过硬件的从模式控制器产生,则无论重复计数器的值是多少,立即发生更新事件,并且TIMx_RCR寄存器中的内容被重载入到重复计数器。
    下图为不同模式下更新速率的例子,及TIMx_RCR的寄存器设置

    重复计数器各位的描述如下:

    位15:8 保留位,始终读为0。
    位7:0 REP[7:0]: 重复计数器的值 (Repetition counter value) 开启了预装载功能后,这些位允许用户设置比较寄存器的更新速率(即周期性地从预装载寄存器传输到当前寄存器);如果允许产生更新中断,则会同时影响产生更新中断的速率。
    每次向下计数器REP_CNT达到0,会产生一个更新事件并且计数器REP_CNT重新从REP值开始计数。由于REP_CNT只有在周期更新事件U_RC发生时才重载REP值,因此对TIMx_RCR寄存器写入的新值只在下次周期更新事件发生时才起作用。这意味着在PWM模式中,(REP+1)对应着:
    - 在边沿对齐模式下,PWM周期的数目;
    - 在中心对称模式下,PWM半周期的数目;

    5.控制寄存器1

    控制寄存器1各位的描述如下:


    位15:10 保留,始终读为0。
    位9:8 CKD[1:0]:时钟分频因子 (Clock division)
    这2位定义在定时器时钟(CK_INT)频率、死区时间和由死区发生器与数字滤波器(ETR,TIx)所用的采样时钟之间的分频比例。
    00:tDTS = tCK_INT
    01:tDTS = 2 x tCK_INT
    10:tDTS = 4 x tCK_INT
    11:保留,不要使用这个配置
    位7 ARPE:自动重装载预装载允许位 (Auto-reload preload enable)
    0:TIMx_ARR寄存器没有缓冲;
    1:TIMx_ARR寄存器被装入缓冲器。
    位6:5 CMS[1:0]:选择中央对齐模式 (Center-aligned mode selection)
    00:边沿对齐模式。计数器依据方向位(DIR)向上或向下计数。
    01:中央对齐模式1。计数器交替地向上和向下计数。配置为输出的通道(TIMx_CCMRx寄存器中CCxS=00)的输出比较中断标志位,只在计数器向下计数时被设置。
    10:中央对齐模式2。计数器交替地向上和向下计数。配置为输出的通道(TIMx_CCMRx寄存器中CCxS=00)的输出比较中断标志位,只在计数器向上计数时被设置。
    11:中央对齐模式3。计数器交替地向上和向下计数。配置为输出的通道(TIMx_CCMRx寄存器中CCxS=00)的输出比较中断标志位,在计数器向上和向下计数时均被设置。
    在计数器开启时(CEN=1),不允许从边沿对齐模式转换到中央对齐模式。
    位4 DIR:方向 (Direction)
    0:计数器向上计数;
    1:计数器向下计数。
    当计数器配置为中央对齐模式或编码器模式时,该位为只读。
    位3 OPM:单脉冲模式 (One pulse mode)
    0:在发生更新事件时,计数器不停止;
    1:在发生下一次更新事件(清除CEN位)时,计数器停止。
    位2 URS:更新请求源 (Update request source)
    软件通过该位选择UEV事件的源
    0:如果使能了更新中断或DMA请求,则下述任一事件产生更新中断或DMA请求:
    −计数器溢出/下溢
    −设置UG位
    −从模式控制器产生的更新
    1:如果使能了更新中断或DMA请求,则只有计数器溢出/下溢才产生更新中断或DMA请求
    位1 UDIS:禁止更新 (Update disable)
    软件通过该位允许/禁止UEV事件的产生
    0:允许UEV。更新(UEV)事件由下述任一事件产生:
    −计数器溢出/下溢
    −设置UG位
    −从模式控制器产生的更新 具有缓存的寄存器被装入它们的预装载值。(更新影子寄存器)
    1:禁止UEV。不产生更新事件,影子寄存器(ARR、PSC、CCRx)保持它们的值。如果设置了UG位或从模式控制器发出了一个硬件复位,则计数器和预分频器被重新初始化。
    位0 CEN:使能计数器 (Counter enable)
    0:禁止计数器;
    1:使能计数器。
    在软件设置了CEN位后,外部时钟、门控模式和编码器模式才能工作。触发模式可以自动地通过硬件设置CEN位。

    6.事件产生寄存器

    位15:8 保留,始终读为0。
    位7 BG:产生刹车事件 (Break generation) 该位由软件置’1’,用于产生一个刹车事件,由硬件自动清’0’。
    0:无动作;
    1:产生一个刹车事件。此时MOE=0、BIF=1,若开启对应的中断和DMA,则产生相应的中断和DMA。
    位6 TG:产生触发事件 (Trigger generation) 该位由软件置’1’,用于产生一个触发事件,由硬件自动清’0’。
    0:无动作;
    1:TIMx_SR寄存器的TIF=1,若开启对应的中断和DMA,则产生相应的中断和DMA。
    位5 COMG:捕获/比较事件,产生控制更新 (Capture/Compare control update generation) 该位由软件置’1’,由硬件自动清’0’。
    0:无动作;
    1:当CCPC=1,允许更新CCxE、CCxNE、OCxM位。
    该位只对拥有互补输出的通道有效。
    位4 CC4G:产生捕获/比较4事件 (Capture/Compare 4 generation) 参考CC1G描述。
    位3 CC3G:产生捕获/比较3事件 (Capture/Compare 3 generation) 参考CC1G描述。
    位2 CC2G:产生捕获/比较2事件 (Capture/Compare 2 generation) 参考CC1G描述。
    位1 CC1G:产生捕获/比较1事件 (Capture/Compare 1 generation) 该位由软件置’1’,用于产生一个捕获/比较事件,由硬件自动清’0’。
    0:无动作;
    1:在通道CC1上产生一个捕获/比较事件:
    若通道CC1配置为输出: 设置CC1IF=1,若开启对应的中断和DMA,则产生相应的中断和DMA。
    若通道CC1配置为输入:当前的计数器值被捕获至TIMx_CCR1寄存器;设置CC1IF=1,若开启对应的中断和DMA,则产生相应的中断和DMA。
    若CC1IF已经为1,则设置CC1OF=1。
    位0 UG:产生更新事件 (Update generation) 该位由软件置’1’,由硬件自动清’0’。
    0:无动作;
    1:重新初始化计数器,并产生一个更新事件。注意预分频器的计数器也被清’0’(但是预分频系数不变)。若在中心对称模式下或DIR=0(向上计数)则计数器被清’0’;若DIR=1(向下计数)则计数器取TIMx_ARR的值。
    关于刹车事件,触发事件,捕获比较事件的描述,详见数据手册13章


    程序分析:

    固件库函数分析:

    STM32的高级定时器功能十分强大,但相应的功能强大就意味着结构复杂。复杂的结构带来的是复杂的库函数。
    高级定时器TIM1和TIM8一共有着80多个库函数,如果对其一一介绍,不但浪费时间,浪费精力,还有可能变成类似《固件库使用手册》一样的东西。在学习的时候,我们对事物的认知总是螺旋上升的,尤其是我们做嵌入式开发,当遇到一个新的系统或者硬件,指望着看一遍数据手册,就完全掌握其使用方法是不可能的。所以,我们先建立起一个最简单,最基础的实验,方便对新事物有着一个感性的直观的认知。有了清晰的认知,明白了基本原理后,后面的学习速度就会大大加快,也能的心应手了.看数据手册和固件库函数的时候,不要图快,不要浮躁,指望着看看相关的资料,复制下固件库例程的代码把程序搞定,这不叫“写代码”,这叫“移植”。基础打的不牢靠,对于细节问题理解的不清晰,是不可能真正的学好ARM的.如果想继续学习的话,你会发现,你“节省”的时间,在越来越深入后,就会给你带来双倍的“节省时间”长的麻烦.
    ----------作者的心得在"stm32f10x_tim.h"中可以看到如下定义:

    typedef struct { uint16_t TIM_Prescaler;   uint16_t TIM_CounterMode;   uint16_tTIM_Period;   uint16_t TIM_ClockDivision;   uint8_t TIM_RepetitionCounter; }TIM_TimeBaseInitTypeDef;

    库函数TIM_TimeBaseInit()的原型如下

    void TIM_TimeBaseInit(TIM_TypeDef* TIMx, TIM_TimeBaseInitTypeDef*TIM_TimeBaseInitStruct) { uint16_t tmpcr1 = 0; assert_param(IS_TIM_ALL_PERIPH(TIMx));assert_param(IS_TIM_COUNTER_MODE(TIM_TimeBaseInitStruct->TIM_CounterMode));assert_param(IS_TIM_CKD_DIV(TIM_TimeBaseInitStruct->TIM_ClockDivision));   tmpcr1 =TIMx->CR1;   if((TIMx == TIM1) || (TIMx == TIM8)|| (TIMx == TIM2) || (TIMx == TIM3)||(TIMx == TIM4) || (TIMx == TIM5)) { tmpcr1 &= (uint16_t)(~((uint16_t)(TIM_CR1_DIR |TIM_CR1_CMS))); tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct->TIM_CounterMode; }  if((TIMx != TIM6) && (TIMx != TIM7)) { tmpcr1 &= (uint16_t)(~((uint16_t)TIM_CR1_CKD));tmpcr1 |= (uint32_t)TIM_TimeBaseInitStruct->TIM_ClockDivision; }   TIMx->CR1 = tmpcr1;  TIMx->ARR = TIM_TimeBaseInitStruct->TIM_Period ; TIMx->PSC = TIM_TimeBaseInitStruct->TIM_Prescaler;   if ((TIMx == TIM1) || (TIMx == TIM8)|| (TIMx == TIM15)|| (TIMx ==TIM16) || (TIMx == TIM17)) { TIMx->RCR = TIM_TimeBaseInitStruct->TIM_RepetitionCounter; } TIMx->EGR = TIM_PSCReloadMode_Immediate; }

    正如函数名,和结构体名所描述的,这个函数的作用为,初始化TIM1的时基部分.
    结合着数据手册和上面的高级定时器框图和时钟简介可知,我们使用高级定时器TIM1中断时对TIM1的时基配置顺序如下所示。

    在此例中,我们可以这样定义他.

    TIM_TimeBaseStructure.TIM_Prescaler=(18000-1); //时钟预分频TIM_TimeBaseStructure.TIM_Period=4000-1; //定时器初始值TIM_TimeBaseStructure.TIM_CounterMode=TIM_CounterMode_Up; //向上计数模式TIM_TimeBaseStructure.TIM_ClockDivision=TIM_CKD_DIV1; // 时钟分割 TIM_CKD_DIV1 为 0x0TIM_TimeBaseInit(TIM1,&TIM_TimeBaseStructure); //初始化定时器的值

    上面的初始化流程图已经说明,
    定时器中断频率 = 时钟频率/(时钟预分频+1)/(计数器装载值+1)
    所以我们要达到1S间隔的跑马灯,定时器的中断频率为1Hz,所以这里只要时钟分频的值与定时器的计数器的装载值之积为72MHZ且不越界即可
    关于计数模式,在stm32f10x.h中有如下的定义

    #define TIM_CounterMode_Up ((uint16_t)0x0000) #define TIM_CounterMode_Down ((uint16_t)0x0010) #define TIM_CounterMode_CenterAligned1 ((uint16_t)0x0020) #define TIM_CounterMode_CenterAligned2 ((uint16_t)0x0040) #define TIM_CounterMode_CenterAligned3 ((uint16_t)0x0060)
    展开全文
  • STM32 定时器除了基本计数定时功能外,还对外扩展了输入、输出通道,从而可以实现输入捕获、比较输出功能。 比较输出[Compare Output]功能:定时器通过对预设的比较值与定时器的值做匹配比较之后,并依据相应的输出...

    STM32 定时器除了基本计数定时功能外,还对外扩展了输入、输出通道,从而可以实现输入捕获、比较输出功能。

    比较输出[Compare Output]功能:定时器通过对预设的比较值与定时器的值做匹配比较之后,并依据相应的输出模式从而实现各类输出。如PWM输出、电平翻转、单脉冲模式、强制输出等。一般来说,STM32的通用定时器和高级定时器都具有比较输出功能,不同的定时器可能通道数量上有差异。

    或者,我们可以使用比较输出功能来感知或提示某个时间段已经过去了。因为比较输出的基本特征是计数器CNT的值与比较寄存器CCR的值作比较,计数器数据变化意味着时间流逝,当计数器记到与比较值相等或向匹配时,也就表示相应时间段的过去。

    具体应用到STM32定时器,在比较输出模式下,当捕获比较单元监测到计数器CNT的值与CCR寄存器值数字相等时,将根据相应的输出比较输出模式实现相应输出。比较输出功能主要靠捕获比较单元实现,同时定时器输出单元与时基单元协同配合。

    捕捉比较单元有个重要的寄存器,捕捉比较寄存器CCR ,它由影子寄存器/预装载寄存器组成。用户访问时,访问预装载寄存器。预装载功能可以开启或关闭。由OCxPE@TIMx_CCMR控制。
    需要修改的预装数据立即生效时将预装功能关闭。
    需要修改的数据不影响当前周期的计数或波形输出时,我们就打开其预装功能。

    比较输出流程:

    在这里插入图片描述

    捕获/比较通道的输出部分(通道1至3)

    在这里插入图片描述
    在这里插入图片描述
    当定时器的比较输出单元检测到计数器CNT的值与捕获比较寄存器CCR的值发送匹配事件时,定时器的比较输出单元会根据比较输出模式输出相应的信号,该信号我们称之为 中间参考信号,即OCxREF。

    该OCxREF源与输出模式控制器,并硬件约定高电平为有效电平 它经过极性选择后,在经过输出控制电路输出到到管脚。当极性选择位 CCxP = 0 时。高电平为OCx的有效输出电平,当CCxP = 1时,低电平作为OCx的有效输出。

    也就是说:OCxREF 信号只是一个中间参考信号,并非最终输出信号,最终输出端OCx的 Active state【有效状态】/ inactive state【无效状态】所对应的电平取决于极性选择控制位CCxp/CCxNP。

    也就是最终的输出需要由2个信号来控制,一个是 OCxREF中间参考信号,用来确定有效信号和与无效信号,另一个CCxP用来控制,有效信号或者无效信号的高电平和低电平。
    在这里插入图片描述
    在这里插入图片描述
    总结为一张表:

    OC1REF CC1P 功能 OC1 描述
    0 0 OC1高电平有效 0(低电平) 无效
    1 OC1低电平有效 1(高电平) 无效
    1 0 OC1高电平有效 1(高电平) 有效
    1 OC1低电平有效 0(低电平) 有效

    比较输出事件:

    • 当核心计数器的值CNT与比较寄存器CCR 的数值匹配时发生比较输出事件
    • 相应通道的比较输出标志位CCxIF@TIMx_SR被置位
    • 触发比较中断 (如果CCxIE@TIMx_DIER被置位使能)
    • 触发DMA请求 (CCxDE@TIMx_DIER CCDS@TIMx_CR2 使能允许)
    • 比较输出事件也可以软件方式产生。通过操作TIMx_EGR@CCxG位来实现

    对于这些比较输出有关的事件,我们需要做到心中有数。因为在我们定时器中,往往需要基于相关事件来开展我们的应用开发。比如基于比较输出事件,做脉冲波形频率或占空比的变更、做脉冲个数的统计、做DMA的请求等等。。

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

    在这里插入图片描述

    输出比较模式预览

    在这里插入图片描述
    总的来讲,这几个比较输出模式,我们有必要对它们的各自输出特征做基本了解,它是我们做比较输出应用时的基础。比方不同比较输出模式,结合不同的计数模式,相应的输出特征是什么。

    边沿对齐PWM输出波形示例【Up Counting + PWM mode1】:

    以下以PWM模式1为例。只要 TIMx_CNT < TIMx_CCRx。PWM的参考信号 OCxREF便为高电平,否则为低电平。
    如果 TIMx_CCRx中的比较值大于自动重装载值(TIM_ARR中),则OCxREF保持为“1”,如果比较值为“0”,则OCxREF保持为“0”。
    在这里插入图片描述

    中心对齐PWM输出波形示例【Center aligned Mode + PWM1】

    在这里插入图片描述

    PWM输出频率计算:

    定时器比较输出最常见的应用就是PWM输出,即脉宽调制输出。这里简单介绍下PWM输出波形参数的计算。

    以计数器向上计数、PWM1为例:

    PWM输出方波信号,信号的频率有TIMx的计数时钟频率和TIMx_ARR这个寄存器决定。输出信号的占空比由TIMx_CRRx寄存器和TIMx_ARR寄存器的值所决定。
    占空比 = (TIMx_CRRx / (TIMx_ARR+1))* 100%。
    频率 = CK_PSC / ((PSC + 1) * (ARR + 1)。

    单脉冲模式

    单脉冲模式(OPM)是上述模式的一个特例,在这个模式下,计数器可以在一个激励信号的触发下启动,并且可在一段可编程的延时后产生一个脉宽可编程的脉冲。

    可以通过从模式控制器启动计数器。可以在输出比较模式或PWM模式下生成波形,将 TIMx_CR1 寄存器中的 OPM 位置1,既可以选择单脉冲模式。这样发,发生下一次更新事件 UEV时,计数器将自动停止。

    只有当比较值与计数器初始值不同时,才能正确产生一个脉冲。启动前(定时器等待触发时),必须如下配置:

    • 递增计数模式下:CNT<CCRxARR(特别注意,0<CCRx)
    • 递减计数模式下:CNT>CCRx
    原理:

    计数器启动后,在下一个更新事件来临之前的时间段内实现固定个数的脉冲输出。当下一个更新事件来临时计数器停止计数。输出的脉冲个数可以一个或几个。如果是通用计数器就是1个,如果是高级定时器,脉冲个数与RCR数值和计数模式有关。

    实现方式

    使用OC比较输出或PWM输出模式。

    启动

    计数器的启动可以通过自身软件使能启动,也可以将定时器配置在触发从模式经过触发启动。

    在这里插入图片描述
    例如:你需要在从TI2输入脚上检测到一个上升沿开始,延迟tDELAY之后,在OC1上产生一个长度为tPULSE的正脉冲。
    假定TI2FP2作为触发1:

    • 置TIMx_CCMR1寄存器中的CC2S=01,把TI2FP2映像到TI2。
    • 置TIMx_CCER寄存器中的CC2P=0,使TI2FP2能够检测上升沿。
    • 置TIMx_SMCR寄存器中的TS=110,TI2FP2作为从模式控制器的触发(TRGI)。
    • 置TIMx_SMCR寄存器中的SMS=110(触发模式),TI2FP2被用来启动计数器。 OPM的波形由写入比较寄存器的数值决定(要考虑时钟频率和计数器预分频器)
    • tDELAY由TIMx_CCR1寄存器中的值定义。
    • tPULSE由自动装载值和比较值之间的差值定义(TIMx_ARR - TIMx_CCR1)。
    • 假定当发生比较匹配时要产生从0到1的波形,当计数器达到预装载值时要产生一个从1到0的波形;首先要置TIMx_CCMR1寄存器的OC1M=111,进入PWM模式2;根据需要有选择地使能预装载寄存器:置TIMx_CCMR1中的OC1PE=1和TIMx_CR1寄存器中的ARPE;然后在TIMx_CCR1寄存器中填写比较值,在TIMx_ARR寄存器中填写自动装载值,设置UG位来产生一个更新事件,然后等待在TI2上的一个外部触发事件。本例中,CC1P=0。

    在这个例子中,TIMx_CR1寄存器中的DIR和CMS位应该置低。
    因为只需要一个脉冲,所以必须设置TIMx_CR1寄存器中的OPM=1,在下一个更新事件(当计数器从自动装载值翻转到0)时停止计数。

    比较输出应用时的几个注意点

    1. 高级定时器相比通用定时器,它增加了主输出使能控制位,【MOE@timx_bdtr】,如果该位置零的话,此时OCx端没有波形输出;

    2. 高级定时器相比通用定时器,它增加了刹车控制机制,BKE@timx_bdtr】,如果使能了刹车控制并触发有效刹车电平,此时OCx端没有波形输出;

    3. 高级定时器相比通用定时器,使用互补输出时增加了死区插入机制,【DTG@timx_bdtr】,若插入的死区时间过大,当超过有效输出电平宽度时,会导致OCx/OCxN一端或两端没有变化的波形输出;

    4. 高级定时器的互补输出在OCxREF出来后、在极性选择之前,二者是互补的,经过极性选择后是否互补取决于两互补通道的极性选择。极性的选择最终由实际驱动电路需求决定的。

    5. 定时器的所有输出通道可以独立自由设置,如禁用/开启、输出模式选择、极性安排等。但高级定时器的做互补输出时,他们共用相同输出模式和CCR值。

    6. 对于通用定时器的Ocx通道,当使能该通道时,Ocx输出=OCxREF+极性;当禁用该通道时,Ocx的输出=0。

    7. 对于高级定时器Ocx/OCxN互补通道,没法同时实现实现有效输出。注意区分有效电平、无效电平与最终输出端的高、低电平。

    8. 对于高级定时器来说,Ocx/OCxN的输出除了跟输出使能位有关外,跟其它多个控制位【MOE/OSSI/OSSR/CCxP/CCxNP】有关。各个系列的STM32参考手册中有个Ocx/OcxN互补通道输出控制表格可以查看。

    展开全文
  • STM32定时器应用中,我们有时希望基于某定时器事件同时对定时器的多个寄存器进行读写访问。为此,STM32芯片设计了专门应对定时器的多寄存器访问应用的DMA Burst传输。高级定时器和部分通用定时器都支持针对定时器...

    06dbdb2f2ce1fc16942108bfccfb3244.png

    STM32定时器应用中,我们有时希望基于某定时器事件同时对定时器的多个寄存器进行读写访问。为此,STM32芯片设计了专门应对定时器的多寄存器访问应用的DMA Burst传输。

    高级定时器和部分通用定时器都支持针对定时器寄存器访问的BURST传输。所谓定时器的BURST传输,就是指当产生某定时器事件时,可以产生多个DMA请求,并触发多次DMA传输,访问多个定时器寄存器实现从内存到寄存器或从寄存器到内存的数据传输。这里的定时器事件可以是更新事件比较匹配事件换相事件以及触发事件

    a9d479c6a64d40ae3083b1a237c7ff77.png

    我们知道,各定时器的所有寄存器都存放在片内某一固定地址开始的连续空间内。下图是我从STM32G4系列定时器地址分布图中截取的一部分,不同的定时器所拥有的寄存器个数可能有差异,但每个定时器的寄存器地址映射表的第一个寄存器一定是TIMx_CR1,所有寄存器在内存空间以字对齐的方式按顺序依次存放。【后面都以TIM2为例来说】

    5fd2612479f5cafbb3add9776bcb3fa9.png

    显然,我们在做定时器的DMA BURST传输时,除了配置基本的源地址、目的地址等DMA传输所需的通用配置信息外,还得告知DMA BURST传输模块每次传输时从哪个寄存器开始,连续访问几个寄存器,比方访问上图中圈出来的从TIMx_CCR1开始的连续4个寄存器。

    这里有两个专门用于定时器BURST传输的寄存器,分别是TIM2_DCRTIM2_DMAR. 其中TIM2_DCR就是用来配置从哪个定时器寄存器开始访问、连续访问几个寄存器的问题。【下面截图来自STM32G4参考手册】

    2b1a23ef04b832f3b7ae3581bb3baba0.png

    DBA:被访问的第一个定时器寄存器相对于定时器地址映射表中的TIMx_CR1的地址偏移量【偏移量从0开始计算】。

    DBL:每组BURST访问的寄存器个数【从0开始计算】。

    仍然按照上面所说,访问从TIM2_CCR1开始的连续4个寄存器,可得知TIM2_CCR1位于寄存器地址映射表中的第14号位置,则DBA= 14-1;用于BURST分组访问的寄存器个数为4个,则DBL=4-1

    另外一个寄存器就是TIM2_DMAR。那它是干什么的呢?上面TIM2_DCR寄存器只是配置了被访问的首个定时器寄存器地址相对于TIMx_CR1的地址偏移量和每组要访问的寄存器个数。其中地址偏移量还只是个相对数,DMA访问最终是需要绝对地址的,而TIM2_DMAR就是来解决DMA访问时所需的绝对地址的。

    202fecef71397279b7f94c4fa6a9c196.png

    DMA访问DMAR寄存器时,按照如下算式得到绝对地址实现对寄存器的逐个访问。(TIM2_CR1address) + (DBA + DMA index)x 4

    [IndexDMA Burst访问时硬件自动生成的动态索引号,按0~DBL依次实现对多个寄存器的连续访问而完成BUSRT传输】

    也就是说,对于定时器DMA BURST传输,外设地址一定是TIM2_DMAR寄存器的地址【或许是源地址,或许是目的地址】,DMA通过访问它,并根据上面算式实现对实际寄存器的访问。所以TIM2_DMAR寄存器又可称之为专门用于定时器DMA Burst传输的虚拟寄存器。

    总的来讲,我们在做基于定时器的DMA BURST传输时,除了使用正确的DMAR寄存器地址作为外设地址外,再就是配置好DCR寄存器中的DBADBL参数,弄清从哪个寄存器开始访问,访问几个寄存器。其它配置环节跟通用DMA传输配置一样。

    下面用个例子来演示相关用法。后面的验证基于STM32G474 Nucleo板。使用TIM2输出4PWM,根据更新事件同步变化占空比,实现PWM占空比呈规律性的宽窄变化。即每次发生更新事件时,DMA到内存区取走4个对应于4个通道的比较寄存器的值赋给对应的比较寄存器[CCR1/CCR2/CCR3,CCR4],如下图所示,多组数据传输完毕后循环重来。

    3f90f16dbd9bad639108c8b952c697b7.png

    下面使用STM32CubeMx工具进行基本的初始化配置。

    配置TIM2_CH1/CH2/CH3/CH4PWM输出:

    81c8c72112d1f51733ef1b549c5f2058.png

    对定时器时基单元进行配置:

    4c00588e727a74dfa6462c92608a1c0d.png

    TIM2更新事件的DMA传输做基本配置:

    2de0b5ab1b72f22522102f9520302c0b.png

    这里配置为循环模式,具体应用时可以根据具有应用来选择模式。将其它时钟、GPIO配置完毕后即可生成初始化工程文件。

    在工程里添加用户应用代码。关于定时器BURST传输有专门的库函数可以给我们直接调用。它们分别是:

    HAL_TIM_DMABurst_WriteStart()    ----(1)

    HAL_TIM_DMABurst_ReadStart()       ----(2)

    第一个函数用于将内存数据以DMA 分组模式写入寄存器的功能函数;

    第二个用于将多个寄存器内容以DMA 分组模式读取到内存的功能函数;

    不过呢,如果我们简单套用这两个函数有些时候可能出问题,或者遇到障碍。我们不妨一起来看看。

    显然,我们要用到第一个函数。当我们进一步打开该函数时,发现它只是再调用了另外一个函数。

    a851ab6c6c1fbaa9e0998e81a3208996.png

    即它调用了HAL_TIM_DMABurst_MultiWriteStart()函数。这里就该函数用到的几个变量一起看下。

    htim:即指向定时器结构体的地址,就不多说了。

    BurstBaseAddress:前面提到过的第一个被访问寄存器的地址偏移量,即给到DCR寄存器中DBA的值。这里第一个被访问的是TIM2_CCR1,所在地址偏移量为13.

    3b5b8db1b7908facb0616c6500386e7a.png

    BurstRequestSrc:即触发DMA Burst传输的定时器事件源。这里是更新事件。

    b3b5dcbbd58b604fae49b9b1713618cc.png

    BurstBuffer:这个是存放数据的内存起始地址,如用户定义的数组地址。

    BurstLength:就是前面提到的对应DCR寄存器中DBL的值,即每组Burst传输的数据个数。具体到这里DBL应该是4-1,即3.

    1d58d79db3d12d4f48e0ed48a5386a27.png

    上面是固件里对该变量的定义。数据为什么这样定义,整整往左移了8位。看看上面DCR寄存器中DBL段所处位置就明白了。

    最后看看紧随其后的另外一个数据量 ((BurstLength) >> 8U) + 1U;结合前面BurstLength的数据,该计算结果就是给到DMA的传输数据个数,数值等于每组  Burst传输的数据个数。具体到这里就是4。换言之,若我们将每组Burst传输的数据个数设为6,则这里的值就是6。这就意味着,如果按照该函数的现有用法,无论发生多少次Busrt传输只能用到一组数据。如果我希望在Burst传输中使用到多组不同数据【可能部分不同或全部不同】,就像上面示例所期望的那样,那怎么办呢?

    这时我们可以基于现有库函数,在BURST传输需要用到多组不同数据时,直接使用

    HAL_TIM_DMABurst_MultiWriteStart()函数将其最后一个表示DMA传输长度的那个变量做适当修改

    056e6484880643dae84a5ece8d4344f9.png

    比方在应用中每组BURST传输m个数据,一轮DMA传输过程中对应n个触发事件,在不同的触发时刻,每组传输的数据内容并不全部相同,这时总的DMA传输数据个数就是m*n。具体到这里,我要用到11组不同的数据,每组传输4个数据,即一轮DMA传输用到4*11个数据。

    好,到此基本介绍和分析都差不多了,再看看具体用户代码。代码很简单,基于STM32HAL库的。

    下面是用来调整不同时刻各个通道PWM占空比的内存数据,共11组。

    75f760930d0325ac224fade759848f83.png

    要添加的用户参考代码都在下面,几行代码,应该说明白如画。主要是那个关于定时器DMA分组传输的那个函数,上面也已经详细解释了。

    0a02819a5f3e9d59f69059c5c6474aa3.png

    最后看看运行后的演示结果。

    示波器只接了2个通通,目的就是演示同时修改4个通道的占空比,实现pwm占空比由窄到宽的规律性变化。

    5375ae9733fe084900eadbef0af12612.png

    0510e5214f4d11ddabb043d164ecc0c0.png

    到此,关于定时器DMA Burst传输的介绍及示例就聊到这里。稍事小结:

    1、从定时器DMA Burst传输原理的理解上讲,稍显小复杂。需要我们对定时器相关原理和DMA基础知识有较好的了解。在阅读STM32参考手册相关章节时,除了看正文部分外,还需细看TIMx_DMARTIMx_DCR寄存器的描述。但从实现代码角度看,使用CubeMx和固件库,其功能代码还是很简单的,将相关变量值对应地填进去即可。

    2、STM32固件库的有些例程或函数侧重点在演示相应的功能或特性,但它不能包罗万象或保证适用于任何场景。有时我们可以在基于现有函数的前提下适当地做些改写调整,甚至完全重写代码以满足实际需求。

    3、在做定时器DMA  Burst传输时,用来被成组访问的定时器寄存器应该是同一定时器的而且是地址连续的寄存器,不可跳跃访问。

    4、上面的示例只是个示范,旨在了解该功能的用法和基本特性。实际应用中,往往还要涉及更多细节,比方各个定时器事件的特性、寄存器的预装功能的开或关、DMA相关知识等,最终结合实际需求加以灵活运用。

    ======================

    往期话题阅读链接【点击阅读】:

    1、对内部FLASH编程时遇到的ADC异常问题

    2、DMA触发请求异常之案例分享

    3、基于ARM MDK调试STM32的两个小提醒

    4、基于STM32H7 DMA传输的SPI 应用示例

    5、一个跟状态位处理有关的应用案例

    a9955cbbd7e00723e6b41d8121333600.png

    展开全文
  • 点击上方蓝色字体,关注我们本博文简要阐述STM32L011微控制器定时器的参数配置(其他型号大同小异,本文侧重讲解配置,至于各类定时器的特点后续再述),STM32定时器种类繁多有通用定时器、基本定时器、独立看门狗...
  • 2019/1/3新年上班第一天 @星辰从官方数据手册看到STM32F103配置的外设:定时器共有3种,分别是高级定时器TIM1,TIM8(愚以为电机控制相关)、通用定时器TIM2,TIM3,TIM4,TIM5、基本定时器TIM6,TIM7。本着物尽其用,...
  • stm32定时器引脚

    2021-03-22 19:35:07
    stm32定时器
  • STM32 定时器中断定时器
  • STM32定时器程序

    2017-04-05 20:24:52
    STM32定时器程序
  • stm32定时器概览.pdf

    2020-04-14 12:19:17
    stm32定时器概览.。
  • STM32定时器是 ST MCU 内部最基础且常用的外设,实际应用尤为普遍。去年,电堂推出了《STM32 TIMER基础及常规应用介绍》,为大家梳理了 STM32 TIMER 的庞大内容,涵盖 TIMER 的基本应用原理、常规应用等。现在将课程...
  • 今天调试了STM32的定时器功能,STM32定时器比较多,但调试都是一样的,寄存器都是一一对应的。就拿TIM2举例说明。在网上搜了好多关于定时器的设置,但大多数都是一个版本,而且都是针对库函数操作的,让人看起来一头...
  • stm32定时器简介

    2015-03-28 16:01:06
    stm32定时器简介
  • STM32定时器.ppt

    2019-08-01 15:28:35
    ppt文档里面介绍了STM32定时器的设置方法,包括寄存器的讲解
  • STM32定时器计算方法,不熟悉STM32定时器定时时间的同学拿走
  • 本文介绍了STM32定时器的时钟源设置问题。
  • STM32定时器计算工具

    2020-02-14 13:42:24
    用C#写的一个简易的STM32定时器计算工具,输入时钟、分频系数、重载值自动计算定时时间,方便使用定时器时计算时间。
  • 本文主要讲了一下关于stm32定时器时间计算方法。
  • stm32 定时器中断算法

    2018-09-06 01:16:13
    stm32 定时器中断算法,s曲线七段法,可以根据自己应用实例进行更改
  • 本文主要介绍STM32定时器的输入滤波机制

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 8,881
精华内容 3,552
关键字:

stm32定时器