You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多
文档控制台
免费开始使用

STM32 LPTIM中断与低功耗睡眠模式重复触发问题咨询

STM32 LPTIM中断与低功耗睡眠模式重复触发问题咨询

您好,针对您遇到的LPTIM无法重复触发中断的问题,我结合您的代码逻辑和STM32低功耗模式的运行机制,梳理出几个核心问题点和对应的解决方案:

一、当前代码的核心问题

您在LPTIM1_IRQHandler中断处理函数里直接调用HAL_PWREx_EnterSTOP2Mode和重启LPTIM的逻辑,是导致后续无法触发中断的主要原因:

  • 中断处理完成后,系统会自动回到进入中断前的上下文(也就是第一次进入STOP模式前的代码位置),这种在中断内嵌套进入睡眠的操作会打乱系统的执行流程,甚至导致LPTIM的中断标志、寄存器状态没有被正确清理或恢复。
  • STOP2模式下,若LPTIM的时钟源配置不正确(比如使用了在STOP模式下会停止的时钟),也会导致LPTIM无法重新计数。

二、修正后的代码逻辑与实现

我们需要把睡眠模式触发、LPTIM重启的逻辑放回主循环,中断处理函数只负责计数、状态更新和条件判断,这样就能保证每次唤醒后流程清晰,LPTIM可以重复触发。

1. 全局变量保持(假设您已定义)

uint8_t timeout_mov = 0;   // 触发EXTI后的计数变量
uint8_t timeout = 0;       // 未触发EXTI的计数变量
bool b_movement = false;   // EXTI触发标志
bool b_wkup = true;        // 主循环控制标志

2. 主循环调整

while (b_wkup)
{
    // 每次唤醒后,重新启动LPTIM超时中断
    HAL_LPTIM_TimeOut_Start_IT(&hlptim1, 0xFFFF, 2500);
    
    // 进入STOP2低功耗模式,等待中断唤醒
    HAL_PWREx_EnterSTOP2Mode(PWR_STOPENTRY_WFI);
    
    // 唤醒后重置标志,确保循环继续执行
    b_wkup = true;
}

3. EXTI中断处理函数(保持原有逻辑,增加计数器重置)

void EXTI15_10_IRQHandler(void)
{
    HAL_GPIO_EXTI_IRQHandler(INT2_Pin);
    
    // 标记EXTI触发,切换计数模式
    b_movement = true;
    // 重置无运动状态的计数器,避免两种计数逻辑冲突
    timeout = 0;
}

4. LPTIM中断处理函数(简化逻辑,仅处理计数与复位)

void LPTIM1_IRQHandler(void)
{
    // 先让HAL库处理底层中断标志清理等操作
    HAL_LPTIM_IRQHandler(&hlptim1);
    
    if (b_movement)
    {
        timeout_mov++;
        // 达到3次计数,触发复位
        if (timeout_mov >= 3)
        {
            timeout_mov = 0;
            b_movement = false;
            HAL_NVIC_SystemReset();
        }
    }
    else
    {
        timeout++;
        // 达到15次计数,触发复位
        if (timeout >= 15)
        {
            timeout = 0;
            HAL_NVIC_SystemReset();
        }
    }
    
    // 无需在此处启动LPTIM或进入睡眠,主循环会处理后续流程
}

三、关键配置注意事项

  1. LPTIM时钟源确认
    在STM32CubeMX中,务必将LPTIM的时钟源设置为LSI或LSE(这两个时钟在STOP2模式下会持续运行),并在RCC的Power Settings里开启对应时钟在STOP模式下的保持功能。

  2. 中断优先级配置
    在NVIC配置中,确保EXTI中断的优先级高于LPTIM,这样EXTI触发时能及时打断当前的LPTIM计数逻辑,避免计数错误。

  3. HAL回调函数优化(可选)
    您也可以将计数逻辑放到HAL的回调函数中,更符合HAL库的使用规范:

    void HAL_LPTIM_TimeOutCallback(LPTIM_HandleTypeDef *hlptim)
    {
        if (hlptim->Instance == LPTIM1)
        {
            if (b_movement)
            {
                timeout_mov++;
                if (timeout_mov >= 3)
                {
                    timeout_mov = 0;
                    b_movement = false;
                    HAL_NVIC_SystemReset();
                }
            }
            else
            {
                timeout++;
                if (timeout >= 15)
                {
                    timeout = 0;
                    HAL_NVIC_SystemReset();
                }
            }
        }
    }
    

四、修正后的执行流程

  1. 主循环启动LPTIM超时中断,随后进入STOP2模式;
  2. 当LPTIM计数完成,触发中断唤醒MCU,中断处理函数完成计数判断后退出;
  3. 系统回到主循环,重新启动LPTIM并再次进入STOP2模式;
  4. 若EXTI中断触发,MCU被唤醒并切换计数模式,随后主循环重复上述流程;
  5. 当计数达到设定阈值时,触发系统复位。

备注:内容来源于stack exchange,提问作者Faiz-983654

火山引擎 最新活动