esp32 rtc 时钟设置不对_Stm32CubeMX配置RTC时钟

本文介绍了如何使用STM32CubeMX配置STM32F412RETx芯片的RTC时钟,重点是启用RTC并连接外部32.768KHz晶振。内容包括RTC时钟源计算、RTC_FORMAT_BIN与RTC_FORMAT_BCD的理解,以及RTC初始化后在电源断开后的状态。文中还提到了STM32F103芯片在RTC配置上的不同行为。
摘要由CSDN通过智能技术生成

环境:

Stm32CubeMX V5.6.0

stm32F412RETx芯片,芯片的VBAT引脚接电池

RTC使用的外部晶振,内部的振荡器配置后断电后不跑,原因未知,下面直接上使用外部晶振的方案


配置RTC使用外部晶振,外部晶振是32.768KHz的

87d4f31c1d93551b9fea88b585220ce3.png

7473607ccbcf6fffe88c43e17a021b5f.png

配置RTC,启用日历和时钟

54bf674412c11498b6ceb805465f7d8d.png

stm32CubeMX默认填入的分频是使用32.768KHz的,但是内部振荡器是32KHz的,所以估计都是推荐使用外部晶振,使用内部振荡器的自己按公式重新计算分频值

公式如下:

RTC时钟频率 = RTC时钟源 / ((Asynchronous Predivider value + 1) * (Synchronous Predivider value + 1))

套用一下公式

32.768KHz / ((127+1)*(255+1)) = 1Hz,也就是1秒

年是从1970年算起的,其他月日时分秒以及24或者12小时制没什么好说的

数据格式Data Format,我使用Binary data format

stm32定义了RTC_FORMAT_BIN和RTC_FORMAT_BCD两种格式

RTC_FORMAT_BIN:为10进制,RTC_FORMAT_BCD为16进制,开始我也是这样认为的,然后并不是

看一下stm32f4xx_hal_rtc.h头文件中对月份的定义:

/** @defgroup RTC_Month_Date_Definitions RTC Month Date Definitions  * @{  *//* Coded in BCD format */#define RTC_MONTH_JANUARY              ((uint8_t)0x01)#define RTC_MONTH_FEBRUARY             ((uint8_t)0x02)#define RTC_MONTH_MARCH                ((uint8_t)0x03)#define RTC_MONTH_APRIL                ((uint8_t)0x04)#define RTC_MONTH_MAY                  ((uint8_t)0x05)#define RTC_MONTH_JUNE                 ((uint8_t)0x06)#define RTC_MONTH_JULY                 ((uint8_t)0x07)#define RTC_MONTH_AUGUST               ((uint8_t)0x08)#define RTC_MONTH_SEPTEMBER            ((uint8_t)0x09)#define RTC_MONTH_OCTOBER              ((uint8_t)0x10)#define RTC_MONTH_NOVEMBER             ((uint8_t)0x11)#define RTC_MONTH_DECEMBER             ((uint8_t)0x12)/** @defgroup RTC_WeekDay_Definitions RTC WeekDay Definitions  * @{  */#define RTC_WEEKDAY_MONDAY             ((uint8_t)0x01)#define RTC_WEEKDAY_TUESDAY            ((uint8_t)0x02)#define RTC_WEEKDAY_WEDNESDAY          ((uint8_t)0x03)#define RTC_WEEKDAY_THURSDAY           ((uint8_t)0x04)#define RTC_WEEKDAY_FRIDAY             ((uint8_t)0x05)#define RTC_WEEKDAY_SATURDAY           ((uint8_t)0x06)#define RTC_WEEKDAY_SUNDAY             ((uint8_t)0x07)

比如12月份RTC_MONTH_DECEMBER的值是等于0x12的,转成10进制等于18,也就是RTC_FORMAT_BCD也不是16进制,只是用了16进制的样式,0x12不看0x直接看数字部分,就是12月份

再来看看stm32内部的两种格式的转换函数

/**  * @brief  Converts a 2 digit decimal to BCD format.  * @param  Value Byte to be converted  * @retval Converted byte  */uint8_t RTC_ByteToBcd2(uint8_t Value){  uint32_t bcdhigh = 0U;  while(Value >= 10U)  {    bcdhigh++;    Value -= 10U;  }  return  ((uint8_t)(bcdhigh << 4U) | Value);}/**  * @brief  Converts from 2 digit BCD to Binary.  * @param  Value BCD value to be converted  * @retval Converted word  */uint8_t RTC_Bcd2ToByte(uint8_t Value){  uint32_t tmp = 0U;  tmp = ((uint8_t)(Value & (uint8_t)0xF0) >> (uint8_t)0x4) * 10;  return (tmp + (Value & (uint8_t)0x0F));}

转换函数代码自己看不说明,总之觉得很奇怪的用法

配置完成,生成工程

找到static void MX_RTC_Init(void)函数,在 HAL_RTC_Init后,使用RTC的后备寄存器保存是否初始化过时间的标志,RTC的后备寄存器也是后备电源供电的,所以主电源断电后数据还在,也可以用这些寄存器保存数据,读写函数如下:

void HAL_RTCEx_BKUPWrite(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister, uint32_t Data);uint32_t HAL_RTCEx_BKUPRead(RTC_HandleTypeDef *hrtc, uint32_t BackupRegister);

MX_RTC_Init函数修改如下:

static void MX_RTC_Init(void){    /* USER CODE BEGIN RTC_Init 0 */    /* USER CODE END RTC_Init 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.OutPutPolarity = RTC_OUTPUT_POLARITY_HIGH;    hrtc.Init.OutPutType = RTC_OUTPUT_TYPE_OPENDRAIN;    if (HAL_RTC_Init(&hrtc) != HAL_OK)    {        Error_Handler();    }    /* USER CODE BEGIN Check_RTC_BKUP */    // 检查后备寄存器    uint32_t iSetFlag = 0x5053;// 这个0x5053值自己随意    if(iSetFlag != HAL_RTCEx_BKUPRead(&hrtc, RTC_BKP_DR0))    {   //        /* USER CODE END Check_RTC_BKUP */        /** Initialize RTC and set the Time and Date        */        sTime.Hours = 9;        sTime.Minutes = 45;        sTime.Seconds = 0;        sTime.DayLightSaving = RTC_DAYLIGHTSAVING_NONE;        sTime.StoreOperation = RTC_STOREOPERATION_RESET;        if (HAL_RTC_SetTime(&hrtc, &sTime, RTC_FORMAT_BIN) != HAL_OK)        {            Error_Handler();        }        sDate.WeekDay = RTC_WEEKDAY_WEDNESDAY;        sDate.Month = RTC_MONTH_MAY;        sDate.Date = 13;        sDate.Year = 50;        if (HAL_RTC_SetDate(&hrtc, &sDate, RTC_FORMAT_BIN) != HAL_OK)        {            Error_Handler();        }        /* USER CODE BEGIN RTC_Init 2 */        // 设置完时钟,设置标志        HAL_RTCEx_BKUPWrite(&hrtc, RTC_BKP_DR0, iSetFlag);    }    else    {            }    {        // 获取一次时间显示        RTC_TimeTypeDef sTime;        HAL_StatusTypeDef status = HAL_RTC_GetTime(&hrtc, &sTime, RTC_FORMAT_BIN);        RTC_DateTypeDef sDate;        status = HAL_RTC_GetDate(&hrtc, &sDate, RTC_FORMAT_BIN);        printf("MX_RTC_Init:Date time: %d-%02d-%02d weekData:%d %02d:%02d:%02d"                                      , 1970 + sDate.Year, sDate.Month, sDate.Date, sDate.WeekDay                   , sTime.Hours, sTime.Minutes, sTime.Seconds);    }    /* USER CODE END RTC_Init 2 */}

获取时间日期HAL_RTC_GetTime和HAL_RTC_GetDate有要求先后顺序的,看函数定义处的说明:

You must call HAL_RTC_GetDate() after HAL_RTC_GetTime() to unlock the values in the higher-order calendar shadow registers to ensure consistency between the time and date values. Reading RTC current time locks the values in calendar shadow registers until Current date is read.

上google翻译的结果:

必须在HAL_RTC_GetTime()之后调用HAL_RTC_GetDate()才能解锁高阶日历影子寄存器中的值,以确保时间和日期值之间的一致性。 读取RTC当前时间将锁定日历影子寄存器中的值,直到读取当前日期为止。

基本配置完成,断主电源后,在次上电,查看输出的时间是正常的

我用F103芯片配置过,发现F103的芯片日期断电后就没有了

参考:

https://blog.csdn.net/qq_24381977/article/details/94460855

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值