#include "../main/SystemInclude.h" /** * @brief RTC 基础初始化(仅需一次) * @note 配置时钟源为 LSI(32.768kHz),预分频器设为 32767 得到 1Hz 计数, * 计数器初始值为 0,闹钟初始值为 0。使用静态标志确保只执行一次。 * @param 无 * @example 内部调用,无需用户直接调用 */ static void RTC_BaseInit(void) { static uint8_t rtc_base_inited = 0; if (rtc_base_inited) return; RTC_InitTypeDef cfg; cfg.ClockSource = RCC_RTCCLKSource_LSI;// RCC_RTCCLKSource_LSE RCC_RTCCLKSource_HSE_DIV128 cfg.Prescaler = 32767; // 1Hz cfg.Counter = 0; cfg.Alarm = 0; LHL_RTC_Init(&cfg); rtc_base_inited = 1; } /**------------------------------------------------------------------------ * @brief 启动 RTC 秒中断 * @note 首次调用时会自动执行 RTC_BaseInit() 完成基础初始化, * 然后使能秒中断,但 NVIC 中断使能需在注册回调时完成。 * 该函数可多次调用,但内部静态标志确保只执行一次配置。 * @param 无 * @example StartRTC_SEC(); **/ void StartRTC_SEC(void) { static uint8_t sec_inited = 0; if (sec_inited) return; RTC_BaseInit(); LHL_RTC_ITConfig(RTC_IT_SECIE, ENABLE); // NVIC_EnableIRQ(RTC_IRQn); // NVIC_SetPriority(RTC_IRQn, 1); sec_inited = 1 ; } /**------------------------------------------------------------------------ * @brief 设置 RTC 闹钟在指定秒数后触发(相对时间) * @param seconds: 延迟秒数(相对于当前计数器值) * @note 首次调用时会自动执行 RTC_BaseInit(),并使能闹钟中断。 * 内部静态标志确保基础配置只执行一次。 * 闹钟中断的 NVIC 使能需在注册回调时完成。 * @example StartRTC_AlarmAfterSeconds(5); // 5 秒后触发闹钟 **/ void StartRTC_AlarmAfterSeconds(uint32_t seconds) { static uint8_t rtc_alrm_inited = 0; if (!rtc_alrm_inited) { RTC_BaseInit(); LHL_RTC_ITConfig(RTC_IT_ALRIE, ENABLE);// 使能 RTC 闹钟中断(注意:SDK 会自动配置 EXTI_LINE_9) // NVIC_EnableIRQ(RTCAlarm_IRQn);// 使能 NVIC 中断 // NVIC_SetPriority(RTCAlarm_IRQn, 0); rtc_alrm_inited = 1; } uint32_t now = 0; LHL_RTC_GetCounter(&now); LHL_RTC_SetAlarm(now + seconds ); } /*-===================================================================================================== //RTC 中断回调 -=====================================================================================================*/ /* 不建议同时开启秒中断和闹钟中断 */ static rtc_irq_callback_t rtc_sec_irq_callback,rtc_alarm_irq_callback ; /**------------------------------------------------------------------------ * @brief 注册 RTC 中断回调函数 * @param rtc_irq_source: 中断源,可选 RTC_SEC(秒中断)或 RTC_ALR(闹钟中断) * @param rtc_irq_callback: 用户回调函数指针 * @note 秒中断注册时会自动使能 RTC_IRQn 并设优先级, * 闹钟中断注册时会自动使能 RTCAlarm_IRQn 并设优先级, * 同时清除对应中断标志。 * @example rtc_register_irq_callback(RTC_SEC, my_sec_callback); **/ void rtc_register_irq_callback(RTC_IRQ_SOURCE_t rtc_irq_source ,rtc_irq_callback_t rtc_irq_callback) { if(rtc_irq_source == RTC_SEC) { rtc_sec_irq_callback = rtc_irq_callback;//赋值回调函数 LHL_RTC_ClearPending(RTC_FLAG_SECF);// 清除中断标志 NVIC_EnableIRQ(RTC_IRQn); NVIC_SetPriority(RTC_IRQn, 1); } else if(rtc_irq_source == RTC_ALR) { rtc_alarm_irq_callback = rtc_irq_callback; LHL_RTC_ClearPending(RTC_FLAG_ALRF); // 清除RTC闹钟中断标志 NVIC_EnableIRQ(RTCAlarm_IRQn);// 使能 NVIC 中断 NVIC_SetPriority(RTCAlarm_IRQn, 0); } } /**------------------------------------------------------------------------ * @brief RTC 秒中断服务函数 * @note 调用已注册的秒中断回调函数(若存在),然后清除秒中断和溢出标志。 **/ void RTC_IRQHandler(void) { uint32_t Time_Count; // 如果有中断发生且注册了回调函数 if (rtc_sec_irq_callback != NULL) rtc_sec_irq_callback();// 调用用户注册的回调函数 // 清除RTC秒中断标志 //if (LHL_RTC_GetPending(RTC_FLAG_SECF) == SET) LHL_RTC_ClearPending(RTC_FLAG_SECF); // 清除RTC秒中断标志 LHL_RTC_ClearPending(RTC_FLAG_OWF); // 清除RTC溢出标志 } /**------------------------------------------------------------------------ * @brief RTC 闹钟中断服务函数 * @note 调用已注册的闹钟中断回调函数(若存在),然后清除闹钟和溢出标志。 **/ void RTCAlarm_IRQHandler(void) { // 如果有中断发生且注册了回调函数 if (rtc_alarm_irq_callback != NULL) rtc_alarm_irq_callback();// 调用用户注册的回调函数 //if (LHL_RTC_GetPending(RTC_FLAG_ALRF) == SET) LHL_RTC_ClearPending(RTC_FLAG_ALRF); // 清除RTC闹钟中断标志 LHL_RTC_ClearPending(RTC_FLAG_OWF); // 清除RTC溢出标志 }