uxpfnesyqrq64087487246.png
t' Z# Q: }8 `" V# s& v
7 \4 C* j3 ^0 y( S4 J* [, j一,背景知识1、RTC时钟源:有三种:IRC32K,内部低速时钟源,不精确,温漂大;LXTAL:外部低速时钟源,32.768KHz,精度高;HXTAL:外部高速时钟源。. |! J% M3 M$ C0 H1 f+ y% o; L
2、实时时钟 (RTC) 是一个独立的 BCD 定时器/计数器;32 位寄存器包含 BCD 格式的秒、分钟、小时(12 或 24 小时制)、星期几、日期、月份和年份。8 K: Z$ H( G# A% |7 T( w
3、BCD进制:BCD进制是便于人们快速进行二进制和十进制之间的转换产生的,是由4位bit表示十进制中的0~9。4位bit可以表示的范围是2^4=16,所以BCD进制也有几种分类:4 b- I: W9 t8 V
8421码:因为从左到右这4位bit,每位为1其他位为0时分别对应十进制数值8/4/2/1,以此得名。
0 J1 _ a& w+ P: V
p20ov51ls5l64087487346.png
6 b; c6 v% D% J9 I
余3码:在8421码的基础上偏移34 y- ]5 `- z, r) d) I3 c
q3zhfbpoyyl64087487446.png
9 \' n+ }8 q5 d m4 p. z! v; L
2421码:+ Z! f9 S9 [5 \5 a4 f" I" ]. K
3 |. |: L4 a0 a, `3 W+ n0 W/ L
二、RTC初始化初始化部分按照GD的RTC例程,去掉提示信息printf这些不需要的东西。初始化先随意设置一个时间,第二章节会讲解如何按照用户需求设定时间。
4 h) |( m3 }8 q( J' s& g$ \8 n9 K1、宏定义和全局变量:选定RTC的时钟源--LXTAL,定义RTC的句柄全局变量。
/ K6 F7 r- D1 s6 `3 j+ q#define RTC_CLOCK_SOURCE_LXTAL //使用外部32.768K晶振#define BKP_VALUE 0x32F1 rtc_parameter_struct rtc_initpara; //RTC句柄2、RTC的初始化: 使能寄存器写入,选择时钟源,设置分频值产生1Hz时钟频率:时钟源频率/( prescaler_a * prescaler_s)=32768/(0x7f * 0xff)=1,使能外设时钟。
% v& w1 X0 P2 N8 i* ~% cvoid RTC_Init(void){ /* enable PMU clock */ rcu_periph_clock_enable(RCU_PMU); /* enable the access of the RTC registers */ pmu_backup_write_enable(); rtc_pre_config(); /* get RTC clock entry selection */ RTCSRC_FLAG = GET_BITS(RCU_BDCTL, 8, 9); /* check if RTC has aready been configured */ if ((BKP_VALUE != RTC_BKP0) || (0x00 == RTCSRC_FLAG)) { /* backup data register value is not correct or not yet programmed or RTC clock source is not configured (when the first time the program is executed or data in RCU_BDCTL is lost due to Vbat feeding) */ rtc_setup(); } rcu_all_reset_flag_clear();} /*! \brief RTC configuration function \param[in] none \param[out] none \retval none*/void rtc_pre_config(void){ #if defined (RTC_CLOCK_SOURCE_IRC32K) rcu_osci_on(RCU_IRC32K); rcu_osci_stab_wait(RCU_IRC32K); rcu_rtc_clock_config(RCU_RTCSRC_IRC32K); prescaler_s = 0x13F; prescaler_a = 0x63; #elif defined (RTC_CLOCK_SOURCE_LXTAL) rcu_osci_on(RCU_LXTAL); rcu_osci_stab_wait(RCU_LXTAL); rcu_rtc_clock_config(RCU_RTCSRC_LXTAL); prescaler_s = 0xFF; prescaler_a = 0x7F; #else #error RTC clock source should be defined. #endif /* RTC_CLOCK_SOURCE_IRC32K */ rcu_periph_clock_enable(RCU_RTC); rtc_register_sync_wait();} /*! \brief use hyperterminal to setup RTC time and alarm \param[in] none \param[out] none \retval none*/void rtc_setup(void){ /* setup RTC time value */ uint32_t tmp_hh = 0x00, tmp_mm = 0x00, tmp_ss = 0x00; rtc_initpara.factor_asyn = prescaler_a; rtc_initpara.factor_syn = prescaler_s; rtc_initpara.year = 0x16; rtc_initpara.day_of_week = 0; rtc_initpara.month = RTC_APR; rtc_initpara.date = 0x30; rtc_initpara.display_format = RTC_24HOUR; rtc_initpara.am_pm = RTC_AM; rtc_initpara.hour = tmp_hh; rtc_initpara.minute = tmp_mm; rtc_initpara.second = tmp_ss; /* RTC current time configuration */ if(ERROR != rtc_init(&rtc_initpara)) { RTC_BKP0 = BKP_VALUE; }}
; x8 ~6 V% {% J5 v5 Q; k三、设置时间和获取时间1、BCD和二进制转换函数:/** * @brief Convert a 2 digit decimal to BCD format. * @param Value: Byte to be converted * @retval Converted byte */uint8_t byte_to_bcd(uint8_t Value){ uint32_t bcdhigh = 0; while(Value >= 10) { bcdhigh++; Value -= 10; } return ((uint8_t)(bcdhigh 4) | Value);} /** * @brief Convert from 2 digit BCD to Binary. * @param Value: BCD value to be converted * @retval Converted word */uint8_t bcd_to_byte(uint8_t Value){ uint32_t tmp = 0; tmp = ((uint8_t)(Value & (uint8_t)0xF0) >> (uint8_t)0x4) * 10; return (tmp + (Value & (uint8_t)0x0F));} 2、设置指定时间:注意一定要将年月日时分秒等参数从二进制转换成BCD,再赋值给rtc_initpara1 M h' V- q! x0 ?+ z& _$ }
typedef struct{uint8_t year;uint8_t month;uint8_t date;uint8_t hour;uint8_t minute;uint8_t second;}S_RTCTimeInfo;//均为二进制格式 S_RTCTimeInfo RTCTime;//RTC全局变量,存储外界输入的待设定的时间 /*需要设定时间时调用此函数,将时间赋值给RTC句柄*/void RtcSetTime(S_RTCTimeInfo time){ rtc_initpara.year = byte_to_bcd(time.year); rtc_initpara.month= byte_to_bcd(time.month); rtc_initpara.date= byte_to_bcd(time.date); rtc_initpara.hour= byte_to_bcd(time.hour); rtc_initpara.minute= byte_to_bcd(time.minute); rtc_initpara.second= byte_to_bcd(time.second); rtc_init(&rtc_initpara);}3、获取当前时间:void RtcGetTime(void){ rtc_current_time_get(&rtc_initpara); RTCTime.year = bcd_to_byte(rtc_initpara.year); RTCTime.month= bcd_to_byte(rtc_initpara.year); RTCTime.date= bcd_to_byte(rtc_initpara.year); RTCTime.hour= bcd_to_byte(rtc_initpara.year); RTCTime.minute= bcd_to_byte(rtc_initpara.year); RTCTime.second= bcd_to_byte(rtc_initpara.year);}# v- M( N+ ?# j% ?: Q
四、遇到的问题1、如果不使用周几,可以将rtc_initpara.day_of_week设为0,这样就不启用这项了。如果初始化时设置了day_of_week,后续修改设定时间时没有将这项对应修改,会造成设置的时间不准。因为设定时间赋值后会进行rtc_init,day_of_week会影响reg_date。
3 b' P1 Q+ y* B4 N D& ]3 `/*gd32f4xx_rtc.c文件中*/ErrStatus rtc_init(rtc_parameter_struct *rtc_initpara_struct){ ErrStatus error_status = ERROR; uint32_t reg_time = 0U, reg_date = 0U; reg_date = (DATE_YR(rtc_initpara_struct->year) | \ DATE_DOW(rtc_initpara_struct->day_of_week) | \ DATE_MON(rtc_initpara_struct->month) | \ DATE_DAY(rtc_initpara_struct->date));...省略部分代码}2、当没有使用宏定义,而是使用数字给rtc_initpara 的年月日时分秒赋值时,一定要进行二进制到BCD的转换。对于此问题,STM32H7的HAL库就封装的很人性化,HAL库函数提供了可以选择使用哪种进制,,用户只需要选择对应的进制,传入参数即可,不需要自己进行进制转换。- J& K' k' \0 |4 n, L
/*stm32h7xx_hal_rtc.c文件*/ /** * @brief Set RTC current date. * @param hrtc: RTC handle * @param sDate: Pointer to date structure * @param Format: specifies the format of the entered parameters. * This parameter can be one of the following values: * @arg RTC_FORMAT_BIN: Binary data format * @arg RTC_FORMAT_BCD: BCD data format * @retval HAL status */HAL_StatusTypeDef HAL_RTC_SetDate(RTC_HandleTypeDef *hrtc, RTC_DateTypeDef *sDate, uint32_t Format);==========, H2 ?% U f% c# i7 |
往期回顾:嵌入式软件工程师常用的
2 t8 R2 z/ {& D- _4 ?/ q# j* r% m单片机的RTC获取网络时间; L; `, s2 `6 O* v% s
我都不知道的PWM的很偏的问题
$ B" F, ^0 F; Y8 ^一个小细节,精度提供一大截5 y) y$ ^3 a$ E$ X! N
蓝桥杯物联网教程汇总
}/ b, ?' D! k3 {: p==========原文:点击阅读原文
Z- d9 N* D, D0 z. d作者:半路程序媛
# F& Y( z3 @. q U) Q; O! s平台:CSDN
2 ?3 W5 ?$ V" E5 f2 l) n# m8 X! z) f; w& r) ^
tvdf1pzefek64087487546.png
9 S2 T2 X) a4 @: ?' Y
3 _. h1 Y2 [; o N5 ~/ p
l5yby5vvsir64087487646.png
, V) `9 q: V8 f8 ~% t
5 L& r( g' W$ O6 [, ~! Z
wxhcafcxxgr64087487747.png
|