CubeMX配置
低速时钟(LSE)选择外部晶振
时钟配置里面选中LSE
在RTC中勾选使用时钟源,使用万年历,闹钟A选择外部闹钟
串口外设和其他自行配置
代码编写
RTC_TimeTypeDef GET_Time;
RTC_DateTypeDef GET_Date;
int main(void)
{
HAL_Init();
SystemClock_Config();
MX_GPIO_Init();
MX_RTC_Init();
MX_USART1_UART_Init();
PrintfDebug("RTC Test\r\n");
RTC_SetDate(23, 11, 28, RTC_WEEKDAY_TUESDAY); //设置时间
RTC_SetTime(15, 13, 55);
RTC_Set_AlarmA(RTC_WEEKDAY_TUESDAY, 15, 14, 0); //设置闹钟
while (1)
{
HAL_RTC_GetDate(&hrtc,&GET_Date,RTC_FORMAT_BIN); //获取日期
PrintfDebug("%02d/%02d/%02d/%d\r\n",2000+GET_Date.Year,GET_Date.Month,GET_Date.Date, GET_Date.WeekDay); //打印日期
HAL_RTC_GetTime(&hrtc,&GET_Time,RTC_FORMAT_BIN); //获取时间
PrintfDebug("%02d:%02d:%02d\r\n",GET_Time.Hours,GET_Time.Minutes,GET_Time.Seconds); //打印时间
PrintfDebug("\r\n"); //换行
HAL_Delay(1000); //1s执行一次以上内容
}
}
设置时间
void RTC_SetDate(uint8_t year, uint8_t month, uint8_t day, uint8_t week)
{
RTC_DateTypeDef sData = {0};
sData.Year = year;
sData.Month = month;
sData.Date = day;
sData.WeekDay = week;
HAL_RTC_SetDate(&hrtc, &sData, RTC_FORMAT_BIN);
}
void RTC_SetTime(uint8_t hour, uint8_t min, uint8_t sec)
{
RTC_TimeTypeDef sTime = {0};
sTime.Hours= hour;
sTime.Minutes = min;
sTime.Seconds = sec;
HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN);
}
设置闹钟
void RTC_Set_AlarmA(uint8_t week,uint8_t hour,uint8_t min,uint8_t sec)
{
RTC_AlarmTypeDef sAlarm = {0};
sAlarm.AlarmTime.Hours=hour; //小时
sAlarm.AlarmTime.Minutes=min; //分钟
sAlarm.AlarmTime.Seconds=sec; //秒
sAlarm.AlarmTime.SubSeconds=0;
sAlarm.AlarmTime.TimeFormat=RTC_HOURFORMAT12_AM;
sAlarm.AlarmMask=RTC_AlarmMask_DateWeekDay;//精确匹配星期,时分秒
sAlarm.AlarmSubSecondMask=RTC_ALARMSUBSECONDMASK_NONE;
sAlarm.AlarmDateWeekDaySel=RTC_ALARMDATEWEEKDAYSEL_WEEKDAY;//按星期
sAlarm.AlarmDateWeekDay=week; //星期
sAlarm.Alarm=RTC_ALARM_A; //闹钟A
HAL_RTC_SetAlarm_IT(&hrtc,&sAlarm,RTC_FORMAT_BIN);
}
扩展:
结构体:RTC_AlarmTypeDef
typedef struct
{
RTC_TimeTypeDef AlarmTime; //配置RTC闹钟时间结构体成员
uint32_t AlarmMask; //用于配置闹钟触发的条件
uint32_t AlarmSubSecondMask; //用于配置子秒级别的闹钟触发条件的掩码
uint32_t AlarmDateWeekDaySel; //用于选择闹钟触发条件中的日期或者星期
uint8_t AlarmDateWeekDay; //用于设置闹钟触发条件中的日期或者星期的具体数值
uint32_t Alarm; //选择闹钟
} RTC_AlarmTypeDef;
AlarmMask
:包括以下几种设置
RTC_AlarmMask_None: 无掩码,所有的时间单元(小时、分钟、秒)都必须匹配才能触发闹钟。
RTC_AlarmMask_DateWeekDay: 只有当日期、星期和时间都匹配时才触发闹钟。
RTC_AlarmMask_Hours: 只有当小时和时间匹配时才触发闹钟。
RTC_AlarmMask_Minutes: 只有当分钟和时间匹配时才触发闹钟。
RTC_AlarmMask_Seconds: 只有当秒和时间匹配时才触发闹钟。
AlarmSubSecondMask
: 若无精确要求可以设置为RTC_ALARMSUBSECONDMASK_ALL或RTC_ALARMSUBSECONDMASK_NONE
AlarmDateWeekDaySel
: 可以选择以下两种模式
RTC_AlarmDateWeekDaySel_Date: 选择日期模式,表示闹钟触发条件中使用日期字段。
RTC_AlarmDateWeekDaySel_WeekDay: 选择星期模式,表示闹钟触发条件中使用星期字段。
AlarmDateWeekDay
: 当AlarmDateWeekDaySel选择日期模式,可以设置1到31之间的任意值,表示具体的日期。
选择星期模式,可以设置1到7之间的任意值,表示星期几,其中1表示星期一,2表示星期二,依次类推。
因此要设置一个日子的闹钟需要配置如下
void RTC_Set_AlarmA(uint8_t day,uint8_t hour,uint8_t min,uint8_t sec)
{
RTC_AlarmTypeDef sAlarm = {0};
sAlarm.AlarmTime.Hours=hour; //小时
sAlarm.AlarmTime.Minutes=min; //分钟
sAlarm.AlarmTime.Seconds=sec; //秒
sAlarm.AlarmTime.SubSeconds=0;
sAlarm.AlarmTime.TimeFormat=RTC_HOURFORMAT12_AM;
sAlarm.AlarmMask=RTC_AlarmMask_DateWeekDay;//精确匹配日期,时分秒
sAlarm.AlarmSubSecondMask=RTC_ALARMSUBSECONDMASK_NONE;
sAlarm.AlarmDateWeekDaySel=RTC_ALARMDATEWEEKDAYSEL_DATE;//按日期
sAlarm.AlarmDateWeekDay=day; //日期
sAlarm.Alarm=RTC_ALARM_A; //闹钟A
HAL_RTC_SetAlarm_IT(&hrtc,&sAlarm,RTC_FORMAT_BIN);
}
问题
下面在main函数中循环的代码中,将注释2和3这两行代码交换一下顺序,先获取时间在把日期和时间全部打印出来,会导致串口打印的时候时间不正常,但使用下面代码的结构则可以正常读取时间日期
while (1)
{
HAL_RTC_GetDate(&hrtc,&GET_Date,RTC_FORMAT_BIN); //1
PrintfDebug("%02d/%02d/%02d/%d\r\n",2000+GET_Date.Year,GET_Date.Month,GET_Date.Date, GET_Date.WeekDay); //2
HAL_RTC_GetTime(&hrtc,&GET_Time,RTC_FORMAT_BIN); //3
PrintfDebug("%02d:%02d:%02d\r\n",GET_Time.Hours,GET_Time.Minutes,GET_Time.Seconds); //4
PrintfDebug("\r\n");
HAL_Delay(1000);
}
}
问题如图
想了好久都没有想明白怎么回事,希望有大佬看到了可以帮我解惑!感谢!