rtc.c 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. /**
  2. ******************************** STM32F10x *********************************
  3. * @文件名 : rtc.c
  4. * @作者 : sun
  5. * @库版本 : V3.5.0
  6. * @文件版本 : V1.0.0
  7. * @日期 : 2018年02月04日
  8. * @摘要 : RTC源文件
  9. ******************************************************************************/
  10. /*----------------------------------------------------------------------------
  11. 更新日志:
  12. 2018-02-04 V1.0.0:初始版本
  13. ----------------------------------------------------------------------------*/
  14. /* 包含的头文件 --------------------------------------------------------------*/
  15. #include "rtc.h"
  16. #include "systick.h"
  17. #include "delay.h"
  18. RTC_DateTimeTypeDef DeviceRTC={16,5,19,15,26,0};
  19. // DeviceRTC.Year = 16;
  20. // DeviceRTC.Month = 5;
  21. // DeviceRTC.Date = 19;
  22. // DeviceRTC.Hour = 15;
  23. // DeviceRTC.Minute = 26;
  24. // DeviceRTC.Second = 0;
  25. /************************************************
  26. 函数名称 : RTC_Configuration
  27. 功 能 : RTC配置
  28. 参 数 : 无
  29. 返 回 值 : 无
  30. 作 者 : sun
  31. *************************************************/
  32. void RTC_Configuration(void)
  33. {
  34. BKP_DeInit(); //复位后备区域
  35. RCC_LSEConfig(RCC_LSE_ON); //使能低速外部时钟(LSE)
  36. while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);
  37. RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //选择LSE作为RTC时钟源
  38. RCC_RTCCLKCmd(ENABLE); //使能RTC时钟
  39. RTC_WaitForSynchro(); //等待同步
  40. RTC_WaitForLastTask(); //等待操作完成
  41. // RTC_ITConfig(RTC_IT_ALR, ENABLE); //使能闹钟中断
  42. // RTC_WaitForLastTask(); //等待操作完成
  43. RTC_SetPrescaler(32767); //分频值
  44. RTC_WaitForLastTask(); //等待操作完成
  45. }
  46. /************************************************
  47. 函数名称 : RTC_Initializes
  48. 功 能 : RTC初始化
  49. 参 数 : 无
  50. 返 回 值 : 无
  51. 作 者 : sun
  52. *************************************************/
  53. void RTC_Initializes(void)
  54. {
  55. RTC_DateTimeTypeDef RTC_DateTimeStructure;
  56. RTC_DateTimeStructure.Year = 16;
  57. RTC_DateTimeStructure.Month = 7;
  58. RTC_DateTimeStructure.Date = 18;
  59. RTC_DateTimeStructure.Hour = 18;
  60. RTC_DateTimeStructure.Minute = 0;
  61. RTC_DateTimeStructure.Second = 0;
  62. PWR_BackupAccessCmd(ENABLE); //允许操作后备区域
  63. /* 判断是否首次操作RTC */
  64. if(BKP_ReadBackupRegister(BKP_DR1) != 0xA5A5)
  65. {
  66. RTC_Configuration(); //配置RTC
  67. RTC_SetDateTime(RTC_DateTimeStructure); //初始化日历(2016年7月18日 18:00:00)
  68. BKP_WriteBackupRegister(BKP_DR1, 0xA5A5);
  69. }
  70. else
  71. {
  72. if(RCC_GetFlagStatus(RCC_FLAG_PORRST) != RESET)
  73. {
  74. }
  75. else if(RCC_GetFlagStatus(RCC_FLAG_PINRST) != RESET)
  76. {
  77. }
  78. RTC_WaitForSynchro(); //等待RTC与RTC_APB时钟同步
  79. }
  80. // RTC_ITConfig(RTC_IT_SEC, ENABLE); //使能秒中断
  81. RTC_WaitForLastTask(); //等待TRC最后一次操作完成
  82. }
  83. static void RTC_NVIC_Config(void)
  84. {
  85. NVIC_InitTypeDef NVIC_InitStructure;
  86. NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn; //RTC全局中断
  87. NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0; //先占优先级1位,从优先级3位
  88. NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0; //先占优先级0位,从优先级4位
  89. NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE; //使能该通道中断
  90. NVIC_Init(&NVIC_InitStructure); //根据NVIC_InitStruct中指定的参数初始化外设NVIC寄存器
  91. }
  92. //实时时钟配置
  93. //初始化RTC时钟,同时检测时钟是否工作正常
  94. //BKP->DR1用于保存是否第一次配置的设置
  95. //返回0:正常
  96. //其他:错误代码
  97. uint8_t RTC_Init(void)
  98. {
  99. uint8_t temp=0;
  100. //检查是不是第一次配置时钟
  101. RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR | RCC_APB1Periph_BKP, ENABLE); //使能PWR和BKP外设时钟
  102. PWR_BackupAccessCmd(ENABLE); //使能后备寄存器访问
  103. if (BKP_ReadBackupRegister(BKP_DR1) != 0x5050) //从指定的后备寄存器中读出数据:读出了与写入的指定数据不相乎
  104. {
  105. BKP_DeInit(); //复位备份区域
  106. /////////////////////(时钟配置部分)////////////////////////////
  107. //RCC_LSEConfig(RCC_LSE_ON); //设置外部低速晶振(LSE),使用外设低速晶振
  108. RCC_LSICmd(ENABLE);//开启内部低速晶振LSI,changed by scx
  109. while( RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == 0 && temp<11)
  110. //while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) //检查指定的RCC标志位设置与否,等待低速晶振就绪
  111. {
  112. temp++;
  113. delay_ms(10);
  114. }
  115. if(temp>=10)return 1;//初始化时钟失败,晶振有问题
  116. RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
  117. //RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE); //设置RTC时钟(RTCCLK),选择LSE作为RTC时钟
  118. RCC_RTCCLKCmd(ENABLE); //使能RTC时钟
  119. RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成
  120. RTC_WaitForSynchro(); //等待RTC寄存器同步
  121. RTC_ITConfig(RTC_IT_SEC, ENABLE); //使能RTC秒中断
  122. RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成
  123. ///////////////// ////(寄存器配置部分)////////////////////////////
  124. RTC_EnterConfigMode();/// 允许配置
  125. RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成
  126. RTC_SetPrescaler(39000);//分频后为1HZ
  127. //RTC_SetPrescaler(32767); //设置RTC预分频的值
  128. RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成
  129. RTC_SetDateTime(DeviceRTC); //设置时间
  130. RTC_ExitConfigMode(); //退出配置模式
  131. BKP_WriteBackupRegister(BKP_DR1, 0X5050); //向指定的后备寄存器中写入用户程序数据
  132. }
  133. else//系统继续计时
  134. {
  135. /////////////////////(时钟配置部分)////////////////////////////
  136. RCC_LSICmd(ENABLE);//开启内部低速晶振LSI
  137. while( RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == 0 && temp<11)
  138. //while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET) //检查指定的RCC标志位设置与否,等待低速晶振就绪
  139. {
  140. temp++;
  141. delay_ms(10);
  142. }
  143. if(temp>=10)return 1;//初始化时钟失败,晶振有问题
  144. RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
  145. RCC_RTCCLKCmd(ENABLE);//选择使能RTC时钟
  146. RTC_WaitForLastTask();//等待上一次写RTC任务完成(常用,只要涉及对RTC里值的修改,都需要在修改后加上此函数)
  147. RTC_WaitForSynchro();//等待与APB1的同步,才能读RTC寄存器
  148. RTC_EnterConfigMode();//允许RTC配置
  149. RTC_ITConfig(RTC_IT_SEC, ENABLE); //使能RTC秒中断
  150. RTC_WaitForLastTask();//等待上一次写RTC任务完成(常用,只要涉及对RTC里值的修改,都需要在修改后加上此函数)
  151. RTC_SetPrescaler(39000);//分频后为1HZ
  152. RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成
  153. RTC_ExitConfigMode(); //等待最近一次对RTC寄存器的写操作完成
  154. RTC_WaitForLastTask(); //等待最近一次对RTC寄存器的写操作完成
  155. }
  156. RTC_NVIC_Config();//RCT中断分组设置
  157. RTC_GetDateTime(&DeviceRTC);//更新时间
  158. return 0; //ok
  159. }
  160. /************************************************
  161. 函数名称 : RTC_SetDateTime
  162. 功 能 : 设置RTC日期时间
  163. 参 数 : RTC_DateTimeStructure --- RTC日期时间结构体
  164. 返 回 值 : RTC_OK ------------------ 成功
  165. RTC_OVERFLOW ------------ 失败(越界)
  166. 作 者 : sun
  167. *************************************************/
  168. RTC_RESULT RTC_SetDateTime(RTC_DateTimeTypeDef RTC_DateTimeStructure)
  169. {
  170. uint32_t num_leapyear; //闰年天数
  171. uint32_t conut_year; //计秒(年)
  172. uint32_t conut_month_day; //月日的秒计数
  173. /*------------------------- 判断是否越界 --------------------------*/
  174. //年、月、星期、时、分、秒
  175. if((130 < RTC_DateTimeStructure.Year) || (12 < RTC_DateTimeStructure.Month) ||
  176. (24 <= RTC_DateTimeStructure.Hour) || (60 <= RTC_DateTimeStructure.Minute) || (60 <= RTC_DateTimeStructure.Second))
  177. {
  178. return RTC_OVERFLOW;
  179. }
  180. //日
  181. if((RTC_DateTimeStructure.Month==1)|(RTC_DateTimeStructure.Month==3)|(RTC_DateTimeStructure.Month==5)|(RTC_DateTimeStructure.Month==7)|(RTC_DateTimeStructure.Month==8)|(RTC_DateTimeStructure.Month==10)|(RTC_DateTimeStructure.Month==12))
  182. {
  183. if(RTC_DateTimeStructure.Date > 31)
  184. return RTC_OVERFLOW;
  185. }
  186. else if((RTC_DateTimeStructure.Month==4)|(RTC_DateTimeStructure.Month==6)|(RTC_DateTimeStructure.Month==9)|(RTC_DateTimeStructure.Month==11))
  187. {
  188. if(RTC_DateTimeStructure.Date > 30)
  189. return RTC_OVERFLOW;
  190. }
  191. else if(RTC_DateTimeStructure.Month==2)
  192. { /* 如果是闰年 */
  193. if(RTC_DateTimeStructure.Year%4 == 0)
  194. {
  195. if(RTC_DateTimeStructure.Date > 29)
  196. return RTC_OVERFLOW;
  197. }
  198. else if(RTC_DateTimeStructure.Date > 28)
  199. return RTC_OVERFLOW;
  200. }
  201. //--------------------------- 计算天数 ----------------------------
  202. //闰年数
  203. num_leapyear = RTC_DateTimeStructure.Year/4 + 1;
  204. //计秒(年)
  205. conut_year = RTC_DateTimeStructure.Year*SEC_YEAR + num_leapyear*SEC_DAY;
  206. switch(RTC_DateTimeStructure.Month)
  207. {
  208. case 1:/* 一月 */
  209. conut_month_day = (RTC_DateTimeStructure.Date-1)*SEC_DAY;
  210. if(RTC_DateTimeStructure.Year%4 == 0) //假如是闰年,需要减去一天的计数
  211. conut_month_day -= SEC_DAY;
  212. break;
  213. case 2:/* 二月 */
  214. conut_month_day = (31 + RTC_DateTimeStructure.Date - 1)*SEC_DAY;
  215. if(RTC_DateTimeStructure.Year%4 == 0) //假如是闰年,需要减去一天的计数
  216. conut_month_day -= SEC_DAY;
  217. break;
  218. case 3:/* 三月 */
  219. conut_month_day = (59 + RTC_DateTimeStructure.Date - 1)*SEC_DAY;
  220. break;
  221. case 4:/* 四月 */
  222. conut_month_day = (90 + RTC_DateTimeStructure.Date - 1)*SEC_DAY;
  223. break;
  224. case 5:/* 五月 */
  225. conut_month_day = (120 + RTC_DateTimeStructure.Date - 1)*SEC_DAY;
  226. break;
  227. case 6:/* 六月 */
  228. conut_month_day = (151 + RTC_DateTimeStructure.Date - 1)*SEC_DAY;
  229. break;
  230. case 7:/* 七月 */
  231. conut_month_day = (181 + RTC_DateTimeStructure.Date - 1)*SEC_DAY;
  232. break;
  233. case 8:/* 八月 */
  234. conut_month_day = (212 + RTC_DateTimeStructure.Date - 1)*SEC_DAY;
  235. break;
  236. case 9:/* 九月 */
  237. conut_month_day = (243 + RTC_DateTimeStructure.Date - 1)*SEC_DAY;
  238. break;
  239. case 10:/* 十月 */
  240. conut_month_day = (273 + RTC_DateTimeStructure.Date - 1)*SEC_DAY;
  241. break;
  242. case 11:/* 十一月 */
  243. conut_month_day = (304 + RTC_DateTimeStructure.Date - 1)*SEC_DAY;
  244. break;
  245. case 12:/* 十二月 */
  246. conut_month_day = (334 + RTC_DateTimeStructure.Date - 1)*SEC_DAY;
  247. break;
  248. }
  249. RTC_WaitForLastTask();
  250. //设置计数值(更新RTC)
  251. RTC_SetCounter(conut_year + conut_month_day + RTC_DateTimeStructure.Hour*3600 + RTC_DateTimeStructure.Minute*60 + RTC_DateTimeStructure.Second);
  252. //等待TRC操作完成
  253. RTC_WaitForLastTask();
  254. return RTC_OK;
  255. }
  256. /************************************************
  257. 函数名称 : RTC_GetDateTime
  258. 功 能 : 读取RTC时间(含日历、星期)
  259. 参 数 : RTC_DateTimeStructure --- RTC日期时间结构体
  260. 返 回 值 : 无
  261. 作 者 : sun
  262. *************************************************/
  263. void RTC_GetDateTime(RTC_DateTimeTypeDef *RTC_DateTimeStructure)
  264. {
  265. uint32_t num_day; //计数的天数
  266. uint32_t num_daytmp; //该年的天数
  267. uint32_t num_leapyear; //闰年数
  268. uint32_t count_value = RTC_GetCounter(); //读取RTC计数值
  269. num_day = count_value/SEC_DAY; //从0开始计算天数
  270. num_leapyear = num_day/(365*4+1) + 1; //闰年数
  271. if(num_day%(365*4+1) == 0) //闰年的1月1日
  272. RTC_DateTimeStructure->Year = (uint8_t)((num_day - num_leapyear + 1)/365);
  273. else
  274. RTC_DateTimeStructure->Year = (num_day - num_leapyear)/365;
  275. if(RTC_DateTimeStructure->Year%4 == 0)
  276. {
  277. /* 闰年一年内的天数 */
  278. num_daytmp = num_day - RTC_DateTimeStructure->Year*365 - (num_leapyear-1);
  279. if(num_daytmp < 31) /* 一月 */
  280. {
  281. RTC_DateTimeStructure->Month = 1;
  282. RTC_DateTimeStructure->Date = num_daytmp%31 + 1;
  283. }
  284. else if(num_daytmp < 60)/* 二月 */
  285. {
  286. RTC_DateTimeStructure->Month = 2;
  287. RTC_DateTimeStructure->Date = (num_daytmp - 31)%29 + 1;
  288. }
  289. else if(num_daytmp < 91)/* 三月 */
  290. {
  291. RTC_DateTimeStructure->Month = 3;
  292. RTC_DateTimeStructure->Date = (num_daytmp - 60)%31 + 1;
  293. }
  294. else if(num_daytmp < 121)/* 四月 */
  295. {
  296. RTC_DateTimeStructure->Month = 4;
  297. RTC_DateTimeStructure->Date = (num_daytmp - 91)%30 + 1;
  298. }
  299. else if(num_daytmp < 152)/* 五月 */
  300. {
  301. RTC_DateTimeStructure->Month = 5;
  302. RTC_DateTimeStructure->Date = (num_daytmp - 121)%31 + 1;
  303. }
  304. else if(num_daytmp < 182)/* 六月 */
  305. {
  306. RTC_DateTimeStructure->Month = 6;
  307. RTC_DateTimeStructure->Date = (num_daytmp - 152)%30 + 1;
  308. }
  309. else if(num_daytmp < 213)/* 七月 */
  310. {
  311. RTC_DateTimeStructure->Month = 7;
  312. RTC_DateTimeStructure->Date = (num_daytmp - 182)%31 + 1;
  313. }
  314. else if(num_daytmp < 244)/* 八月 */
  315. {
  316. RTC_DateTimeStructure->Month = 8;
  317. RTC_DateTimeStructure->Date = (num_daytmp - 213)%31 + 1;
  318. }
  319. else if(num_daytmp < 274)/* 九月 */
  320. {
  321. RTC_DateTimeStructure->Month = 9;
  322. RTC_DateTimeStructure->Date = (num_daytmp - 244)%30 + 1;
  323. }
  324. else if(num_daytmp < 305)/* 十月 */
  325. {
  326. RTC_DateTimeStructure->Month = 10;
  327. RTC_DateTimeStructure->Date = (num_daytmp - 274)%31 + 1;
  328. }
  329. else if(num_daytmp < 335)/* 十一月 */
  330. {
  331. RTC_DateTimeStructure->Month = 11;
  332. RTC_DateTimeStructure->Date = (num_daytmp - 305)%30 + 1;
  333. }
  334. else if(num_daytmp < 366)/* 十二月 */
  335. {
  336. RTC_DateTimeStructure->Month = 12;
  337. RTC_DateTimeStructure->Date = (num_daytmp - 335)%31 + 1;
  338. }
  339. }
  340. else
  341. {
  342. /* 平年一年内的天数 */
  343. num_daytmp = num_day - RTC_DateTimeStructure->Year*365 - num_leapyear ;
  344. if(num_daytmp < 31)
  345. {
  346. RTC_DateTimeStructure->Month = 1;
  347. RTC_DateTimeStructure->Date = num_daytmp%31 + 1;
  348. }
  349. else if(num_daytmp < 59)
  350. {
  351. RTC_DateTimeStructure->Month = 2;
  352. RTC_DateTimeStructure->Date = (num_daytmp - 31)%28 + 1;
  353. }
  354. else if(num_daytmp < 90)
  355. {
  356. RTC_DateTimeStructure->Month = 3;
  357. RTC_DateTimeStructure->Date = (num_daytmp - 59)%31 + 1;
  358. }
  359. else if(num_daytmp < 120)
  360. {
  361. RTC_DateTimeStructure->Month = 4;
  362. RTC_DateTimeStructure->Date = (num_daytmp - 90)%30 + 1;
  363. }
  364. else if(num_daytmp < 151)
  365. {
  366. RTC_DateTimeStructure->Month = 5;
  367. RTC_DateTimeStructure->Date = (num_daytmp - 120)%31 + 1;
  368. }
  369. else if(num_daytmp < 181)
  370. {
  371. RTC_DateTimeStructure->Month = 6;
  372. RTC_DateTimeStructure->Date = (num_daytmp - 151)%30 + 1;
  373. }
  374. else if(num_daytmp < 212)
  375. {
  376. RTC_DateTimeStructure->Month = 7;
  377. RTC_DateTimeStructure->Date = (num_daytmp - 181)%31 + 1;
  378. }
  379. else if(num_daytmp < 243)
  380. {
  381. RTC_DateTimeStructure->Month = 8;
  382. RTC_DateTimeStructure->Date = (num_daytmp - 212)%31 + 1;
  383. }
  384. else if(num_daytmp < 273)
  385. {
  386. RTC_DateTimeStructure->Month = 9;
  387. RTC_DateTimeStructure->Date = (num_daytmp - 243)%30 + 1;
  388. }
  389. else if(num_daytmp < 304)
  390. {
  391. RTC_DateTimeStructure->Month = 10;
  392. RTC_DateTimeStructure->Date = (num_daytmp - 273)%31 + 1;
  393. }
  394. else if(num_daytmp < 334)
  395. {
  396. RTC_DateTimeStructure->Month = 11;
  397. RTC_DateTimeStructure->Date = (num_daytmp - 304)%30 + 1;
  398. }
  399. else if(num_daytmp < 365)
  400. {
  401. RTC_DateTimeStructure->Month = 12;
  402. RTC_DateTimeStructure->Date = (num_daytmp - 334)%31 + 1;
  403. }
  404. }
  405. /* 星期 */
  406. RTC_DateTimeStructure->Week = (num_day + 5)%7 + 1;
  407. /* 时 */
  408. RTC_DateTimeStructure->Hour = (count_value / 3600) % 24;
  409. /* 分 */
  410. RTC_DateTimeStructure->Minute = (count_value % 3600) / 60;
  411. /* 秒 */
  412. RTC_DateTimeStructure->Second = count_value % 60;
  413. }
  414. /************************************************
  415. 函数名称 : RTC_Initializes
  416. 功 能 : RTC初始化
  417. 参 数 : 无
  418. 返 回 值 : 无
  419. 作 者 : sun
  420. *************************************************/
  421. void RTC_SetAlarmTime_S(uint32_t Time )
  422. {
  423. uint32_t TimeNow = 0;
  424. RTC_ITConfig(RTC_IT_ALR, DISABLE); //使能闹钟中断
  425. RTC_WaitForLastTask(); //等待操作完成
  426. TimeNow = RTC_GetCounter();
  427. TimeNow = TimeNow + Time -1;
  428. RTC_SetAlarm(TimeNow); //闹钟时间
  429. RTC_WaitForLastTask(); //等待操作完成
  430. RTC_ITConfig(RTC_IT_ALR, ENABLE); //使能闹钟中断
  431. RTC_WaitForLastTask(); //等待操作完成
  432. }
  433. /**** Copyright (C)2016 sun. All Rights Reserved **** END OF FILE ****/