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

STM32F103RCT6 RTC闹钟中断触发后主循环输出停止问题求助

STM32F103RCT6 RTC闹钟中断后主循环输出停止的解决方案

针对你遇到的RTC闹钟激活后,中断反复打印"Alarm match"但主循环输出停滞的问题,结合STM32F1系列的硬件特性,从以下核心点排查修复:

1. 修正RTC中断标志位的清除逻辑

STM32F1的RTC闹钟中断依赖EXTI线17触发,必须同时清除RTC内部标志和EXTI挂起标志,只清除其中一个会导致中断持续触发,CPU被中断抢占无法执行主循环。

正确的中断服务函数实现:

#include "stm32f1xx_it.h"
#include "stm32f1xx_rtc.h"
#include "stm32f1xx_exti.h"

void RTC_IRQHandler(void)
{
    // 检查闹钟中断触发
    if (RTC_GetITStatus(RTC_IT_ALR) != RESET)
    {
        printf("Alarm match\r\n");

        // 第一步:清除RTC闹钟中断标志
        RTC_ClearITPendingBit(RTC_IT_ALR);
        // 第二步:清除EXTI线17的挂起标志(F1系列必须操作)
        EXTI_ClearITPendingBit(EXTI_Line17);
        // 等待RTC寄存器操作完成(F1系列必要同步步骤)
        RTC_WaitForLastTask();
    }
}

2. 调整中断优先级配置

如果RTC中断的抢占优先级过高,会持续抢占主循环执行资源。确保NVIC配置中RTC中断优先级为中等,避免完全阻塞主循环:

NVIC配置示例:

#include "stm32f1xx_nvic.h"

void RTC_NVIC_Config(void)
{
    NVIC_InitTypeDef NVIC_InitStructure;
    NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
    // 设置抢占优先级为2(数值越小优先级越高,根据实际系统调整)
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
}

3. 解决printf的重入冲突

串口printf默认不具备重入性,中断和主循环同时调用printf会导致串口输出阻塞或混乱。可以通过临界区保护解决:

主循环输出示例:

// 主循环中输出日期时间
__disable_irq(); // 关闭中断,进入临界区
printf("Date: %02d-%02d-%02d Time: %02d:%02d:%02d\r\n", 
       year, month, day, hour, minute, second);
__enable_irq();  // 恢复中断

中断中输出示例:

void RTC_IRQHandler(void)
{
    if (RTC_GetITStatus(RTC_IT_ALR) != RESET)
    {
        __disable_irq();
        printf("Alarm match\r\n");
        __enable_irq();

        // 清除标志位步骤...
    }
}

4. 排查主循环中的阻塞操作

检查主循环是否存在死循环等待、高优先级阻塞延时(如依赖SysTick的HAL_Delay)。如果RTC中断优先级高于SysTick,会导致HAL_Delay无法正常计时,主循环被卡住。建议改用非阻塞式延时或调整优先级。

5. 确保RTC初始化的同步正确性

STM32F1的RTC寄存器需要同步操作,初始化时必须添加同步等待,避免后续读写异常:

RTC初始化关键步骤:

#include "stm32f1xx_rcc.h"
#include "stm32f1xx_pwr.h"
#include "stm32f1xx_bkp.h"
#include "stm32f1xx_rtc.h"

void RTC_Init(void)
{
    // 使能PWR和BKP时钟
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE);
    // 允许访问备份区域
    PWR_BackupAccessCmd(ENABLE);

    // 等待RTC寄存器同步(必须操作)
    RTC_WaitForSynchro();
    // 等待最后一次RTC操作完成
    RTC_WaitForLastTask();

    // 后续闹钟配置...
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 05:03:31