【STM32H7教程】第36章 STM32H7的LPTIM低功耗定时器基础知识和HAL库API

2023-04-13  

36.1 初学者重要提示

  1. 使用LPTIM的好处是系统处于睡眠、停机状态依然可以正常工作(除了待机模式)。停机状态可以正常工作的关键是LSE,LSI时钟不会被关闭,同时也可以选择使用外部时钟源。

  2. 重点学习本章的2.9小节,对于LPTIM的认识起到至关重要的作用。

36.2 低功耗定时器基础知识

下面将低功耗定时器应用中要用到的基础知识做个介绍。

36.2.1 定时器的硬件框图

认识一个外设,最好的方式就是看它的框图,方便我们快速的了解定时器的基本功能,然后再看手册了解细节。

下面我们直接看最复杂的LPTIM1&LPTIM2框图:

通过这个框图,我们可以得到如下信息:

  • lptim_pclk接口

主要用于LPTIM的寄存器提供时钟,寄存器操作需要高速时钟,不能像LPTIM的其它部分一样使用LSI,LSE等低速时钟。

  • lptim_it接口

用于触发中断。

  • lptim_ker_ck接口

内核时钟,供lptim使用。lptim_ker_tim接入到CLKMUX双路选择器的一个输入端,另一个输入端是LPTIM_IN1或者LPTIM_IN2的输入。也就是说LPTIM的计数器可以选择lptim_ker_ck,也可以选择LPTIM_IN1或者LPTIM_IN。

注意:CLKMUX双路选择器对应的是CFGR寄存器的bit0:CKSEL,用于控制内核时钟选择由内部时钟源(APB时钟或LSE、LSI和HSI等任何其他内置振荡器)提供时钟。也可以选择由外部时钟源通过 LPTIM 外部 Input提供时钟。

Count mode对应的是CFGR寄存器的bit23:COUNTMODE计数模式位,用于选择 LPTIM 使用哪个时钟源来为计数器提供时钟。可以选择计数器在每个内部时钟脉冲后递增,或者在 LPTIM 外部 Input上的每个有效时钟脉冲后递增。

  • lptim_wkup

用于将系统从睡眠或者停机模式唤醒。

  • lptim_out和LPTIM_OUT

lptim_out表示计数器输出,用于内部触发。

LPTIM_OUT表示GPIO的输出通道,用于PWM。

  • LPTIM_ETR

通过GPIO为LPTIM提供外部触发。

  • lptim_ext_trigx

LPTIM的计数器既可以通过软件启动,也可以通过外部触发启动,有8种触发方式可供选择,以LPTIM1为例,支持的触发如下:

  • LPTIM_IN1,lptim_in1_mux1,lptim_in1_mux2和lptim_in1_mux3

LPTIM_IN2实际对应的是多路选择器的mux0,通过GPIO输入。

lptim_in1_mux1到lptim_in1_mux3对应的是内部输入,以LPTIM1为例,支持的输入信号如下:

  • LPTIM_IN2,lptim_in2_mux1,lptim_in2_mux2和lptim_in2_mux3

LPTIM_IN2实际对应的是多路选择器的mux0,通过GPIO输入。

lptim_in2_mux1到lptim_in2_mux3对应的是内部输入,以LPTIM1为例,支持的输入信号如下:

  • Glitch filter(干扰滤波器)

从框图中可以看到有三组Glitch filter,LPTIM_IN1和LPTIM_IN2接入多路选择器后各有一组,LPTIM_ETR接入后,也有一组。Glitch filter的作用是避免任何毛刺和噪声干扰在 LPTIM 内部传播,从而防止产生意外计数或触发。

注意:使用Glitch filter要向LPTIM 提供内部时钟源。

36.2.2 低功耗定时器的基本功能

LPTIM1 – LPTIM5都是16位的低功耗定时器(自动重载寄存器、比较寄存器和计数器都是16位的),相比TIM1 – TIM17这种通用定时器,在睡眠或者停机模式下依然可以工作(待机模式除外)。低功耗模式下要工作,就必然要支持低速时钟LSI、LSE或者外部输入时钟,这点是与通用定时器的本质区别。同时LPTIM的中断还可以唤醒停机模式,这点比较重要(休眠模式是任何中断都可以唤醒的,而停机模式可以LPTIM中断唤醒)。

以下几点是大家在使用中必须要了解到的:

1、 TIM1 – TIM17有专门的分频寄存器,而LPTIM1 – LPTIM5的分频是几种固定的值。

2、 低功耗定时器支持以下6种模式:

  • PWM模式

  • 单脉冲模式

  • 单次模式

在此模式下,当满足匹配条件时,输出可以切换高低电平(如果输出极性配置为高,则为低电平至高电平变化,反之亦然)。

  • 编码器模式

  • 超时模式

有效的边沿触发输入可复位定时器。第一个触发事件将启动计时器,任何连续触发事件将重置计数器并重新开始。

  • 计数器模式:

计数器可用于计算来自Input1的外部事件或用于计算内部时钟周期。

36.2.3 低功耗定时器时钟选择问题(重要)

这个知识点比较重要,可以帮助大家更好的理解LPTIM。下面先看框图:

首先将框图里面两个最重要的标识跟寄存器对上号。

1、lptim_ker_ck接口

内核时钟,供lptim使用。lptim_ker_tim接入到CLKMUX双路选择器的一个输入端,另一个输入端是LPTIM_IN1或者LPTIM_IN2的输入。也就是说LPTIM的计数器可以选择lptim_ker_ck,也可以选择LPTIM_IN1或者LPTIM_IN。

2、最关键的地方来了

(1) CLKMUX多路选择器对应的是CFGR寄存器的bit0:CKSEL

  • 用于控制内核时钟选择由内部时钟源(APB时钟或LSE、LSI和HSI等任何其他内置振荡器)提供时钟。

  • 也可以选择由外部时钟源通过 LPTIM 外部 Input提供时钟。

(2) Count mode对应的是CFGR寄存器的bit23:COUNTMODE计数模式位,用于选择 LPTIM 使用哪个时钟源来为计数器提供时钟。

  • 可以选择计数器在每个内部时钟脉冲后递增。

  • 或者在 LPTIM 外部 Input上的每个有效时钟脉冲后递增。

3、应用的时候,我们可以选择

(1) CKSEL = 0 , COUNTMODE = 0

表示LPTIM内核时钟使用的内部时钟源,计数器通过内部时钟脉计数。

(2) CKSEL = 0 , COUNTMODE = 1

表示LPTIM内核时钟使用的内部时钟源,计数器通过外部输入脉冲计数。

(3) CKSEL = 1 , COUNTMODE = x

表示LPTIM内核时钟使用的外部时钟源,计数器通过外部输入脉冲计数。

36.2.4 干扰滤波器(Glitch filter)

Glitch filter干扰滤波器的作用是避免任何毛刺和噪声干扰在 LPTIM 内部传播,从而防止产生意外计数或触发。

实现原理就是LPTIM的CFGR寄存器有专门的控制位TRGFLT[1:0](用于滤波外部触发信号)和CKFLT[1:0](用于滤波外部输入时钟)来控制信号,其有效电平变化必须至少稳定2/4/8个时钟周期才能将其视为有效触发。

比如下面的截图,配置为稳定2个时钟周期才算有效信号。

36.2.5 单次触发和连续模式

单次触发的含义就是定时器由触发事件启动,当达到 ARR 值时停止,效果如下:

连续模式的含义是定时器由触发事件启动,并且直到被禁止才会停止,效果如下:

36.2.6 溢出模式

注:这个模式用来做停机模式唤醒比较方便。

检测引脚第1次检查到触发信号,LPTIM就开始工作了,在溢出时间内检测到的触发信号都将复位计数,定时器重新开始工作。如果溢出内没有再接收到触发信号,仅进入溢出中断。

36.2.7 波形输出

通过下面的截图,可以让大家对低功耗定时器的波形输出效果有个全面认识。

LPTIM_ARR是自动重载寄存器,Compare是比较寄存器。当定时器的计数器达到Compare后,GPIO输出高电平还是低电平,是由CFGR寄存器的bit2:1:WAVPOL波形极性决定的。

以PWM输出为例:

  • 如果WAVPOL = 0表示计数器的数值介于Compare和LPTIM_ARR之间时,GPIO输出高电平。其它时间是低电平。

  • 如果WAVPOL = 1表示计数器的数值介于Compare和LPTIM_ARR之间时,GPIO输出低电平。其它时间是高电平。

One–Shot效果跟PWM一样,不过GPIO仅输出1次脉冲。

Set–Once特殊些,计数到ARR后,GPIO输出结果将一直保持达到Compare寄存器数值的输出电平。

36.2.8 低功耗定时器LPTIM1 – LPTIM5的区别

关于这五个低功耗定时器的区别,可以直接通过参考手册里面的框图看它们的区别。我们这里也简单整理下:

  • LPTIM1和LPTIM2的功能是一样的,且支持编码器模式,而LPTIM3,LPTIM4和LPTIM5均不支持。

  • LPTIM3跟LPTIM1的区别是仅有1组LPTIM_IN输入,且不支持LTPTIM_ETR。

  • LPTIM4和LPTIM5的功能是一样的,这两个功能最弱。跟LPTIM1的区别是没有LPTIM_IN输入端,也不支持LPTIM_ETR,仅有一个内部触发lptim_ext_trigx。

36.3 低功耗定时器的HAL库用法

低功耗定时器的HAL库用法其实就是几个结构体变量成员的配置和使用,然后配置GPIO、时钟,并根据需要配置NVIC,中断和DMA。下面我们逐一展开为大家做个说明。

36.3.1 定时器寄存器结构体LPTIM_TypeDef

低功耗定时器相关的寄存器是通过HAL库中的结构体LPTIM_TypeDef定义的,在stm32h743xx.h中可以找到这个类型定义:

typedef struct

{

  __IO uint32_t ISR;      /*!< LPTIM Interrupt and Status register,         Address offset: 0x00 */

  __IO uint32_t ICR;      /*!< LPTIM Interrupt Clear register,              Address offset: 0x04 */

  __IO uint32_t IER;      /*!< LPTIM Interrupt Enable register,             Address offset: 0x08 */

  __IO uint32_t CFGR;     /*!< LPTIM Configuration register,                Address offset: 0x0C */

  __IO uint32_t CR;       /*!< LPTIM Control register,                      Address offset: 0x10 */

  __IO uint32_t CMP;      /*!< LPTIM Compare register,                      Address offset: 0x14 */

  __IO uint32_t ARR;      /*!< LPTIM Autoreload register,                   Address offset: 0x18 */

  __IO uint32_t CNT;      /*!< LPTIM Counter register,                      Address offset: 0x1C */

  uint16_t  RESERVED1;    /*!< Reserved, 0x20                                                    */

  __IO uint32_t CFGR2;    /*!< LPTIM Option register,                      Address offset: 0x24 */

} LPTIM_TypeDef;

这个结构体的成员名称和排列次序和CPU的定时器寄存器是一 一对应的。


__IO表示volatile, 这是标准C语言中的一个修饰字,表示这个变量是非易失性的,编译器不要将其优化掉。core_m7.h 文件定义了这个宏:


#define     __O     volatile             /*!< Defines 'write only' permissions */

#define     __IO    volatile             /*!< Defines 'read / write' permissions */

下面我们看下LPTIM1,LPTIM2,LPTIM3,LPTIM4和LPTIM5的定义,在stm32h743xx.h文件。


#define PERIPH_BASE         ((uint32_t)0x40000000)

#define D2_APB2PERIPH_BASE   (PERIPH_BASE + 0x00010000)

#define D3_APB1PERIPH_BASE   (PERIPH_BASE + 0x18000000)


#define LPTIM1_BASE           (D2_APB1PERIPH_BASE + 0x2400)

#define LPTIM2_BASE           (D3_APB1PERIPH_BASE + 0x2400)

#define LPTIM3_BASE           (D3_APB1PERIPH_BASE + 0x2800)

#define LPTIM4_BASE           (D3_APB1PERIPH_BASE + 0x2C00)

#define LPTIM5_BASE           (D3_APB1PERIPH_BASE + 0x3000)



#define LPTIM1              ((LPTIM_TypeDef *) LPTIM1_BASE) #define LPTIM2              ((LPTIM_TypeDef *) LPTIM2_BASE)

#define LPTIM3              ((LPTIM_TypeDef *) LPTIM3_BASE)

#define LPTIM4              ((LPTIM_TypeDef *) LPTIM4_BASE)

#define LPTIM5              ((LPTIM_TypeDef *) LPTIM5_BASE)

我们访问LPTIM的ISR寄存器可以采用这种形式:LPTIM->ISR = 0。


36.3.2 定时器句柄结构体LPTIM_HandleTypeDef

HAL库在LPTIM_TypeDef的基础上封装了一个结构体LPTIM_HandleTypeDef,定义如下:


typedef struct

{

      LPTIM_TypeDef              *Instance;         /*!< Register base address     */

      LPTIM_InitTypeDef           Init;             /*!< LPTIM required parameters */

      HAL_StatusTypeDef           Status;           /*!< LPTIM peripheral status   */  

      HAL_LockTypeDef             Lock;             /*!< LPTIM locking object      */

   __IO  HAL_LPTIM_StateTypeDef   State;            /*!< LPTIM peripheral state    */

  

}LPTIM_HandleTypeDef;

这里重点介绍前两个参数,其它参数主要是HAL库内部使用的。


TIM_TypeDef *Instance


这个参数是寄存器的例化,方便操作寄存器,比如使能定时器的计数器。


SET_BIT(huart->Instance->CR, LPTIM_CR_CNTSTRT)。


LPTIM_InitTypeDef Init


这个参数是用户接触最多的,用于配置低功耗定时器的基本参数。


LPTIM_InitTypeDef结构体的定义如下:


typedef struct

{                                                  

  LPTIM_ClockConfigTypeDef     Clock;               

  LPTIM_ULPClockConfigTypeDef  UltraLowPowerClock;  

  LPTIM_TriggerConfigTypeDef   Trigger;             

  uint32_t                     OutputPolarity;                                                      

  uint32_t                     UpdateMode;          

  uint32_t                     CounterSource;      

  uint32_t                     Input1Source;       

  uint32_t                     Input2Source;       

}LPTIM_InitTypeDef;

成员Clock

用于设置时钟源和时钟分频,结构体变量LPTIM_ClockConfigTypeDef的定义如下。


typedef struct

{

  uint32_t Source;   

文章来源于:电子工程世界    原文链接
本站所有转载文章系出于传递更多信息之目的,且明确注明来源,不希望被转载的媒体或个人可与我们联系,我们将立即进行删除处理。