初窥门径32系列15--RTC,读写时间,设置闹钟

文章讲述了如何在STM32平台中使用CubeMX配置RTC(实时时钟)设置时间和闹钟,以及在代码中实现这些功能的过程。遇到的问题是,如果在主循环中获取日期后再获取时间,可能会导致时间显示异常,需确保获取时间的操作在日期之前。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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_ALLRTC_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);         
  }
}

问题如图
在这里插入图片描述
想了好久都没有想明白怎么回事,希望有大佬看到了可以帮我解惑!感谢!

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值