Files
CHJ/user/MCU/lhl_rtc.c
2026-03-20 21:19:53 +08:00

134 lines
4.5 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "../main/SystemInclude.h"
/**
* @brief RTC 基础初始化(仅需一次)
* @note 配置时钟源为 LSI32.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溢出标志
}