2024-08-23 11:16:27 +08:00
|
|
|
|
#include "bsp_rtc.h"
|
|
|
|
|
|
2024-09-02 16:09:03 +08:00
|
|
|
|
|
|
|
|
|
|
2024-08-23 14:07:32 +08:00
|
|
|
|
/* 时钟精度ppm值,根据实测RTC时钟精度填写 */
|
|
|
|
|
#define FRTC_PPM (-20L)
|
|
|
|
|
#define TIMES_TO_GET_TR (0x03) /* 两次读日历不一致后再次循环次数 */
|
2024-08-23 11:16:27 +08:00
|
|
|
|
|
2024-08-23 14:07:32 +08:00
|
|
|
|
/**
|
|
|
|
|
* @brief RTC中断服务函数
|
|
|
|
|
* @retval 无
|
|
|
|
|
*/
|
|
|
|
|
void RTC_TAMP_IRQHandler(void)
|
|
|
|
|
{
|
|
|
|
|
/* enter interrupt */
|
|
|
|
|
rt_interrupt_enter();
|
|
|
|
|
|
|
|
|
|
/* 校准周期中断处理流程 */
|
|
|
|
|
if (std_rtc_get_calib_interrupt_enable() && std_rtc_get_interrupt_flag(RTC_INTERRUPT_FLAG_CALIBRATION))
|
|
|
|
|
{
|
|
|
|
|
/* 清除校准周期标志 */
|
|
|
|
|
std_rtc_clear_flag(RTC_CLEAR_CALIBRATION);
|
|
|
|
|
}
|
|
|
|
|
/* TAMP IN中断处理流程 */
|
|
|
|
|
if (std_tamp_get_interrupt_enable(TAMP_INTERRUPT_TAMP_IN) && std_tamp_get_interrupt_flag(TAMP_INTERRUPT_FLAG_TAMP_IN))
|
|
|
|
|
{
|
|
|
|
|
/* 清除外部入侵检测(外部引脚)的标志 */
|
|
|
|
|
std_tamp_clear_flag(TAMP_CLEAR_FLAG_TAMP_IN);
|
|
|
|
|
}
|
|
|
|
|
/* 闹钟中断处理流程 */
|
|
|
|
|
if (std_rtc_get_alarm_interrupt_enable() && std_rtc_get_interrupt_flag(RTC_INTERRUPT_FLAG_ALARM))
|
|
|
|
|
{
|
|
|
|
|
/* 清除闹钟标志 */
|
|
|
|
|
std_rtc_clear_flag(RTC_CLEAR_ALARM);
|
|
|
|
|
}
|
2024-09-02 16:09:03 +08:00
|
|
|
|
/* 周期中断处理流程 */
|
|
|
|
|
if (std_rtc_get_wut_interrupt_enable(RTC_WUT_INTERRUPT_MIN) && std_rtc_get_interrupt_flag(RTC_INTERRUPT_FLAG_MIN))
|
2024-08-23 14:07:32 +08:00
|
|
|
|
{
|
2024-09-02 16:09:03 +08:00
|
|
|
|
/* 清除周期中断标志 */
|
|
|
|
|
std_rtc_clear_flag(RTC_INTERRUPT_FLAG_MIN);
|
2024-08-23 14:07:32 +08:00
|
|
|
|
}
|
|
|
|
|
/* leave interrupt */
|
|
|
|
|
rt_interrupt_leave();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief RTC日期时间配置
|
|
|
|
|
* @retval 无 BCD输入
|
|
|
|
|
*/
|
2024-09-02 16:09:03 +08:00
|
|
|
|
void BSP_Rtc_DateTime_Cfg(uint8_t years, uint8_t months, uint8_t days, uint8_t hour, uint8_t minute, uint8_t second, uint8_t week)
|
2024-08-23 14:07:32 +08:00
|
|
|
|
{
|
|
|
|
|
std_rtc_time_t rtc_time = {0};
|
|
|
|
|
std_rtc_date_t rtc_date = {0};
|
|
|
|
|
std_status_t status = STD_ERR;
|
|
|
|
|
|
|
|
|
|
/* RTC日期(BCD码)初始化 */
|
|
|
|
|
// rtc_date.weekday = RTC_WEEKDAY_FRIDAY;
|
|
|
|
|
// rtc_date.month = RTC_MONTH_AUGUST;
|
|
|
|
|
|
|
|
|
|
rtc_date.weekday = week;
|
|
|
|
|
rtc_date.month = months;
|
|
|
|
|
rtc_date.day = days;
|
|
|
|
|
rtc_date.year = years;
|
|
|
|
|
|
|
|
|
|
status = std_rtc_date_init(&rtc_date);
|
|
|
|
|
while (status != STD_OK)
|
|
|
|
|
{
|
|
|
|
|
/* RTC日期初始化失败处理代码 */
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* RTC时间(BCD码)初始化 */
|
|
|
|
|
rtc_time.hours = hour;
|
|
|
|
|
rtc_time.minutes = minute;
|
|
|
|
|
rtc_time.seconds = second;
|
|
|
|
|
|
|
|
|
|
status = std_rtc_time_init(&rtc_time);
|
|
|
|
|
while (status != STD_OK)
|
|
|
|
|
{
|
|
|
|
|
/* RTC时间初始化失败处理代码 */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
MSH_CMD_EXPORT(BSP_Rtc_DateTime_Cfg, " BCD格式输入 RTC日期时间配置:y,m,d,h,m,s,w ");
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief RTC_OUT输出信号配置
|
|
|
|
|
* @retval 无
|
|
|
|
|
*/
|
|
|
|
|
void BSP_Rtc_OutPut_Config(void)
|
|
|
|
|
{
|
|
|
|
|
/* 关闭RTC寄存器写保护 */
|
|
|
|
|
std_rtc_write_protection_disable();
|
|
|
|
|
|
|
|
|
|
/* 配置RTC_OUT输出1Hz */
|
|
|
|
|
std_rtc_out_config(RTC_OUTPUT_SPRE_1HZ);
|
|
|
|
|
|
|
|
|
|
/* 配置RTC_OUT输出使能 */
|
|
|
|
|
std_rtc_output_enable();
|
|
|
|
|
|
|
|
|
|
/* 使能RTC寄存器写保护 */
|
|
|
|
|
std_rtc_write_protection_enable();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief RTC_OUT输出信号配置
|
|
|
|
|
* @retval 无
|
|
|
|
|
*/
|
|
|
|
|
void BSP_Rtc_Output_Cfg(void)
|
|
|
|
|
{
|
|
|
|
|
/* 配置RTC_OUT输出1Hz */
|
|
|
|
|
std_rtc_out_config(RTC_OUTPUT_SPRE_1HZ);
|
|
|
|
|
/* 配置RTC_OUT输出使能 */
|
|
|
|
|
std_rtc_output_enable();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief 外部引脚入侵检测TAMP IN配置
|
|
|
|
|
* @retval 无
|
|
|
|
|
*/
|
|
|
|
|
void bsp_rtc_tamp_in_config(void)
|
|
|
|
|
{
|
|
|
|
|
/* 关闭RTC寄存器写保护 */
|
|
|
|
|
std_rtc_write_protection_disable();
|
|
|
|
|
|
|
|
|
|
/* 关闭RTC_OUT信号输出 */
|
|
|
|
|
std_rtc_output_disable();
|
|
|
|
|
|
|
|
|
|
/* RTC寄存器写保护使能 */
|
|
|
|
|
std_rtc_write_protection_enable();
|
|
|
|
|
|
|
|
|
|
/* 禁止外部入侵检测 */
|
|
|
|
|
std_tamp_disable(TAMP_SOURCE_TAMP_IN);
|
|
|
|
|
|
|
|
|
|
/* 设置入侵检测触发方式 */
|
|
|
|
|
std_tamp_set_trigger(TAMP_TRIGGER_FALLING_EDGE);
|
|
|
|
|
|
|
|
|
|
/* 设置入侵检测引脚数字滤波参数 */
|
|
|
|
|
std_tamp_set_filter(TAMP_FILTER_DISABLE);
|
|
|
|
|
|
|
|
|
|
/* 使能入侵检测引脚上拉电阻 */
|
|
|
|
|
std_tamp_pullup_enable();
|
|
|
|
|
|
|
|
|
|
/* 使能外部入侵检测中断 */
|
|
|
|
|
std_tamp_interrupt_enable(TAMP_INTERRUPT_TAMP_IN);
|
|
|
|
|
|
|
|
|
|
/* 使能外部入侵检测 */
|
|
|
|
|
std_tamp_enable(TAMP_SOURCE_TAMP_IN);
|
|
|
|
|
|
|
|
|
|
/* 配置中断优先级 */
|
|
|
|
|
NVIC_SetPriority(RTC_TAMP_IRQn, NVIC_PRIO_0);
|
|
|
|
|
/* 使能中断 */
|
|
|
|
|
NVIC_EnableIRQ(RTC_TAMP_IRQn);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief RTC闹钟配置
|
|
|
|
|
* @retval 无
|
|
|
|
|
*/
|
|
|
|
|
void BSP_Rtc_Alarm_Config(uint8_t hours, uint8_t minutes, uint8_t seconds)
|
|
|
|
|
{
|
|
|
|
|
std_rtc_alarm_t rtc_alarm = {0};
|
|
|
|
|
|
|
|
|
|
/* 禁止闹钟 */
|
|
|
|
|
std_rtc_write_protection_disable();
|
|
|
|
|
std_rtc_alarm_disable();
|
|
|
|
|
std_rtc_write_protection_enable();
|
|
|
|
|
|
|
|
|
|
/* 闹钟初始化 */
|
|
|
|
|
rtc_alarm.time.hours = std_rtc_convert_bin2bcd(hours);
|
|
|
|
|
rtc_alarm.time.minutes = std_rtc_convert_bin2bcd(minutes);
|
|
|
|
|
rtc_alarm.time.seconds = std_rtc_convert_bin2bcd(seconds);
|
|
|
|
|
rtc_alarm.time_mask = RTC_ALARM_MASK_NONE;
|
|
|
|
|
|
|
|
|
|
std_rtc_alarm_init(&rtc_alarm);
|
|
|
|
|
|
|
|
|
|
/* 使能闹钟,开启闹钟中断 */
|
|
|
|
|
std_rtc_write_protection_disable();
|
|
|
|
|
std_rtc_alarm_interrupt_enable();
|
|
|
|
|
std_rtc_alarm_enable();
|
|
|
|
|
std_rtc_write_protection_enable();
|
|
|
|
|
|
|
|
|
|
/* 配置中断优先级 */
|
|
|
|
|
NVIC_SetPriority(RTC_TAMP_IRQn, NVIC_PRIO_0);
|
|
|
|
|
/* 使能中断 */
|
|
|
|
|
NVIC_EnableIRQ(RTC_TAMP_IRQn);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2024-09-02 16:09:03 +08:00
|
|
|
|
* @brief RTC唤醒定时器配置
|
|
|
|
|
* @retval 无
|
|
|
|
|
*/
|
2024-08-23 14:07:32 +08:00
|
|
|
|
void BSP_Rtc_Wakeup_Config(void)
|
|
|
|
|
{
|
|
|
|
|
/* 关闭RTC寄存器写保护 */
|
|
|
|
|
std_rtc_write_protection_disable();
|
2024-09-02 16:09:03 +08:00
|
|
|
|
|
|
|
|
|
/* 使能分钟周期定时中断 */
|
|
|
|
|
std_rtc_wut_interrupt_enable(RTC_WUT_INTERRUPT_MIN);
|
|
|
|
|
|
2024-08-23 14:07:32 +08:00
|
|
|
|
/* 使能RTC寄存器写保护 */
|
|
|
|
|
std_rtc_write_protection_enable();
|
2024-09-02 16:09:03 +08:00
|
|
|
|
|
2024-08-23 14:07:32 +08:00
|
|
|
|
/* 配置中断优先级 */
|
2024-09-02 16:09:03 +08:00
|
|
|
|
NVIC_SetPriority(RTC_TAMP_IRQn, NVIC_PRIO_0);
|
2024-08-23 14:07:32 +08:00
|
|
|
|
/* 使能中断 */
|
2024-09-02 16:09:03 +08:00
|
|
|
|
NVIC_EnableIRQ(RTC_TAMP_IRQn);
|
2024-08-23 14:07:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
2024-09-02 16:09:03 +08:00
|
|
|
|
* @brief 使能PMU低功耗配置
|
|
|
|
|
* @retval 无
|
|
|
|
|
*/
|
2024-08-23 14:07:32 +08:00
|
|
|
|
void BSP_Pmu_LowPower_Config(void)
|
|
|
|
|
{
|
|
|
|
|
std_rcc_apb1_clk_enable(RCC_PERIPH_CLK_PMU);
|
2024-09-02 16:09:03 +08:00
|
|
|
|
|
2024-08-23 14:07:32 +08:00
|
|
|
|
/* 使能超低功耗配置 */
|
2024-09-02 16:09:03 +08:00
|
|
|
|
std_pmu_ultra_lowpower_enable();
|
2024-08-23 14:07:32 +08:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief 获取日历日期与时间
|
|
|
|
|
* @param rtcdate 输出日期信息
|
|
|
|
|
* @param rtctime 输出时间信息
|
|
|
|
|
* @retval 无
|
|
|
|
|
*/
|
|
|
|
|
void BSP_Rtc_Get_Calendar(uint8_t *rtcdate, uint8_t *rtctime)
|
|
|
|
|
{
|
|
|
|
|
uint32_t i, read_ok = 0;
|
|
|
|
|
uint32_t temp_time1 = 0, temp_time2 = 0;
|
|
|
|
|
uint32_t temp_date1 = 0, temp_date2 = 0;
|
|
|
|
|
|
|
|
|
|
/* 读取日历 */
|
|
|
|
|
for (i = 0; i < TIMES_TO_GET_TR; i++)
|
|
|
|
|
{
|
|
|
|
|
/* 读一次日历时间 */
|
|
|
|
|
temp_time1 = std_rtc_time_get_time();
|
|
|
|
|
temp_date1 = std_rtc_date_get_date();
|
|
|
|
|
|
|
|
|
|
/* 再读一次日历时间 */
|
|
|
|
|
temp_time2 = std_rtc_time_get_time();
|
|
|
|
|
temp_date2 = std_rtc_date_get_date();
|
|
|
|
|
|
|
|
|
|
/* 连续两次读取结果比对 */
|
|
|
|
|
if ((temp_time1 == temp_time2) && (temp_date1 == temp_date2))
|
|
|
|
|
{
|
|
|
|
|
/* 两者一致,表示读取成功 */
|
|
|
|
|
read_ok = 1;
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 时间读取正确 */
|
|
|
|
|
if (read_ok)
|
|
|
|
|
{
|
|
|
|
|
/* 获取时间 */
|
|
|
|
|
rtctime[0] = (temp_time1 >> RTC_OFFSET_HOUR) & 0xFF;
|
|
|
|
|
rtctime[1] = (temp_time1 >> RTC_OFFSET_MINUTE) & 0xFF;
|
|
|
|
|
rtctime[2] = temp_time1 & 0xFF;
|
|
|
|
|
|
|
|
|
|
/* 获取日期 */
|
|
|
|
|
rtcdate[0] = (temp_date1 >> RTC_OFFSET_YEAR) & 0xFF;
|
|
|
|
|
rtcdate[1] = (temp_date1 >> RTC_OFFSET_MONTH) & 0xFF;
|
|
|
|
|
rtcdate[2] = temp_date1 & 0xFF;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 时间读取不正确 */
|
|
|
|
|
else
|
|
|
|
|
{
|
|
|
|
|
while (1)
|
|
|
|
|
{
|
|
|
|
|
/* 时间读取不正确处理代码 */
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief 获取时间戳日期与时间
|
|
|
|
|
* @param timestamp_date 输出时间戳日期信息
|
|
|
|
|
* @param timestamp_time 输出时间戳时间信息
|
|
|
|
|
* @retval 无
|
|
|
|
|
*/
|
|
|
|
|
void BSP_Rtc_Get_Timestamp(uint8_t *timestamp_date, uint8_t *timestamp_time)
|
|
|
|
|
{
|
|
|
|
|
/* 等待时间戳标志TSF置1 */
|
|
|
|
|
while (!std_rtc_get_flag(RTC_FLAG_TIMESTAMP));
|
|
|
|
|
|
|
|
|
|
/* 读取时间戳时间 */
|
|
|
|
|
timestamp_time[0] = std_rtc_timestamp_get_hour();
|
|
|
|
|
timestamp_time[1] = std_rtc_timestamp_get_minute();
|
|
|
|
|
timestamp_time[2] = std_rtc_timestamp_get_second();
|
|
|
|
|
|
|
|
|
|
/* 读取时间戳日期 */
|
|
|
|
|
timestamp_date[0] = std_rtc_timestamp_get_day();
|
|
|
|
|
timestamp_date[1] = std_rtc_timestamp_get_month();
|
|
|
|
|
|
|
|
|
|
/* 清除时间戳标志 */
|
|
|
|
|
std_rtc_clear_flag(RTC_CLEAR_TIMESTAMP);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief 配置RTC时钟数字平滑校准参数
|
|
|
|
|
* @param calib_plus_pulses 插入时钟脉冲控制
|
|
|
|
|
* @arg RTC_SMOOTH_CALIB_PLUS_PULSES_RESET
|
|
|
|
|
* @arg RTC_SMOOTH_CALIB_PLUS_PULSES_SET
|
|
|
|
|
* @param calib_minus_pulses 屏蔽时钟脉冲个数
|
|
|
|
|
* @retval 无
|
|
|
|
|
*/
|
|
|
|
|
void BSP_Rtc_Calib_Cfg(uint32_t calib_plus_pulses, uint32_t calib_minus_pulses)
|
|
|
|
|
{
|
|
|
|
|
/* 开启校准周期中断 */
|
|
|
|
|
std_rtc_calib_interrupt_enable();
|
|
|
|
|
|
|
|
|
|
/* 配置数字平滑校准参数 */
|
|
|
|
|
while (std_rtc_cal_get_status());
|
|
|
|
|
std_rtc_cal_config(calib_plus_pulses, calib_minus_pulses);
|
|
|
|
|
|
|
|
|
|
/* 配置中断优先级 */
|
|
|
|
|
NVIC_SetPriority(RTC_TAMP_IRQn, NVIC_PRIO_0);
|
|
|
|
|
/* 使能中断 */
|
|
|
|
|
NVIC_EnableIRQ(RTC_TAMP_IRQn);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* @brief RTC时钟设置 RTC在VCORE_AON域,可使用VCORE_AON复位清除所有寄存器状态
|
|
|
|
|
* @retval 无
|
|
|
|
|
*/
|
|
|
|
|
void rtc_clock_config(void)
|
|
|
|
|
{
|
|
|
|
|
/* RTC APB时钟使能 */
|
|
|
|
|
std_rcc_apb1_clk_enable(RCC_PERIPH_CLK_RTC);
|
|
|
|
|
|
|
|
|
|
/* 使能PMU时钟,开启VCORE_AON写使能 */
|
|
|
|
|
std_rcc_apb1_clk_enable(RCC_PERIPH_CLK_PMU);
|
|
|
|
|
std_pmu_vaon_write_enable();
|
|
|
|
|
|
|
|
|
|
/* 使能LXTAL时钟 */
|
|
|
|
|
std_rcc_lxtal_drive_mode_config(RCC_LXTAL_DRIVE_MODE_ENHANCE);
|
|
|
|
|
std_rcc_lxtal_drive_config(RCC_LXTAL_DRIVE_LEVEL2);
|
|
|
|
|
std_rcc_lxtal_enable(RCC_LXTAL_ON);
|
|
|
|
|
while (!std_rcc_get_lxtal_ready());
|
|
|
|
|
|
|
|
|
|
/* 选择LXTAL作为RTC时钟源
|
|
|
|
|
|
|
|
|
|
注意: 选择RTC时钟源后,以下情况可重新配置RTC时钟源:
|
|
|
|
|
- VCORE_AON域复位
|
|
|
|
|
*/
|
|
|
|
|
std_rcc_set_rtcclk_source(RCC_RTC_ASYNC_CLK_SRC_LXTAL);
|
|
|
|
|
|
|
|
|
|
/* RTC外设时钟使能 */
|
|
|
|
|
std_rcc_rtc_enable();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int BSP_RTC_Init(void)
|
|
|
|
|
{
|
|
|
|
|
float calp_val = 0, calm_val = 0;
|
|
|
|
|
|
|
|
|
|
/* RTC时钟源选择LXTAL */
|
|
|
|
|
rtc_clock_config();
|
|
|
|
|
/* RTC在VCORE_AON域,可使用VCORE_AON复位清除所有寄存器状态 */
|
|
|
|
|
|
|
|
|
|
/* 关闭RTC寄存器写保护 */
|
|
|
|
|
std_rtc_write_protection_disable();
|
|
|
|
|
|
|
|
|
|
/* RTC_OUT输出预分频的时钟信号1Hz */
|
|
|
|
|
BSP_Rtc_Output_Cfg();
|
|
|
|
|
|
|
|
|
|
/* 等待3s */
|
|
|
|
|
rt_thread_mdelay(3000);
|
|
|
|
|
|
|
|
|
|
if (FRTC_PPM > 0)
|
|
|
|
|
{
|
|
|
|
|
calp_val = RTC_SMOOTH_CALIB_PLUS_PULSES_RESET;
|
|
|
|
|
calm_val = FRTC_PPM / 0.954 + 0.5;
|
|
|
|
|
}
|
|
|
|
|
else if (FRTC_PPM < 0)
|
|
|
|
|
{
|
|
|
|
|
calp_val = RTC_SMOOTH_CALIB_PLUS_PULSES_SET;
|
|
|
|
|
calm_val = (512 + (FRTC_PPM / 0.954) + 0.5);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 设置校准参数 */
|
|
|
|
|
BSP_Rtc_Calib_Cfg((uint32_t)calp_val, (uint32_t)calm_val);
|
|
|
|
|
|
|
|
|
|
/* 使能RTC寄存器写保护 */
|
|
|
|
|
std_rtc_write_protection_enable();
|
|
|
|
|
|
|
|
|
|
/* RTC日期时间配置 */
|
|
|
|
|
BSP_Rtc_DateTime_Cfg(0x24, 0x08, 0x23, 0x14, 0x03, 0x05, 0x05);
|
2024-09-02 16:09:03 +08:00
|
|
|
|
|
2024-08-23 14:07:32 +08:00
|
|
|
|
|
|
|
|
|
return RT_EOK;
|
|
|
|
|
}
|
|
|
|
|
INIT_PREV_EXPORT(BSP_RTC_Init);
|