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达到最低功耗详解含测量实际电流值