You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

STM32L412裸机编程中RTC唤醒中断无法触发问题求助

STM32L412T6 RTC唤醒中断不触发问题修复

以下是代码中存在的关键问题及对应修复方案:

1. 唤醒定时器时钟源配置错误

当前配置的时钟源为RTC->CR |= (1U<<2)(WUCKSEL=010),对应RTCCLK/16(32.768kHz/16=2048Hz),会导致唤醒周期远小于预期的3秒。要实现秒级触发,需将时钟源配置为RTCCLK/1024(WUCKSEL=100),得到32Hz的时钟,再通过重载值计算实现3秒触发:

  • 3秒对应的计数值:32Hz * 3s -1 = 95

修复代码:

// 替换原时钟源配置代码
/* Configure the clock source */
RTC->CR &= ~(0x7 << 0); // 清除WUCKSEL[2:0]位
RTC->CR |= (0x4 << 0);  // 设置WUCKSEL=100,RTCCLK/2^10=32Hz

2. WUTR寄存器赋值错误

使用|=操作符设置重载值会保留寄存器原有值导致计数错误,应直接用=覆盖:

// 替换原WUTR配置代码
/* Configure the Wakeup Timer counter */
RTC->WUTR = 95; // 32Hz*3s -1 =95,实现3秒触发
// 高16位自动重载值在当前时钟源下无效,无需设置

3. 变量未全局/volatile声明

count、flag等变量需全局声明并添加volatile修饰,防止编译器优化导致变量值异常:

// 在所有函数外添加
volatile uint32_t count = 0;
volatile uint32_t flag = 0;
#define RTC_WAKEUP_TIME_IN_SECONDS 3
#define WakeUpAutoClr 0

4. NVIC优先级配置缺失

仅使能IRQ未设置优先级,部分场景下可能导致中断无法响应,添加优先级配置:

// 在main函数中NVIC_EnableIRQ前添加
NVIC_SetPriority(RTC_WKUP_IRQn, 2); // 设置合适优先级(范围0-15,数值越小优先级越高)

5. 初始化顺序调整

先配置NVIC再初始化唤醒定时器,确保中断使能在定时器启动前完成:

int main(void)
{
    //LedConfig();
    rtc_domain_access();
    rtc_init();

    NVIC_SetPriority(RTC_WKUP_IRQn, 2);
    NVIC_EnableIRQ(RTC_WKUP_IRQn);
    initialize_rtc_wakeup();

    /* Loop forever */
    for(;;)
    {
        flag = 1;
    }
}

6. 中断处理函数优化

确保正确清除所有相关标志位,避免中断被挂起:

void RTC_WKUP_IRQHandler(void)
{
    // 清除EXTI挂起标志
    EXTI->PR1 = (1U<<20);
    // 检查RTC唤醒中断标志
    if((RTC->ISR & RTC_ISR_WUTIF) != 0)
    {
        RTC->ISR &= ~RTC_ISR_WUTIF; // 清除RTC唤醒中断标志
        count++ ;
    }
}

完整修改后的关键函数片段

// 全局变量声明
volatile uint32_t count = 0;
volatile uint32_t flag = 0;
#define RTC_WAKEUP_TIME_IN_SECONDS 3
#define WakeUpAutoClr 0

int main(void)
{
    //LedConfig();
    rtc_domain_access();
    rtc_init();

    NVIC_SetPriority(RTC_WKUP_IRQn, 2);
    NVIC_EnableIRQ(RTC_WKUP_IRQn);
    initialize_rtc_wakeup();

    /* Loop forever */
    for(;;)
    {
        flag = 1;
    }
}

void RTCEx_SetWakeUpTimer_IT(uint32_t wakeup_counter, uint32_t WakeUpAutoClr)
{
     /* Disable the write protection for RTC registers */
    RTC->WPR = 0xCA;
    RTC->WPR = 0x53;

     /* Clear WUTE in RTC_CR to disable the wakeup timer */
    RTC->CR &= ~(1U<<10);

     /* Clear flag Wake-Up */
    RTC->ISR &= ~RTC_ISR_WUTIF;
    EXTI->PR1 = (1U<<20);

     /* Poll WUTWF until it is set in RTC_ICSR to make sure the access to wakeup autoreload
         counter and to WUCKSEL[2:0] bits is allowed. */
    if((RTC->ISR & RTC_ISR_INITF) == 0)
    {
        while((RTC->ISR & RTC_ISR_WUTWF) == 0);
    }

    /* Configure the Wakeup Timer counter */
    RTC->WUTR = wakeup_counter;

   /* Configure the clock source */
    RTC->CR &= ~(0x7 << 0);
    RTC->CR |= (0x4 << 0);

     /* RTC WakeUpTimer EXTI Configuration: Interrupt configuration */
    EXTI->IMR1 |= (1U<<20);
    EXTI->RTSR1 |= (1U<<20);

     /* Configure the Interrupt in the RTC_CR register */
    RTC->CR |= (1U<<14);

     /* Enable the Wakeup Timer */
    RTC->CR |= (1U<<10);

     /* Enable the write protection for RTC registers */
    RTC->WPR = 0xFF;
}

void initialize_rtc_wakeup(void)
{
    RTCEx_DeactivateWakeUpTimer();
    Pwr_Clear_Flag();
    RTCEx_SetWakeUpTimer_IT(95, WakeUpAutoClr); // 传入计算好的计数值
}

void RTC_WKUP_IRQHandler(void)
{
    EXTI->PR1 = (1U<<20);
    if((RTC->ISR & RTC_ISR_WUTIF) != 0)
    {
        RTC->ISR &= ~RTC_ISR_WUTIF;
        count++ ;
    }
}

内容的提问来源于stack exchange,提问作者Suhaib Saiyde

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.03 06:05:24