• PY32F003F18之RTC


    一、RTC振荡器

    PY32F003F18实时时钟的振荡器是内部RC振荡器,频率为32.768KHz。它也可以使用HSE时钟,不建议使用。HAL库提到LSE振荡器,但PY32F003F18实际上没有这个振荡器。

    缺点:CPU掉电后,需要重新配置RTC,这个确实不太友好,有点像是鸡肋,在要求不严格的场合,凑合使用吧。

    RTC时钟框图如下:

    二、RTC的HAL库有一个不是很严重的bug

     PY32F003F18的HAL库润年函数中有一个BUG,不是很严重,因为2400年是一个闰年,它把年定义为字节型变量,是没有办法分辨出是不是闰年。

    闰年的计算方法:年数能被4整除,但不能被100年整除,为闰年;若年数能400年整除,也为闰年

    HAL库确实不大好,它喜欢用全局变量来实现其功能,让人受不了。我改了,让它适合自己需要的。HAL处的好处,就是我们可以从中抠出自己需要的部分,修修改改,就可以了,比HAL库的灵活多了。时刻不忘黑它一把,因为人云亦云的人太多了。

    三、非完全HAL库测试程序

    如果你觉得HAL库,就用HAL中的程序,也是可以的。

    1. #include "RTC.h"
    2. #include "LED.h"
    3. #include "stdio.h" //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()
    4. uint8_t Century;//世纪,21世纪用20表示
    5. RTC_DateTypeDef RTC_DateStructureure;//用来保存读到的"年月日"
    6. RTC_TimeTypeDef RTC_TimeStructureure;//用来保存读到的"时分秒"
    7. RTC_AlarmTypeDef RTC_AlarmStructureure;
    8. void RTC_Init(void);
    9. void RTC_Display(void);
    10. //函数功能:读"RTC计数寄存器"
    11. uint32_t Read_RTC_Time_Counter(void)
    12. {
    13. uint16_t high1 = 0U, high2 = 0U, low = 0U;
    14. uint32_t timecounter = 0U;
    15. high1 = READ_REG(RTC->CNTH & RTC_CNTH_RTC_CNT);//"RTC计数寄存器高位RTC_CNTH"
    16. low = READ_REG(RTC->CNTL & RTC_CNTL_RTC_CNT);//"RTC计数寄存器低位RTC_CNTL"
    17. high2 = READ_REG(RTC->CNTH & RTC_CNTH_RTC_CNT);//"RTC计数寄存器高位RTC_CNTH"
    18. if (high1 != high2)
    19. {//"RTC计数寄存器低位RTC_CNTL"时,发现"RTC计数寄存器高位RTC_CNTH"中的数据发生改变了
    20. //In this case the counter roll over during reading of CNTL and CNTH registers,
    21. //read again CNTL register then return the counter value
    22. timecounter = (((uint32_t) high2 << 16U) | READ_REG(RTC->CNTL & RTC_CNTL_RTC_CNT));
    23. }
    24. else
    25. {
    26. //No counter roll over during reading of CNTL and CNTH registers,
    27. //counter value is equal to first value of CNTL and CNTH
    28. timecounter = (((uint32_t) high1 << 16U) | low);
    29. }
    30. return timecounter;
    31. }
    32. //函数功能:
    33. //等待RTC写操作结束
    34. //返回0,表示退出RTC配置模式,开始更新RTC寄存器
    35. HAL_StatusTypeDef Enter_RTC_Init_Mode(void)
    36. {
    37. uint32_t tickstart = 0U;
    38. tickstart = HAL_GetTick();
    39. /* Wait till RTC is in INIT state and if Time out is reached exit */
    40. while ( (RTC->CRL & RTC_CRL_RTOFF) == (uint32_t)RESET )
    41. {//"RTC控制寄存器RTC_CRL"中的RTOFF,若RTOFF=0,则上一次对RTC寄存器的写操作仍在进行
    42. if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
    43. {//RTC_TIMEOUT_VALUE=2000,最大等待时间为2000ms
    44. return HAL_TIMEOUT;
    45. }
    46. }
    47. _HAL_RTC_WRITEPROTECTION_DISABLE(RTC);
    48. //"RTC控制寄存器RTC_CRL"中的CNF=0,退出配置模式,开始更新RTC寄存器
    49. //Disable the write protection for RTC registers
    50. return HAL_OK;
    51. }
    52. //函数功能:
    53. //等待RTC写操作结束
    54. //返回0,表示RTC写操作结束
    55. HAL_StatusTypeDef Exit_RTC_Init_Mode(void)
    56. {
    57. uint32_t tickstart = 0U;
    58. _HAL_RTC_WRITEPROTECTION_ENABLE(RTC);
    59. //"RTC控制寄存器RTC_CRL"中的CNF=1,进入RTC配置模式
    60. tickstart = HAL_GetTick();
    61. while ((RTC->CRL & RTC_CRL_RTOFF) == RTC_CRL_RTOFF)
    62. {//"RTC控制寄存器RTC_CRL"中的RTOFF,若RTOFF=1,则上一次对RTC寄存器的写操作已经完成
    63. if ((HAL_GetTick() - tickstart) > RTC_RTOFF_RESET_TIMEOUT_VALUE)
    64. {//RTC_RTOFF_RESET_TIMEOUT_VALUE=4,最大等待时间为4ms
    65. break;
    66. }
    67. }
    68. tickstart = HAL_GetTick();
    69. while ((RTC->CRL & RTC_CRL_RTOFF) == (uint32_t)RESET)
    70. {//"RTC控制寄存器RTC_CRL"中的RTOFF,若RTOFF=0,则上一次对RTC寄存器的写操作仍在进行
    71. if ((HAL_GetTick() - tickstart) > RTC_TIMEOUT_VALUE)
    72. {//RTC_TIMEOUT_VALUE=2000,最大等待时间为2000ms
    73. return HAL_TIMEOUT;
    74. }
    75. }
    76. return HAL_OK;
    77. }
    78. //函数功能:将TimeCounter写入"RTC计数寄存器"
    79. HAL_StatusTypeDef Write_RTC_Time_Counter( uint32_t TimeCounter )
    80. {
    81. HAL_StatusTypeDef status = HAL_OK;
    82. if (Enter_RTC_Init_Mode() != HAL_OK)
    83. {//等待RTC写操作结束
    84. //返回0,表示退出RTC配置模式,开始更新RTC寄存器
    85. status = HAL_ERROR;
    86. }
    87. else
    88. {
    89. WRITE_REG(RTC->CNTH, (TimeCounter >> 16U));
    90. //"RTC计数寄存器高位RTC_CNTH"
    91. //Set RTC COUNTER MSB word
    92. WRITE_REG(RTC->CNTL, (TimeCounter & RTC_CNTL_RTC_CNT));
    93. //"RTC计数寄存器低位RTC_CNTL"
    94. //Set RTC COUNTER LSB word
    95. if (Exit_RTC_Init_Mode() != HAL_OK)
    96. {//等待RTC写操作结束
    97. status = HAL_ERROR;
    98. }
    99. }
    100. return status;
    101. }
    102. //函数功能:读"RTC闹钟寄存器"
    103. uint32_t Read_RTC_Alarm_Counter(void)
    104. {
    105. uint16_t high1 = 0U, low = 0U;
    106. high1 = READ_REG(RTC->ALRH & RTC_CNTH_RTC_CNT);
    107. //"RTC闹钟寄存器高位RTC_ALRH"
    108. low = READ_REG(RTC->ALRL & RTC_CNTL_RTC_CNT);
    109. //"RTC闹钟寄存器低位RTC_ALRL"
    110. return (((uint32_t) high1 << 16U) | low);
    111. }
    112. //函数功能:将AlarmCounter写入"RTC闹钟寄存器"
    113. HAL_StatusTypeDef Write_RTC_Alarm_Counter( uint32_t AlarmCounter)
    114. {
    115. HAL_StatusTypeDef status = HAL_OK;
    116. /* Set Initialization mode */
    117. if (Enter_RTC_Init_Mode() != HAL_OK)
    118. {//等待RTC写操作结束
    119. //返回0,表示退出RTC配置模式,开始更新RTC寄存器
    120. status = HAL_ERROR;
    121. }
    122. else
    123. {
    124. WRITE_REG(RTC->ALRH, (AlarmCounter >> 16U));
    125. //"RTC闹钟寄存器高位RTC_ALRH",Set RTC COUNTER MSB word
    126. WRITE_REG(RTC->ALRL, (AlarmCounter & RTC_ALRL_RTC_ALR));
    127. //"RTC闹钟寄存器低位RTC_ALRL",Set RTC COUNTER LSB word
    128. /* Wait for synchro */
    129. if (Exit_RTC_Init_Mode() != HAL_OK)
    130. {//等待RTC写操作结束
    131. status = HAL_ERROR;
    132. }
    133. }
    134. return status;
    135. }
    136. //函数功能:返回0表示闰年
    137. uint8_t Is_LeapYear(uint16_t nYear)
    138. {
    139. uint16_t y;
    140. y=Century;//2023926
    141. y=y*100;//2023926
    142. nYear=y+nYear;//2023926
    143. if ((nYear % 4U) != 0U)
    144. {
    145. return 0U;
    146. }
    147. if ((nYear % 100U) != 0U)
    148. {
    149. return 1U;
    150. }
    151. if ((nYear % 400U) == 0U)
    152. {
    153. return 1U;
    154. }
    155. else
    156. {
    157. return 0U;
    158. }
    159. }
    160. //函数功能;读取星期几的值
    161. uint8_t Read_RTC_WeekDay(uint32_t nYear, uint8_t nMonth, uint8_t nDay)
    162. {
    163. uint32_t year = 0U, weekday = 0U;
    164. year = 2000U + nYear;
    165. if (nMonth < 3U)
    166. {
    167. /*D = { [(23 x month)/9] + day + 4 + year + [(year-1)/4] - [(year-1)/100] + [(year-1)/400] } mod 7*/
    168. weekday = (((23U * nMonth) / 9U) + nDay + 4U + year + ((year - 1U) / 4U) - ((year - 1U) / 100U) + ((year - 1U) / 400U)) % 7U;
    169. }
    170. else
    171. {
    172. /*D = { [(23 x month)/9] + day + 4 + year + [year/4] - [year/100] + [year/400] - 2 } mod 7*/
    173. weekday = (((23U * nMonth) / 9U) + nDay + 4U + year + (year / 4U) - (year / 100U) + (year / 400U) - 2U) % 7U;
    174. }
    175. return (uint8_t)weekday;
    176. }
    177. void Update_RTC_Date(RTC_DateTypeDef *update_RTCDate, uint32_t DayElapsed)
    178. {
    179. uint32_t year = 0U, month = 0U, day = 0U;
    180. uint32_t loop = 0U;
    181. /* Get the current year*/
    182. year = update_RTCDate->Year;
    183. /* Get the current month and day */
    184. month = update_RTCDate->Month;
    185. day = update_RTCDate->Date;
    186. for (loop = 0U; loop < DayElapsed; loop++)
    187. {
    188. if ((month == 1U) || (month == 3U) || (month == 5U) || (month == 7U) || \
    189. (month == 8U) || (month == 10U) || (month == 12U))
    190. {
    191. if (day < 31U)
    192. {
    193. day++;
    194. }
    195. /* Date structure member: day = 31 */
    196. else
    197. {
    198. if (month != 12U)
    199. {
    200. month++;
    201. day = 1U;
    202. }
    203. /* Date structure member: day = 31 & month =12 */
    204. else
    205. {
    206. month = 1U;
    207. day = 1U;
    208. year++;
    209. }
    210. }
    211. }
    212. else if ((month == 4U) || (month == 6U) || (month == 9U) || (month == 11U))
    213. {
    214. if (day < 30U)
    215. {
    216. day++;
    217. }
    218. /* Date structure member: day = 30 */
    219. else
    220. {
    221. month++;
    222. day = 1U;
    223. }
    224. }
    225. else if (month == 2U)
    226. {
    227. if (day < 28U)
    228. {
    229. day++;
    230. }
    231. else if (day == 28U)
    232. {
    233. if (Is_LeapYear(year))//不闰年
    234. {//返回0表示闰年
    235. day++;
    236. }
    237. else //闰年
    238. {
    239. month++;
    240. day = 1U;
    241. }
    242. }
    243. else if (day == 29U)
    244. {
    245. month++;
    246. day = 1U;
    247. }
    248. }
    249. }
    250. if(year>=100)//2023926
    251. {
    252. Century++;
    253. year=year-100;
    254. }
    255. /* Update year */
    256. update_RTCDate->Year = year;
    257. /* Update day and month */
    258. update_RTCDate->Month = month;
    259. update_RTCDate->Date = day;
    260. /* Update day of the week */
    261. update_RTCDate->WeekDay = Read_RTC_WeekDay(year, month, day);
    262. //读取星期几的值
    263. }
    264. HAL_StatusTypeDef Read_RTC_Time(RTC_DateTypeDef *update_RTCDate, RTC_TimeTypeDef *sTime)
    265. {
    266. uint32_t counter_time = 0U, counter_alarm = 0U, days_elapsed = 0U, hours = 0U;
    267. counter_time = Read_RTC_Time_Counter();//"RTC计数寄存器",总秒数
    268. hours = counter_time / 3600U;//计算有多少小时
    269. sTime->Minutes = (uint8_t)((counter_time % 3600U) / 60U);//计算分钟数值
    270. sTime->Seconds = (uint8_t)((counter_time % 3600U) % 60U);//计算秒数值
    271. if (hours >= 24U)
    272. {
    273. days_elapsed = (hours / 24U);//计算"天"
    274. sTime->Hours = (hours % 24U);//计算今天的"小时时间"
    275. counter_alarm = Read_RTC_Alarm_Counter();
    276. //"RTC闹钟寄存器"
    277. //Read Alarm counter in RTC registers
    278. /* Calculate remaining time to reach alarm (only if set and not yet expired)*/
    279. if ((counter_alarm != 0xFFFFFFFF) && (counter_alarm > counter_time))
    280. {//RTC_ALARM_RESETVALUE=0xFFFFFFFFU
    281. counter_alarm -= counter_time;//计算"距离报警时间的差值"
    282. }
    283. else
    284. {
    285. /* In case of counter_alarm < counter_time */
    286. /* Alarm expiration already occurred but alarm not deactivated */
    287. counter_alarm = 0xFFFFFFFF;
    288. //RTC_ALARM_RESETVALUE=0xFFFFFFFFU
    289. }
    290. /* Set updated time in decreasing counter by number of days elapsed */
    291. counter_time -= (days_elapsed * 24U * 3600U);//计算"今天的总秒数"
    292. /* Write time counter in RTC registers */
    293. if (Write_RTC_Time_Counter(counter_time) != HAL_OK)
    294. {//"今天的总秒数"counter_time写入"RTC计数寄存器"
    295. return HAL_ERROR;
    296. }
    297. /* Set updated alarm to be set */
    298. if (counter_alarm != 0xFFFFFFFF)
    299. {//RTC_ALARM_RESETVALUE=0xFFFFFFFFU
    300. counter_alarm += counter_time;
    301. //报警时间 = "距离报警时间的差值" + "今天的总秒数"
    302. if (Write_RTC_Alarm_Counter(counter_alarm) != HAL_OK)
    303. {//将AlarmCounter写入"RTC闹钟寄存器"
    304. return HAL_ERROR;
    305. }
    306. }
    307. else
    308. {
    309. /* Alarm already occurred. Set it to reset values to avoid unexpected expiration */
    310. if (Write_RTC_Alarm_Counter(counter_alarm) != HAL_OK)
    311. {//将AlarmCounter写入"RTC闹钟寄存器"
    312. return HAL_ERROR;
    313. }
    314. }
    315. /* Update date */
    316. Update_RTC_Date(update_RTCDate, days_elapsed);
    317. }
    318. else
    319. {
    320. sTime->Hours = hours;
    321. }
    322. return HAL_OK;
    323. }
    324. HAL_StatusTypeDef Read_RTC_Date(RTC_DateTypeDef *update_RTCDate,RTC_DateTypeDef *sDate)
    325. {
    326. RTC_TimeTypeDef stime = {0U};
    327. /* Call HAL_RTC_GetTime function to update date if counter higher than 24 hours */
    328. if (Read_RTC_Time(update_RTCDate, &stime) != HAL_OK)
    329. {
    330. return HAL_ERROR;
    331. }
    332. /* Fill the structure fields with the read parameters */
    333. sDate->WeekDay = update_RTCDate->WeekDay;
    334. sDate->Year = update_RTCDate->Year;
    335. sDate->Month = update_RTCDate->Month;
    336. sDate->Date = update_RTCDate->Date;
    337. return HAL_OK;
    338. }
    339. void RTC_Init(void)
    340. {
    341. RTC_HandleTypeDef RTC_HandleStructureure;
    342. RCC_OscInitTypeDef RCC_OscInit_Structureure;
    343. RCC_PeriphCLKInitTypeDef PeriphClkInit_Structureure;
    344. Century=20;//世纪,21世纪用20表示
    345. RTC_HandleStructureure.Instance = RTC; //选择RTC
    346. RTC_HandleStructureure.Init.AsynchPrediv = RTC_AUTO_1_SECOND; //RTC一秒时基自动计算
    347. //HAL_RTC_MspInit函数开始//
    348. RCC_OscInit_Structureure.OscillatorType = RCC_OSCILLATORTYPE_LSI;
    349. RCC_OscInit_Structureure.LSIState = RCC_LSI_ON;
    350. HAL_RCC_OscConfig(&RCC_OscInit_Structureure);
    351. PeriphClkInit_Structureure.PeriphClockSelection = RCC_PERIPHCLK_RTC;
    352. PeriphClkInit_Structureure.RTCClockSelection = RCC_RTCCLKSOURCE_LSI;
    353. HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit_Structureure);
    354. __HAL_RCC_RTCAPB_CLK_ENABLE();
    355. //使能RTC APB外部设备时钟,Enable RTC peripheral Clocks
    356. __HAL_RCC_RTC_ENABLE();//使能RTC时钟,Enable RTC Clock
    357. HAL_NVIC_SetPriority(RTC_IRQn, 0x01, 0);
    358. //设置RTC中断优先级为0x01,0无意义
    359. NVIC_EnableIRQ(RTC_IRQn);//使能RTC中断
    360. __HAL_RTC_OVERFLOW_ENABLE_IT(&RTC_HandleStructureure, RTC_IT_OW);//使能溢出中断,Overflow interrupt
    361. __HAL_RTC_ALARM_ENABLE_IT(&RTC_HandleStructureure, RTC_IT_ALRA);//使能报警中断,Alarm interrupt
    362. __HAL_RTC_SECOND_ENABLE_IT(&RTC_HandleStructureure, RTC_IT_SEC);//使能秒中断,Second interrupt
    363. //HAL_RTC_MspInit函数结束//
    364. HAL_RTC_Init(&RTC_HandleStructureure);//RTC初始化
    365. /设置日期: 2023/9/27 星期三/
    366. RTC_DateStructureure.Year = 23;
    367. RTC_DateStructureure.Month =9;
    368. RTC_DateStructureure.Date = 27;
    369. RTC_DateStructureure.WeekDay = RTC_WEEKDAY_WEDNESDAY;
    370. HAL_RTC_SetDate(&RTC_HandleStructureure, &RTC_DateStructureure, RTC_FORMAT_BIN);
    371. //设置RTC日期
    372. /设置时间: 09:00:00/
    373. RTC_TimeStructureure.Hours = 9;
    374. RTC_TimeStructureure.Minutes =00;
    375. RTC_TimeStructureure.Seconds = 00;
    376. HAL_RTC_SetTime(&RTC_HandleStructureure, &RTC_TimeStructureure, RTC_FORMAT_BIN);
    377. //设置RTC时间
    378. /设置RTC闹钟,时间到09:01:00产生中断/
    379. RTC_AlarmStructureure.AlarmTime.Hours = 9;
    380. RTC_AlarmStructureure.AlarmTime.Minutes = 1;
    381. RTC_AlarmStructureure.AlarmTime.Seconds = 00;
    382. HAL_RTC_SetAlarm_IT(&RTC_HandleStructureure, &RTC_AlarmStructureure, RTC_FORMAT_BIN);
    383. }
    384. void RTC_Display(void)
    385. {
    386. Read_RTC_Time(&RTC_DateStructureure,&RTC_TimeStructureure);
    387. // Read_RTC_Date(&RTC_DateStructureure,&RTC_DateStructureure);
    388. // RTC_HandleTypeDef RTC_HandleStructureure;
    389. // RTC_HandleStructureure.Instance = RTC;//选择RTC
    390. // printf("RTC_IT_SEC\r\n");
    391. // HAL_RTC_GetTime(&RTC_HandleStructureure, &RTC_TimeStructureure, RTC_FORMAT_BIN);//读取"RTC时间"
    392. // HAL_RTC_GetDate(&RTC_HandleStructureure, &RTC_DateStructureure, RTC_FORMAT_BIN);//读取"RTC日期"
    393. printf("%02d%02d-%02d-%02d %02d:%02d:%02d\r\n", Century,RTC_DateStructureure.Year,RTC_DateStructureure.Month,RTC_DateStructureure.Date,RTC_TimeStructureure.Hours, RTC_TimeStructureure.Minutes, RTC_TimeStructureure.Seconds);
    394. //显示时间格式为 : YY-MM-DD hh:mm:ss
    395. if(RTC_DateStructureure.WeekDay==RTC_WEEKDAY_SUNDAY) printf("Sunday\r\n");
    396. if(RTC_DateStructureure.WeekDay==RTC_WEEKDAY_MONDAY) printf("Monday\r\n");
    397. if(RTC_DateStructureure.WeekDay==RTC_WEEKDAY_TUESDAY) printf("Tuesday\r\n");
    398. if(RTC_DateStructureure.WeekDay==RTC_WEEKDAY_WEDNESDAY) printf("Wednesday\r\n");
    399. if(RTC_DateStructureure.WeekDay==RTC_WEEKDAY_THURSDAY) printf("Thursday\r\n");
    400. if(RTC_DateStructureure.WeekDay==RTC_WEEKDAY_FRIDAY) printf("Friday\r\n");
    401. if(RTC_DateStructureure.WeekDay==RTC_WEEKDAY_SATURDAY) printf("Saturday\r\n");
    402. }
    403. //函数功能;RTC中断服务函数
    404. void RTC_IRQHandler(void)
    405. {
    406. if (_HAL_RTC_SECOND_GET_FLAG(RTC,RTC_FLAG_SEC))
    407. {
    408. if (_HAL_RTC_SECOND_GET_FLAG(RTC, RTC_FLAG_OW))
    409. {//RTC计数器溢出中断
    410. /HAL_RTCEx_RTCEventCallback函数开始/
    411. printf("%s","\r\nRTC Overflow!!!\r\n");
    412. /HAL_RTCEx_RTCEventCallback函数结束/
    413. _HAL_RTC_OVERFLOW_CLEAR_FLAG(RTC, RTC_FLAG_OW);
    414. //清除溢出中断
    415. }
    416. else
    417. {//RTC产生秒中断
    418. /HAL_RTCEx_RTCEventCallback函数开始/
    419. MCU_LED_Toggle();
    420. /HAL_RTCEx_RTCEventCallback函数结束/
    421. }
    422. _HAL_RTC_SECOND_CLEAR_FLAG(RTC, RTC_FLAG_SEC);
    423. }
    424. if (_HAL_RTC_ALARM_GET_FLAG(RTC, RTC_FLAG_ALRAF) != (uint32_t)RESET)
    425. {//RTC产生报警中断
    426. /HAL_RTC_AlarmAEventCallback函数开始/
    427. printf("%s","\r\nRTC Alarm!!!\r\n");
    428. /HAL_RTC_AlarmAEventCallback函数结束/
    429. _HAL_RTC_ALARM_CLEAR_FLAG(RTC, RTC_FLAG_ALRAF);
    430. //Clear the Alarm interrupt pending bit
    431. }
    432. }
    1. #ifndef __RTC_H
    2. #define __RTC_H
    3. #include "py32f0xx_hal.h"
    4. #define _HAL_RTC_SECOND_GET_FLAG(__INSTANCE__, __FLAG__) (((((__INSTANCE__)->CRL) & (__FLAG__)) != RESET)? SET : RESET)
    5. #define _HAL_RTC_OVERFLOW_CLEAR_FLAG(__INSTANCE__, __FLAG__) ((__INSTANCE__)->CRL) = ~(__FLAG__)
    6. #define _HAL_RTC_SECOND_CLEAR_FLAG(__INSTANCE__, __FLAG__) ((__INSTANCE__)->CRL) = ~(__FLAG__)
    7. #define _HAL_RTC_ALARM_GET_FLAG(__INSTANCE__, __FLAG__) (((((__INSTANCE__)->CRL) & (__FLAG__)) != RESET)? SET : RESET)
    8. #define _HAL_RTC_ALARM_CLEAR_FLAG(__INSTANCE__, __FLAG__) ((__INSTANCE__)->CRL) = ~(__FLAG__)
    9. //#define _HAL_RTC_ALARM_ENABLE_IT(__INSTANCE__, __INTERRUPT__) SET_BIT((__INSTANCE__)->CRH, (__INTERRUPT__))
    10. #define _HAL_RTC_WRITEPROTECTION_ENABLE(__INSTANCE__) CLEAR_BIT((__INSTANCE__)->CRL, RTC_CRL_CNF)
    11. //"RTC控制寄存器RTC_CRL"中的CNF=1,进入RTC配置模式
    12. #define _HAL_RTC_WRITEPROTECTION_DISABLE(__INSTANCE__) SET_BIT((__INSTANCE__)->CRL, RTC_CRL_CNF)
    13. //"RTC控制寄存器RTC_CRL"中的CNF=0,退出配置模式,开始更新RTC寄存器
    14. extern void RTC_Init(void);
    15. extern void RTC_Display(void);
    16. #endif /* __RTC_H */
    1. #include "py32f0xx_hal.h"
    2. #include "SystemClock.h"
    3. #include "delay.h"
    4. #include "LED.h"
    5. #include "SystemClock.h"
    6. #include "USART2.h"
    7. #include "stdio.h" //getchar(),putchar(),scanf(),printf(),puts(),gets(),sprintf()
    8. #include "string.h" //使能strcpy(),strlen(),memset()
    9. #include "RTC.h"
    10. const char CPU_Reset_REG[]="\r\nCPU reset!\r\n";
    11. int main(void)
    12. {
    13. HSE_Config();
    14. // HAL_Init();//systick初始化
    15. delay_init();
    16. HAL_Delay(1000);
    17. USART2_Init(115200);
    18. //PA0是为USART2_TX,PA1是USART2_RX
    19. //中断优先级为0x01
    20. //波特率为115200,数字为8位,停止位为1位,无奇偶校验,允许发送和接收数据,只允许接收中断,并使能串口
    21. printf("%s",CPU_Reset_REG);
    22. MCU_LED_Init();
    23. RTC_Init();
    24. while (1)
    25. {
    26. delay_ms(1000);
    27. RTC_Display();
    28. }
    29. }

    四、误差分析

    误差: 每10分钟误差6秒。1%的误差,还行。

  • 相关阅读:
    JS 流行框架(八):ScrollReveal
    MySQL数据库管理基本操作
    【图像配准】Canny边缘检测+模板配准红外可见光双路数据
    python+django车辆违章信息查询管理系统pycharm项目
    js看代码说输出
    MC Layer Target
    React知识点系列(4)-每天10个小知识
    设计模式之美 - 如何理解单例模式中的唯一性?
    注塑行业MES系统解决方案,打造数字化智能工厂 先达智控
    CAPL学习之路-DoIP相关函数
  • 原文地址:https://blog.csdn.net/weixin_42550185/article/details/133338811