STM32中的LPTIM使用说明
这个函数实现的功能是,在超时时间到达前,如果发生触发事件(例程中是PB6引脚触发),那么定时器清零重新计数,如果没有,则继续计数直到Period周期(其实就是ARR寄存器值)。计数寄存器的值(CNT)从0开始计数,当CNT的值等于CMP时,可触发一些操作(波形输出或者中断,取决于你的配置),此时CNT继续计数,当CNT的值等于ARR时,触发一些操作(波形输出或者中断,取决于你的配置)并且CNT归零
最近工作中用到了STM32的LPTIM定时器,也就是低功耗定时器。
首先看了下官方的示例代码,工程名LPTIM_Timeout。代码不多,也不复杂,由于手上的板子和官方开发板定义不同,所以自己用CubeMX生成了代码。但是调试后发现定时周期总是不对,最后追根溯源,发现生成的代码默认给LPTIM选择的时钟源时PCLK。
PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_LPTIM1;
PeriphClkInit.Lptim1ClockSelection = RCC_LPTIM1CLKSOURCE_PCLK;
if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)
{
Error_Handler();
}
而我一直认为低功耗定时器应该默认就使用低频时钟。(这个有点想当然了,导致走了弯路)其实一开始就怀疑这个问题了,示例代码中时钟源选择放在了main()里面,而生成代码放在了HAL_LPTIM_MspInit()里面。导致我没注意,虽然自己设置了时钟源,但是设置到了HAL_LPTIM_MspInit()前面,导致自己设置的无法生效。
然后就是LPTIM的运行机制。LPTIM支持的模式挺多,好多人可能搞不清楚,这里我简要介绍一下最基本的计数模式。其实一开始我也没搞明白,看了参考手册才大概了解了一些。
LPTIM的计数寄存器是16位,计数时钟可选内部或者外部,预分频1 ~ 128. 触发源有8种(可以GPIO触发,RTC触发等)。支持连续模式和单次模式。
除了计数寄存器,另外两个比较重要的寄存器是ARR和CMP,即自动重载寄存器和比较寄存器。注意,一般来说,CMP的值应该小于ARR。运行逻辑如下:
计数寄存器的值(CNT)从0开始计数,当CNT的值等于CMP时,可触发一些操作(波形输出或者中断,取决于你的配置),此时CNT继续计数,当CNT的值等于ARR时,触发一些操作(波形输出或者中断,取决于你的配置)并且CNT归零。是否重新连续计数,取决于你的模式是单次模式还是连续模式。
对应官方LPTIM_Timeout这个例程,它使用了连续计数模式,并且使用了超时功能。关键代码在于
if (HAL_LPTIM_TimeOut_Start_IT(&LptimHandle, Period, Timeout) != HAL_OK)
{
Error_Handler();
}
HAL_LPTIM_TimeOut_Start_IT()函数启用了超时功能和中断,并以连续模式启动了定时器。这个函数实现的功能是,在超时时间到达前,如果发生触发事件(例程中是PB6引脚触发),那么定时器清零重新计数,如果没有,则继续计数直到Period周期(其实就是ARR寄存器值)。这个函数内部开启了比较匹配中断,超时时会触发中断,回调HAL_LPTIM_CompareMatchCallback()这个函数。
除了官方例程种这个启动定时器的函数,还有几个常用的启动函数可以用。
HAL_LPTIM_SetOnce_Start()
HAL_LPTIM_SetOnce_Start_IT()
这两个是以单次模式启动定时器,一个开中断,一个不开。
HAL_LPTIM_Counter_Start()
HAL_LPTIM_Counter_Start_IT()
这个是以连续模式启动定时器,一个开中断,一个不开。
至于开了哪些中断,可以进入函数查看。
更多推荐



所有评论(0)