134 lines
4.5 KiB
C
134 lines
4.5 KiB
C
#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溢出标志
|
||
}
|