本帖最后由 FuShenxiao 于 2024-10-24 16:58 编辑
STM32的RTC指的是实时时钟(Real-Time Clock),它是一种用于计时和日期记录的硬件模块。在STM32微控制器中,RTC模块是由一个32位的计数器和一组用于保存日期和时间的寄存器组成的。由于RTC具有较高的精度和稳定性,从而能保持准确的日期和时间信息,因此它常用于需要精确定时和实时数据处理的应用场景。
本来以为RTC实现挺简单的,没想到这里还有那么多坑,主要是CubeMX代码生成存在一些问题。
在CubeMX中配置
选择STM32H7S78-DK模板
配置RTC
为了能输出时间和日期,还需要配置UART4
代码编写
生成RTC初始化代码如下
void MX_RTC_Init(void)
{
/* USER CODE BEGIN RTC_Init 0 */
/* USER CODE END RTC_Init 0 */
RTC_PrivilegeStateTypeDef privilegeState = {0};
RTC_TimeTypeDef sTime = {0};
RTC_DateTypeDef sDate = {0};
/* USER CODE BEGIN RTC_Init 1 */
/* USER CODE END RTC_Init 1 */
/** Initialize RTC Only
*/
hrtc.Instance = RTC;
hrtc.Init.HourFormat = RTC_HOURFORMAT_24;
hrtc.Init.AsynchPrediv = 127;
hrtc.Init.SynchPrediv = 255;
hrtc.Init.OutPut = RTC_OUTPUT_DISABLE;
hrtc.Init.OutPutRemap = RTC_OUTPUT_REMAP_NONE;
hrtc.Init.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;
hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;
hrtc.Init.OutPutPullUp = RTC_OUTPUT_PULLUP_NONE;
hrtc.Init.BinMode = RTC_BINARY_NONE;
if (HAL_RTC_Init(&hrtc) != HAL_OK)
{
Error_Handler();
}
privilegeState.rtcPrivilegeFull = RTC_PRIVILEGE_FULL_NO;
privilegeState.backupRegisterPrivZone = RTC_PRIVILEGE_BKUP_ZONE_NONE;
privilegeState.backupRegisterStartZone2 = RTC_BKP_DR0;
privilegeState.backupRegisterStartZone3 = RTC_BKP_DR0;
if (HAL_RTCEx_PrivilegeModeSet(&hrtc, &privilegeState) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN Check_RTC_BKUP */
/* USER CODE END Check_RTC_BKUP */
/** Initialize RTC and set the Time and Date
*/
sTime.Hours = 0x15;
sTime.Minutes = 0x0;
sTime.Seconds = 0x0;
sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;
sTime.StoreOperation = RTC_STOREOPERATION_RESET;
if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
sDate.WeekDay = RTC_WEEKDAY_THURSDAY;
sDate.Month = RTC_MONTH_OCTOBER;
sDate.Date = 0x24;
sDate.Year = 0x24;
if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BCD) != HAL_OK)
{
Error_Handler();
}
/* USER CODE BEGIN RTC_Init 2 */
/* USER CODE END RTC_Init 2 */
}
编写printf重定向
int fputc(int ch,FILE *p)
{
char c=ch;
HAL_UART_Transmit(&huart4,(unsigned char *)&c,1,50);
return ch;
}
void UART4_SendByte(char c)
{
HAL_UART_Transmit(&huart4,(unsigned char *)&c,1,50);
}
void UART4_SendData(char *p,int len)
{
HAL_UART_Transmit(&huart4,(unsigned char *)p,len,50);
}
编写输出RTC日历的代码
static void RTC_CalendarShow(uint8_t *showtime, uint8_t *showdate)
{
RTC_DateTypeDef sdatestructureget;
RTC_TimeTypeDef stimestructureget;
/* Get the RTC current Time */
HAL_RTC_GetTime(&hrtc, &stimestructureget, RTC_FORMAT_BIN);
/* Get the RTC current Date */
HAL_RTC_GetDate(&hrtc, &sdatestructureget, RTC_FORMAT_BIN);
/* Display time Format : hh:mm:ss */
sprintf((char *)showtime, "%2d:%2d:%2d", stimestructureget.Hours, stimestructureget.Minutes, stimestructureget.Seconds);
/* Display date Format : mm-dd-yyyy */
sprintf((char *)showdate, "%2d-%2d-%2d", sdatestructureget.Month, sdatestructureget.Date, 2000 + sdatestructureget.Year);
printf("%s\r\n", showtime);
printf("%s\r\n", showdate);
}
初始化时间/日期字符串
uint8_t aShowTime[16] = "hh:ms:ss";
uint8_t aShowDate[16] = "mm-dd-yyyy";
在主函数循环中加入如下代码
RTC_CalendarShow(aShowTime, aShowDate);
HAL_Delay(1000);
但是,这样还是有问题的。
问题出在 HAL_StatusTypeDef RTC_EnterInitMode(RTC_HandleTypeDef *hrtc)
其代码如下
HAL_StatusTypeDef RTC_EnterInitMode(RTC_HandleTypeDef *hrtc)
{
uint32_t tickstart;
HAL_StatusTypeDef status = HAL_OK;
/* Check if the Initialization mode is set */
if (READ_BIT(RTC->ICSR, RTC_ICSR_INITF) == 0U)
{
/* Set the Initialization mode */
SET_BIT(RTC->ICSR, RTC_ICSR_INIT);
tickstart = HAL_GetTick();
/* Wait till RTC is in INIT state and if Time out is reached exit */
while ((READ_BIT(RTC->ICSR, RTC_ICSR_INITF) == 0U) && (status != HAL_TIMEOUT))
{
if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
{
/* New check to avoid false timeout detection in case of preemption */
if (READ_BIT(RTC->ICSR, RTC_ICSR_INITF) == 0U)
{
status = HAL_TIMEOUT;
/* Change RTC state */
hrtc->State = HAL_RTC_STATE_TIMEOUT;
}
else
{
break;
}
}
}
}
return status;
}
问题出现在执行 SET_BIT(RTC->ICSR, RTC_ICSR_INIT); 之后,寄存器的初始化位并没有置1。
阅读手册可知需要对DBP置1才能使能写RTC寄存器。