STM32Cube STM32L053配置RTC时钟详解

Posted シ゛甜虾

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STM32Cube STM32L053配置RTC时钟详解相关的知识,希望对你有一定的参考价值。

先看下STM32L053的RTC时钟,这里没有外部晶振用的是内部LSE,频率37KHz

 通过Cube配置RTC,启用日历和时钟,我这里开启了一个RTC中断,用来唤醒休眠中的单片机

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进制,开始我也是这样认为的,然后并不是

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

/** @defgroup RTC_LL_EC_WEEKDAY  WEEK DAY
  * @
  */
#define LL_RTC_WEEKDAY_MONDAY              ((uint8_t)0x01U) /*!< Monday    */
#define LL_RTC_WEEKDAY_TUESDAY             ((uint8_t)0x02U) /*!< Tuesday   */
#define LL_RTC_WEEKDAY_WEDNESDAY           ((uint8_t)0x03U) /*!< Wednesday */
#define LL_RTC_WEEKDAY_THURSDAY            ((uint8_t)0x04U) /*!< Thrusday  */
#define LL_RTC_WEEKDAY_FRIDAY              ((uint8_t)0x05U) /*!< Friday    */
#define LL_RTC_WEEKDAY_SATURDAY            ((uint8_t)0x06U) /*!< Saturday  */
#define LL_RTC_WEEKDAY_SUNDAY              ((uint8_t)0x07U) /*!< Sunday    */
/**
  * @
  */

/** @defgroup RTC_LL_EC_MONTH  MONTH
  * @
  */
#define LL_RTC_MONTH_JANUARY               ((uint8_t)0x01U)  /*!< January   */
#define LL_RTC_MONTH_FEBRUARY              ((uint8_t)0x02U)  /*!< February  */
#define LL_RTC_MONTH_MARCH                 ((uint8_t)0x03U)  /*!< March     */
#define LL_RTC_MONTH_APRIL                 ((uint8_t)0x04U)  /*!< April     */
#define LL_RTC_MONTH_MAY                   ((uint8_t)0x05U)  /*!< May       */
#define LL_RTC_MONTH_JUNE                  ((uint8_t)0x06U)  /*!< June      */
#define LL_RTC_MONTH_JULY                  ((uint8_t)0x07U)  /*!< July      */
#define LL_RTC_MONTH_AUGUST                ((uint8_t)0x08U)  /*!< August    */
#define LL_RTC_MONTH_SEPTEMBER             ((uint8_t)0x09U)  /*!< September */
#define LL_RTC_MONTH_OCTOBER               ((uint8_t)0x10U)  /*!< October   */
#define LL_RTC_MONTH_NOVEMBER              ((uint8_t)0x11U)  /*!< November  */
#define LL_RTC_MONTH_DECEMBER              ((uint8_t)0x12U)  /*!< December  */

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

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

/**
  * @brief  Helper macro to convert a value from 2 digit decimal format to BCD format
  * @param  __VALUE__ Byte to be converted
  * @retval Converted byte
  */
#define __LL_RTC_CONVERT_BIN2BCD(__VALUE__) (uint8_t)((((__VALUE__) / 10U) << 4U) | ((__VALUE__) % 10U))

/**
  * @brief  Helper macro to convert a value from BCD format to 2 digit decimal format
  * @param  __VALUE__ BCD value to be converted
  * @retval Converted byte
  */
#define __LL_RTC_CONVERT_BCD2BIN(__VALUE__) (uint8_t)((((uint8_t)((__VALUE__) & (uint8_t)0xF0U) >> (uint8_t)0x4U) * 10U ) + ((__VALUE__) & (uint8_t)0x0FU))

配置完成,生成工程

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

#define RTC_BKP_DATE_TIME_UPDTATED ((uint32_t)0x32F2)
unsigned char const table_week[12]=0,3,3,6,1,4,6,2,5,0,3,5; //月修正数据表   
unsigned char rtc_get_week(unsigned short int year,unsigned char month, unsigned char day)

	unsigned short int temp2;
	unsigned char yearH, yearL;

	yearH = year/100; yearL = year%100;
	
	// 如果为21世纪,年份数加100
	if (yearH>19) yearL+=100;
	
	// 所过闰年数只算1900年之后的
	temp2 = yearL + yearL/4;
	temp2 = temp2 % 7;
	temp2 = temp2 + day + table_week[month-1];
	
	if (yearL%4 == 0&&month<3) temp2--;
	
	return(temp2 % 7);


void rtc_set(LL_RTC_DateTypeDef *date,LL_RTC_TimeTypeDef *time)
	
	LL_RTC_TIME_Init(RTC, LL_RTC_FORMAT_BIN, time);
	LL_RTC_DATE_Init(RTC, LL_RTC_FORMAT_BIN, date);	
	LL_RTC_BAK_SetRegister(RTC, LL_RTC_BKP_DR0, RTC_BKP_DATE_TIME_UPDTATED);


void rtc_get(LL_RTC_DateTypeDef *date,LL_RTC_TimeTypeDef *time)

	time->Hours   = __LL_RTC_CONVERT_BCD2BIN(LL_RTC_TIME_GetHour(RTC));
	time->Minutes = __LL_RTC_CONVERT_BCD2BIN(LL_RTC_TIME_GetMinute(RTC));
	time->Seconds = __LL_RTC_CONVERT_BCD2BIN(LL_RTC_TIME_GetSecond(RTC));
	date->Year  = __LL_RTC_CONVERT_BCD2BIN(LL_RTC_DATE_GetYear(RTC));
	date->Month = __LL_RTC_CONVERT_BCD2BIN(LL_RTC_DATE_GetMonth(RTC));
	date->Day   = __LL_RTC_CONVERT_BCD2BIN(LL_RTC_DATE_GetDay(RTC));

需要屏蔽2个函数

//LL_RCC_ForceBackupDomainReset();
//LL_RCC_ReleaseBackupDomainReset();

测试代码

void rtc_read(void)
	
	LL_RTC_DateTypeDef curData;
	LL_RTC_TimeTypeDef curTime;
		
	rtc_get(&curData, &curTime);
#ifdef ENABLE_PRINT
	printf("MX_RTC_Init:Date time: %d-%02d-%02d weekData:%d %02d:%02d:%02d\\r\\n"                   
                   , 1970 + curData.Year, curData.Month, curData.Day, curData.WeekDay
                   , curTime.Hours, curTime.Minutes, curTime.Seconds);
#endif
	curData.WeekDay = rtc_get_week((curData.Year+2000), curData.Month, curData.Day );
	
	curData.Year = 51;
	curData.Month = 7;
	curData.Day = 4;	
	curData.WeekDay = rtc_get_week((curData.Year+2000), curData.Month, curData.Day );
	
	curTime.Hours = 9;
	curTime.Minutes = 29;
	curTime.Seconds = 1;	
	
	rtc_set(&curData, &curTime);	
	#ifdef ENABLE_PRINT
	printf("MX_RTC_Init:Date time: %d-%02d-%02d weekData:%d %02d:%02d:%02d\\r\\n"                   
                   , 1970 + curData.Year, curData.Month, curData.Day, curData.WeekDay
                   , curTime.Hours, curTime.Minutes, curTime.Seconds);
#endif
	rtc_get(&curData, &curTime);	
	#ifdef ENABLE_PRINT
	printf("MX_RTC_Init:Date time: %d-%02d-%02d weekData:%d %02d:%02d:%02d\\r\\n"                   
                   , 1970 + curData.Year, curData.Month, curData.Day, curData.WeekDay
                   , curTime.Hours, curTime.Minutes, curTime.Seconds);
#endif
	rtc_get(&curData, &curTime);
	#ifdef ENABLE_PRINT
	printf("MX_RTC_Init:Date time: %d-%02d-%02d weekData:%d %02d:%02d:%02d\\r\\n"                   
                   , 1970 + curData.Year, curData.Month, curData.Day, curData.WeekDay
                   , curTime.Hours, curTime.Minutes, curTime.Seconds);
#endif

以上是关于STM32Cube STM32L053配置RTC时钟详解的主要内容,如果未能解决你的问题,请参考以下文章

STM32Cube STM32L053配置RTC WAKEUP中断唤醒

STM32Cube STM32L053闹钟唤醒LL库和HAL库

STM32Cube STM32L053配置GPIO达到最低功耗详解含测量实际电流值

STM32Cube STM32L053配置GPIO达到最低功耗详解含测量实际电流值

STM32L031F6 LL库硬件I2C使用,中断模式

STM32L031F6 LL库硬件I2C使用,中断模式