请选择 进入手机版 | 继续访问电脑版

你的浏览器版本过低,可能导致网站不能正常访问!
为了你能正常使用网站功能,请使用这些浏览器。

低功耗定时器LPTIM应用

[复制链接]
gaosmile 发布时间:2021-2-9 21:17

目标实现:使用LPTIM1,在低功耗stop模式下定时1s,1s后将STM32从stop模式唤醒,并且点亮LED灯

1 LPTIM 介绍

LPTIM,顾名思义,即低功耗定时器的意思,与普通定时器的差别是LPTIM在睡眠或者停机模式下依然可以工作(待机模式除外),支持低速时钟 LSI、 LSE 或者外部输入时钟。LPTIM是低功耗产品在低功耗功耗模式下定时的不二之选

  • 支持芯片:并不是STM32的所有芯片都有LPTIM这个外设,,从官方资料可知,支持LPTIM的芯片有:STM32F410、STM32F413/423、STM32F7系列, STM32G0系列, STM32H7系列, STM32L0系列, STM32L4系列, STM32L4+系列, STM32L5系列, STM32WB系列 微信图片_20210209204303.png

    微信图片_20210209204307.png
  • STM32L431芯片手册对LPTIM的介绍

    微信图片_20210209204310.png + B9 C. J- l$ |- r* H  s: q
微信图片_20210209204313.png 2 LPTIM 功能

LPTIM 低功耗定时器有以下 6 种模式:

  • 单脉冲模式
  • PWM 模式
  • 单次模式:在此模式下,当满足匹配条件时,输出可以切换高低电平(如果输出极性配置为高,则为低电平至高电平变化,反之亦然)
  • 编码器模式
  • 超时模式:有效的边沿触发输入可复位定时器。第一个触发事件将启动计时器,任何连续触发事件将重置计 数器并重新开始。
  • 计数器模式:计数器可用于计算来自 Input1 的外部事件或用于计算内部时钟周期
    3 W; u1 _% L8 k* R

主要有以下三个使用场景,本文将介绍LPTIM超时唤醒的应用:

  • Asynchronous pulse counter in Stop mode(异步脉冲计数)

  • PWM generator in Stop mode(PWM输出)

  • Timeout wakeup mode(超时唤醒)


    7 |0 c3 E' m: u
3 LPTIM初始化结构体

介绍下LPTIM初始化结构体各个参数的含义及配置

微信图片_20210209204317.png 3.1 Clock
  • Clock用于设置时钟源和时钟分频 微信图片_20210209204321.png

  • 其中,时钟源参数 Source 可以选择如下两种: 微信图片_20210209204324.png


    ! D/ ]! y% n/ r$ Z5 j
    • #define LPTIM_CLOCKSOURCE_APBCLOCK_LPOSC ((uint32_t)0x00U) 表示 LPTIM 由内部时钟源(APB 时钟或 APB 或 LSE、 LSI 和 HSI 等)提供时钟

    • #define LPTIM_CLOCKSOURCE_ULPTIM LPTIM_CFGR_CKSEL 表示 LPTIM 由外部时钟源通过 LPTIM 外部 Input1 提供时钟

      3 B# E* f7 I) [! y1 V
  • Prescaler 时钟分频参数则可以选择八种,有1、2、4、8、16、32、64、128分频:

  • 微信图片_20210209204327.png


    ( @8 D  Q3 A/ L6 T
3.2 UltraLowPowerClock
  • UltraLowPowerClock参数仅在使用超低功耗时钟源时使用,用于设置所选择的外部时钟

  • 微信图片_20210209204329.png

  • 其中,时钟极性参数 Polarity 用于选择有效的时钟极性,如果使能了双边沿,Auxiliary Clock(一种低功耗振荡器)必须处于激活状态 微信图片_20210209204332.png

  • SampleTime 参数用于配置时钟干扰滤波器 微信图片_20210209204335.png


    ! ~* S; N) I4 l; R
3.3 Trigger
  • Trigger 用于配置触发参数

  • 微信图片_20210209204338.png

  • 其中,Source 参数配置触发源,可选配置如下: 微信图片_20210209204341.png

  • ActiveEdge 参数用于设置有效的触发边沿,可以选择上升沿,下降沿或者双边沿触发

  • 微信图片_20210209204344.png

  • SampleTime参数配置采样时间

  • 微信图片_20210209204348.png

    % `9 O! ^% [' M
3.4 OutputPolarity
  • OutputPolarity 用于配置输出极性,可选择高电平或者低电平输出 微信图片_20210209204352.png
    ) d+ H2 }& X9 m: a* Z% Q( }5 y& `3 I7 R
3.5 UpdateMode
  • UpdateMode用于配置是否立即更新自动重装寄存器和比较寄存器,可以选择立即更新,或者当前周期结束后更新 微信图片_20210209204355.png
    9 E) U( J" `* Z
3.5 CounterSource
  • CounterSource用于配置定时器计数器在每个内部事件或者外部事件后递增计数,可以选择内部或者外部
  • 微信图片_20210209204358.png
    ; }3 ], ?! ~: O0 N% ]
3.6 Input1Source
  • Input1Source用于配置 Input1 的输入源,可以选择 GPIO,比较器输出或者 SAI FSA/FSB
  • 微信图片_20210209204401.png
    2 h* w" f2 t$ x; {
3.7 Input2ource
  • Input2ource用于配置 Input2 的输入源,可以选择 GPIO 和比较器(注意:此参数仅用于编码器模式)
  • 微信图片_20210209204404.png
      C2 s1 v9 w$ W# ~
3 LPTIM 超时唤醒应用

需求:使用LPTIM1,在低功耗stop模式下定时1s,1s后将STM32从stop模式唤醒,并且点亮LED灯

3.1 LPTIM1时钟初始化
  • 配置LPTIM1时钟为LSE,即外部低速时钟32768Hz,也可配置为内部低速时钟LSI,修改对应配置即可
    8 `* H" ~, C  {7 N; Q' l1 _" d
RCC_PeriphCLKInitTypeDef RCC_PeriphCLKInitStruct = {0};
2 n$ e. B. A) F+ b- m% bRCC_OscInitTypeDef RCC_OscInitStruct = {0};- q" {3 l. o7 ]) \
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;1 o( c5 \1 W! v7 e  Z3 J. Q
RCC_OscInitStruct.LSEState = RCC_LSE_ON;: S) i1 x9 t' M9 I" ?' |
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
  d0 W* y) t" P- a. m- K; @if (HAL_RCC_OscConfig(&RCC_OscInitStruct)!= HAL_OK)& Q" O+ u: h/ K" ~3 ?% i9 k
{4 `& n7 \+ S8 \+ @
Error_Handler(__FILE__, __LINE__);% ?4 Q+ ]# i8 L/ V1 l  a
}" M0 M* a$ e1 @4 W9 B3 X9 O0 F
RCC_PeriphCLKInitStruct.PeriphClockSelection = RCC_PERIPHCLK_LPTIM1;" o3 Y* x% A7 C9 V. _9 J
RCC_PeriphCLKInitStruct.Lptim1ClockSelection = RCC_LPTIM1CLKSOURCE_LSE;
) w/ f# O3 C4 X+ lHAL_RCCEx_PeriphCLKConfig(&RCC_PeriphCLKInitStruct);' F+ D1 K3 W. Y' Z# |4 `; b" r
3.2 LPTIM1初始化
  • 按上面概述的参数配置,对LPTIM1进行配置如下
    0 R) F3 v8 m. G& [6 @
LPTIM_HandleTypeDef hlptim1;
( L/ c1 ^1 t" N9 g8 h6 g$ E' @; A! I4 U" c
void MX_LPTIM1_Init(void)& H0 T# a' K, y& j
{. Z% {' Q( Q# W
  hlptim1.Instance = LPTIM1;
/ C8 J4 K" l" d2 X5 t8 a5 O9 u- a  hlptim1.Init.Clock.Source = LPTIM_CLOCKSOURCE_APBCLOCK_LPOSC;  //选择内部时钟源$ b- H  p8 |% i, }* L  K
  hlptim1.Init.Clock.Prescaler = LPTIM_PRESCALER_DIV64;           //设置LPTIM时钟分频' D9 [* j( ^# y& L$ d9 S
  hlptim1.Init.Trigger.Source = LPTIM_TRIGSOURCE_SOFTWARE;                        //设置软件触发/ S- M: e% \! z
  hlptim1.Init.Trigger.ActiveEdge = LPTIM_ACTIVEEDGE_RISING;                      //设置上升沿触发
8 _/ d4 Z1 e0 J: ]0 L6 x5 W  hlptim1.Init.Trigger.SampleTime = LPTIM_TRIGSAMPLETIME_DIRECTTRANSITION;        //设置时钟干扰滤波器1 U' K& V# q( ~3 \9 F
  hlptim1.Init.OutputPolarity = LPTIM_OUTPUTPOLARITY_HIGH;     //设置输出高电平
3 v2 P1 M) E5 s4 D( P- E  hlptim1.Init.UpdateMode = LPTIM_UPDATE_IMMEDIATE;            //比较寄存器和ARR自动重载寄存器选择更改后立即更新! |% E  L! l5 o2 N& i# f/ G
  hlptim1.Init.CounterSource = LPTIM_COUNTERSOURCE_INTERNAL;   //LPTIM计数器对内部时钟源计数
! U" e8 p# _5 g& k9 a8 O  T  hlptim1.Init.Input1Source = LPTIM_INPUT1SOURCE_GPIO;         //外部输入1,本配置未使用' z% z% z+ x* |. b
  hlptim1.Init.Input2Source = LPTIM_INPUT2SOURCE_GPIO;         //外部输入2,本配置未使用
* T( Z: W5 Q! S& w6 d6 H  if (HAL_LPTIM_Init(&hlptim1) != HAL_OK)
# F6 O/ {, C) u& z$ B  {
/ C5 r6 T: l$ H* \5 Y7 G9 m    while (1)
( C5 O+ ]0 c0 M1 }7 |    {
9 g* S0 h2 g" O- f" Q      Error_Handler(__FILE__, __LINE__);7 E) D. c  D  L* E
    }2 z1 d' O# y; o- e
  }& |8 {2 H- o4 W, }6 T* E# u( t2 O: R
}7 q6 \9 O( p, G1 h1 J
  • 当 HAL_LPTIM_Init()运行时会调用 HAL_LPTIM_MspInit()函数,这是一个虚函数,还需要我们重新定义,开启LPTIM时钟及 LPTIM1_IRQn 初始化
    4 a- x. ^7 s" N
void HAL_LPTIM_MspInit(LPTIM_HandleTypeDef* hlptim)
3 |% c# h7 G5 S{
1 Q) D8 l& g" g  if(hlptim->Instance==LPTIM1)8 G$ y. k. t5 L
  {- O2 W7 ^( j! G* w0 D
    /* Peripheral clock enable */
/ b3 G6 x8 ?$ n) b9 p- f8 d' T- z    __HAL_RCC_LPTIM1_CLK_ENABLE();
' I1 v1 }% I& F6 H$ Z/ k$ M6 u& V! x. ?( K  d
    /* Peripheral interrupt init */3 p9 y+ U/ ^9 Q8 b( d
    HAL_NVIC_SetPriority(LPTIM1_IRQn, 0, 0);% t8 s* T7 s+ i, L8 c( V. t
    HAL_NVIC_EnableIRQ(LPTIM1_IRQn);5 g" B( o0 X+ ]- x% Q9 B
  }/ j# v4 P' ]0 J3 q- z; t! x1 o5 T% M, N
}' Q# s3 p9 y8 q4 r+ k, G# R. D
3.3 中断函数
  • 编写中断回调函数,当定时时间到,点亮LED灯% l3 n) e, [7 {8 o$ l" C0 ^
void LPTIM1_IRQHandler(void)/ y; o9 a% H: o" P
{8 p- s2 T1 E0 A9 U: |
  HAL_LPTIM_IRQHandler(&hlptim1);  N& I  C2 O" ?9 b# d1 A; E9 |
}
% G5 V1 I$ H4 E# [4 r5 V7 q4 {
; r' {! M- m' M" {- A5 i5 pvoid HAL_LPTIM_CompareMatchCallback(LPTIM_HandleTypeDef *hlptim)" ~) O, I! U$ {) U) v
{! q( h3 F5 t7 r) u/ k  x; Q3 }+ B; A* i
  /* Timeout was reached, turn on LED */. r# K% @+ ^* X( k/ k6 [
  BSP_LED_On();! U2 m8 x9 {; I, ]
}# |, f  m; i9 A4 H. T9 f+ B0 B+ e
3.4 开启定时器
  • 开启定时器及进入stop模式" \1 X. p. p4 h
#define PERIOD  65535+ A; [! P3 v0 D4 x+ `/ @% U
#define PULSE  32767
' Z3 l$ Q; f% r; x6 M' U( SHAL_LPTIM_TimeOut_Start_IT(&hlptim1, PERIOD, PULSE);. c& ?& b: y5 f7 a- E
$ A6 n. G% `+ ~' G8 v
HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
+ i; J5 U! O* z; z
  • 第1个参数是 LPTIM_HandleTypeDef 类型结构体指针变量
  • 第2个参数是低功耗定时器的周期配置,范围 0 – 0xFFFF。
  • 第3个参数是低功耗定时器的超时时间配置,范围 0 -0xFFFF。
  • 返回值,返回 HAL_ERROR 表示配置失败,HAL_OK 表示配置成功,HAL_BUSY 表示忙(操作中),HAL_TIMEOUT 表示时间溢出
  • 超时时间由 Compare 寄存器决定,即第3个参数,超时配置用不到第2个参数
  • 超时时间计算方式:timeout = (Compare + 1) / LSE_Frequency,如配置Compare = 32767,LSE = 32768Hz,则超时时间为1s
    # _. x# Q: J0 v. y4 a( o" s
4 踩坑记录
  • 在使用官方例程的时候,不能触发定时中断,将触发源由 LPTIM_TRIGSOURCE_0 改为 LPTIM_TRIGSOURCE_SOFTWARE

  • 移植官方例程时,未在 stm32l4xx_hal_conf.h 文件内打开LPTIM 外设的宏定义,导致一直报错

  • 微信图片_20210209204407.png

  • 微信图片_20210209204409.png

  • 配置定时时间时候,未注意到参数范围是 0 -0xFFFF ,导致达不到自己想要的定时时间,最大可配置为65535,在Prescaler参数配置为 LPTIM_PRESCALER_DIV1 1分频的时候,超时时间最大为(65535+1)/32768 = 2s


    * Q1 \; ~3 q) ?# k. Z- D

+ m9 j% h3 q( z3 X5 G% r% [; m
收藏 评论0 发布时间:2021-2-9 21:17

举报

0个回答

所属标签

相似分享

关于意法半导体
我们是谁
投资者关系
意法半导体可持续发展举措
创新和工艺
招聘信息
联系我们
联系ST分支机构
寻找销售人员和分销渠道
社区
媒体中心
活动与培训
隐私策略
隐私策略
Cookies管理
行使您的权利
关注我们
st-img 微信公众号
st-img 手机版