207 lines
7.0 KiB
C
207 lines
7.0 KiB
C
#include "McuBspRtc.h"
|
||
|
||
static BspRtcAlarmCallback gMcuBspRtcExtiCallback = NULL;
|
||
|
||
static RTC_HandleTypeDef gRTCHandle;
|
||
|
||
static unsigned char gCentury = 0;
|
||
static unsigned char gRtcSyncFlag = 0; // RTC时钟同步标志位
|
||
|
||
/* 初始化RTC */
|
||
int McuBspRtcInit(void)
|
||
{
|
||
gRTCHandle.Instance = RTC;
|
||
gRTCHandle.Init.AsynchPrediv = RTC_AUTO_1_SECOND; // 设定基本时钟为1s,时钟精度为1s
|
||
gRTCHandle.Init.OutPut = RTC_OUTPUTSOURCE_NONE; // 允许PC13脚作为普通IO口使用
|
||
if (HAL_RTC_Init(&gRTCHandle) != HAL_OK) {
|
||
return -1;
|
||
}
|
||
return 0;
|
||
}
|
||
|
||
/* 设置当前时间 */
|
||
int McuBspRtcSetTime(MCU_BSP_CLOCK *time)
|
||
{
|
||
RTC_TimeTypeDef sTime = {0};
|
||
RTC_DateTypeDef sDate = {0};
|
||
if (time == NULL) {
|
||
return -1;
|
||
}
|
||
sTime.Hours = time->Hours;
|
||
sTime.Minutes = time->Minutes;
|
||
sTime.Seconds = time->Seconds;
|
||
sDate.Month = time->Month;
|
||
sDate.Date = time->Date;
|
||
sDate.Year = time->Year % 100;
|
||
gCentury = time->Year / 100;
|
||
if(HAL_RTC_SetDate(&gRTCHandle, &sDate, RTC_FORMAT_BIN) != HAL_OK) {
|
||
return -1;
|
||
}
|
||
if(HAL_RTC_SetTime(&gRTCHandle, &sTime, RTC_FORMAT_BIN) != HAL_OK) {
|
||
return -1;
|
||
}
|
||
gRtcSyncFlag = 1;
|
||
return 0;
|
||
}
|
||
|
||
/* 获取RTC同步标志位 */
|
||
int McuBspRtcGetSyncFlag(void)
|
||
{
|
||
return gRtcSyncFlag;
|
||
}
|
||
|
||
/* 读取当前时间 */
|
||
int McuBspRtcGetTime(MCU_BSP_CLOCK *time)
|
||
{
|
||
RTC_TimeTypeDef sTime = {0};
|
||
RTC_DateTypeDef sDate = {0};
|
||
if (time == NULL) {
|
||
return -1;
|
||
}
|
||
if (HAL_RTC_GetTime(&gRTCHandle, &sTime, RTC_FORMAT_BIN) != HAL_OK) {
|
||
return -1;
|
||
}
|
||
if (HAL_RTC_GetDate(&gRTCHandle, &sDate, RTC_FORMAT_BIN) != HAL_OK) {
|
||
return -1;
|
||
}
|
||
time->Hours = sTime.Hours;
|
||
time->Minutes = sTime.Minutes;
|
||
time->Seconds = sTime.Seconds;
|
||
time->Month = sDate.Month;
|
||
time->Date = sDate.Date;
|
||
time->Year = gCentury * 100 + sDate.Year;
|
||
return 0;
|
||
}
|
||
|
||
/* 启动RTC闹钟中断 */
|
||
int McuBspRtcStartAlarm(unsigned char RtcPeriod, BspRtcAlarmCallback Callback)
|
||
{
|
||
RTC_AlarmTypeDef sAlarm = {0};
|
||
/* 获取当前时间 */
|
||
RTC_TimeTypeDef sTime = {0};
|
||
if (HAL_RTC_GetTime(&gRTCHandle, &sTime, RTC_FORMAT_BIN) != HAL_OK) {
|
||
return -1;
|
||
}
|
||
sAlarm.Alarm = RTC_ALARM_A;
|
||
switch (RtcPeriod) {
|
||
case MCU_BSP_RTC_CLOCK_WAKEUP_PERIOD_30MIN:
|
||
if ((sTime.Minutes + 30) > 60) {
|
||
sAlarm.AlarmTime.Hours = sTime.Hours + 1;
|
||
} else {
|
||
sAlarm.AlarmTime.Hours = sTime.Hours;
|
||
}
|
||
if (((sTime.Minutes + 30) > 60) && ((sTime.Minutes + 30) < 90)) {
|
||
sAlarm.AlarmTime.Minutes = 0;
|
||
} else {
|
||
sAlarm.AlarmTime.Minutes = 30;
|
||
}
|
||
sAlarm.AlarmTime.Seconds = 0;
|
||
break;
|
||
case MCU_BSP_RTC_CLOCK_WAKEUP_PERIOD_1HOUR:
|
||
sAlarm.AlarmTime.Hours = (sTime.Hours + (MCU_BSP_RTC_CLOCK_WAKEUP_PERIOD_1HOUR -
|
||
(sTime.Hours % MCU_BSP_RTC_CLOCK_WAKEUP_PERIOD_1HOUR))) % 24;
|
||
sAlarm.AlarmTime.Minutes = 0;
|
||
sAlarm.AlarmTime.Seconds = 0;
|
||
break;
|
||
case MCU_BSP_RTC_CLOCK_WAKEUP_PERIOD_2HOUR:
|
||
sAlarm.AlarmTime.Hours = (sTime.Hours + (MCU_BSP_RTC_CLOCK_WAKEUP_PERIOD_2HOUR -
|
||
(sTime.Hours % MCU_BSP_RTC_CLOCK_WAKEUP_PERIOD_2HOUR))) % 24;
|
||
sAlarm.AlarmTime.Minutes = 0;
|
||
sAlarm.AlarmTime.Seconds = 0;
|
||
break;
|
||
case MCU_BSP_RTC_CLOCK_WAKEUP_PERIOD_3HOUR:
|
||
sAlarm.AlarmTime.Hours = (sTime.Hours + (MCU_BSP_RTC_CLOCK_WAKEUP_PERIOD_3HOUR -
|
||
(sTime.Hours % MCU_BSP_RTC_CLOCK_WAKEUP_PERIOD_3HOUR))) % 24;
|
||
sAlarm.AlarmTime.Minutes = 0;
|
||
sAlarm.AlarmTime.Seconds = 0;
|
||
break;
|
||
case MCU_BSP_RTC_CLOCK_WAKEUP_PERIOD_4HOUR:
|
||
sAlarm.AlarmTime.Hours = (sTime.Hours + (MCU_BSP_RTC_CLOCK_WAKEUP_PERIOD_4HOUR -
|
||
(sTime.Hours % MCU_BSP_RTC_CLOCK_WAKEUP_PERIOD_4HOUR))) % 24;
|
||
sAlarm.AlarmTime.Minutes = 0;
|
||
sAlarm.AlarmTime.Seconds = 0;
|
||
break;
|
||
case MCU_BSP_RTC_CLOCK_WAKEUP_PERIOD_6HOUR:
|
||
sAlarm.AlarmTime.Hours = (sTime.Hours + (MCU_BSP_RTC_CLOCK_WAKEUP_PERIOD_6HOUR -
|
||
(sTime.Hours % MCU_BSP_RTC_CLOCK_WAKEUP_PERIOD_6HOUR))) % 24;
|
||
sAlarm.AlarmTime.Minutes = 0;
|
||
sAlarm.AlarmTime.Seconds = 0;
|
||
break;
|
||
case MCU_BSP_RTC_CLOCK_WAKEUP_PERIOD_8HOUR:
|
||
sAlarm.AlarmTime.Hours = (sTime.Hours + (MCU_BSP_RTC_CLOCK_WAKEUP_PERIOD_8HOUR -
|
||
(sTime.Hours % MCU_BSP_RTC_CLOCK_WAKEUP_PERIOD_8HOUR))) % 24;
|
||
sAlarm.AlarmTime.Minutes = 0;
|
||
sAlarm.AlarmTime.Seconds = 0;
|
||
break;
|
||
case MCU_BSP_RTC_CLOCK_WAKEUP_PERIOD_12HOUR:
|
||
sAlarm.AlarmTime.Hours = (sTime.Hours + (MCU_BSP_RTC_CLOCK_WAKEUP_PERIOD_12HOUR -
|
||
(sTime.Hours % MCU_BSP_RTC_CLOCK_WAKEUP_PERIOD_12HOUR))) % 24;
|
||
sAlarm.AlarmTime.Minutes = 0;
|
||
sAlarm.AlarmTime.Seconds = 0;
|
||
break;
|
||
case MCU_BSP_RTC_CLOCK_WAKEUP_PERIOD_24HOUR:
|
||
sAlarm.AlarmTime.Hours = 0;
|
||
sAlarm.AlarmTime.Minutes = 0;
|
||
sAlarm.AlarmTime.Seconds = 0;
|
||
break;
|
||
default :
|
||
return -1;
|
||
}
|
||
HAL_NVIC_SetPriority(RTC_Alarm_IRQn, 0x0F, 0); // 优先级最低与系统滴答优先级一致
|
||
HAL_NVIC_EnableIRQ(RTC_Alarm_IRQn);
|
||
if (HAL_RTC_SetAlarm_IT(&gRTCHandle, &sAlarm, RTC_FORMAT_BIN) != HAL_OK) {
|
||
return -1;
|
||
}
|
||
gMcuBspRtcExtiCallback = Callback;
|
||
return 0;
|
||
}
|
||
|
||
void McuBspRtcEndAlarm(void)
|
||
{
|
||
HAL_NVIC_DisableIRQ(RTC_Alarm_IRQn);
|
||
}
|
||
|
||
/* RTC初始化的时候底层硬件使用 */
|
||
void HAL_RTC_MspInit(RTC_HandleTypeDef *hrtc)
|
||
{
|
||
RCC_OscInitTypeDef RCC_OscInitStruct;
|
||
RCC_PeriphCLKInitTypeDef PeriphClkInitStruct;
|
||
if (hrtc -> Instance == RTC) {
|
||
__HAL_RCC_PWR_CLK_ENABLE();
|
||
HAL_PWR_EnableBkUpAccess();
|
||
/* Configue LSE as RTC clock soucre */
|
||
RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_LSE;
|
||
RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE;
|
||
RCC_OscInitStruct.LSEState = RCC_LSE_ON;
|
||
PeriphClkInitStruct.RTCClockSelection = RCC_RTCCLKSOURCE_LSE;
|
||
if(HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) {
|
||
|
||
}
|
||
PeriphClkInitStruct.PeriphClockSelection = RCC_PERIPHCLK_RTC;
|
||
if(HAL_RCCEx_PeriphCLKConfig(&PeriphClkInitStruct) != HAL_OK) {
|
||
|
||
}
|
||
__HAL_RCC_RTC_ENABLE();
|
||
}
|
||
}
|
||
|
||
/* 反初始化底层硬件调用 */
|
||
void HAL_RTC_MspDeInit(RTC_HandleTypeDef *hrtc)
|
||
{
|
||
/*##-1- Reset peripherals ##################################################*/
|
||
__HAL_RCC_RTC_DISABLE();
|
||
}
|
||
|
||
void RTC_Alarm_IRQHandler(void)
|
||
{
|
||
HAL_RTC_AlarmIRQHandler(&gRTCHandle);
|
||
}
|
||
|
||
void HAL_RTC_AlarmAEventCallback(RTC_HandleTypeDef *hrtc)
|
||
{
|
||
if (gMcuBspRtcExtiCallback != NULL) {
|
||
gMcuBspRtcExtiCallback();
|
||
}
|
||
}
|
||
|