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
相关产品推荐
相关产品推荐

