rtc.c 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877
  1. /**
  2. * |----------------------------------------------------------------------
  3. * | Copyright (C) Tilen Majerle, 2014
  4. * |
  5. * | This program is free software: you can redistribute it and/or modify
  6. * | it under the terms of the GNU General Public License as published by
  7. * | the Free Software Foundation, either version 3 of the License, or
  8. * | any later version.
  9. * |
  10. * | This program is distributed in the hope that it will be useful,
  11. * | but WITHOUT ANY WARRANTY; without even the implied warranty of
  12. * | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  13. * | GNU General Public License for more details.
  14. * |
  15. * | You should have received a copy of the GNU General Public License
  16. * | along with this program. If not, see <http://www.gnu.org/licenses/>.
  17. * |----------------------------------------------------------------------
  18. */
  19. #include "rtc.h"
  20. /* Private macros */
  21. /* Internal status registers for RTC */
  22. #define RTC_STATUS_REG RTC_BKP_DR19 /* Status Register */
  23. #define RTC_STATUS_INIT_OK 0x1234 /* RTC initialised */
  24. #define RTC_STATUS_TIME_OK 0x4321 /* RTC time OK */
  25. #define RTC_STATUS_ZERO 0x0000
  26. /* Internal RTC defines */
  27. #define TM_RTC_LEAP_YEAR(year) ((((year) % 4 == 0) && ((year) % 100 != 0)) || ((year) % 400 == 0))
  28. #define TM_RTC_DAYS_IN_YEAR(x) TM_RTC_LEAP_YEAR(x) ? 366 : 365
  29. #define TM_RTC_OFFSET_YEAR 1970
  30. #define TM_RTC_SECONDS_PER_DAY 86400
  31. #define TM_RTC_SECONDS_PER_HOUR 3600
  32. #define TM_RTC_SECONDS_PER_MINUTE 60
  33. #define TM_RTC_BCD2BIN(x) ((((x) >> 4) & 0x0F) * 10 + ((x) & 0x0F))
  34. #define TM_RTC_CHAR2NUM(x) ((x) - '0')
  35. #define TM_RTC_CHARISNUM(x) ((x) >= '0' && (x) <= '9')
  36. /* Internal functions */
  37. void TM_RTC_Config(TM_RTC_ClockSource_t source);
  38. /* Default RTC status */
  39. uint32_t TM_RTC_Status = RTC_STATUS_ZERO;
  40. /* RTC declarations */
  41. RTC_TimeTypeDef RTC_TimeStruct;
  42. RTC_InitTypeDef RTC_InitStruct;
  43. RTC_DateTypeDef RTC_DateStruct;
  44. NVIC_InitTypeDef NVIC_InitStruct;
  45. EXTI_InitTypeDef EXTI_InitStruct;
  46. RTC_InitTypeDef RTC_InitStructure;
  47. RTC_TimeTypeDef RTC_TimeStructure;
  48. RTC_DateTypeDef RTC_DateStructure;
  49. #define RTC_CLOCK_SOURCE_LSE /* LSE used as RTC source clock */
  50. #define FIRST_DATA 0x32F2
  51. #define RTC_BKP_DR_NUMBER 0x14
  52. __IO uint32_t uwAsynchPrediv = 0;
  53. __IO uint32_t uwSynchPrediv = 0;
  54. __IO uint32_t uwTimeDisplay = 0;
  55. uint32_t uwErrorIndex = 0;
  56. uint32_t uwIndex = 0;
  57. uint32_t aBKPDataReg[RTC_BKP_DR_NUMBER] =
  58. {
  59. RTC_BKP_DR0, RTC_BKP_DR1, RTC_BKP_DR2,
  60. RTC_BKP_DR3, RTC_BKP_DR4, RTC_BKP_DR5,
  61. RTC_BKP_DR6, RTC_BKP_DR7, RTC_BKP_DR8,
  62. RTC_BKP_DR9, RTC_BKP_DR10, RTC_BKP_DR11,
  63. RTC_BKP_DR12, RTC_BKP_DR13, RTC_BKP_DR14,
  64. RTC_BKP_DR15, RTC_BKP_DR16, RTC_BKP_DR17,
  65. RTC_BKP_DR18, RTC_BKP_DR19
  66. };
  67. /* Days in a month */
  68. uint8_t TM_RTC_Months[2][12] = {
  69. {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}, /* Not leap year */
  70. {31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31} /* Leap year */
  71. };
  72. /**
  73. * @brief Writes data to all Backup data registers.
  74. * @param FirstBackupData: data to write to first backup data register.
  75. * @retval None
  76. */
  77. static void WriteToBackupReg(uint16_t FirstBackupData)
  78. {
  79. uint32_t index = 0;
  80. for (index = 0; index < RTC_BKP_DR_NUMBER; index++)
  81. {
  82. RTC_WriteBackupRegister(aBKPDataReg[index], FirstBackupData + (index * 0x5A));
  83. }
  84. }
  85. uint32_t TM_RTC_Init(TM_RTC_ClockSource_t source)
  86. {
  87. uint32_t status;
  88. uint8_t stat = 1;
  89. TM_RTC_t datatime;
  90. /* Enable PWR peripheral clock */
  91. RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);
  92. /* Allow access to BKP Domain */
  93. PWR_BackupAccessCmd(ENABLE);
  94. /* Get RTC status */
  95. status = RTC_ReadBackupRegister(RTC_STATUS_REG);
  96. if (status == RTC_STATUS_TIME_OK)
  97. {
  98. TM_RTC_Status = RTC_STATUS_TIME_OK;
  99. /* Start internal clock if we choose internal clock */
  100. if (source == TM_RTC_ClockSource_Internal)
  101. TM_RTC_Config(TM_RTC_ClockSource_Internal);
  102. /* Wait for RTC APB registers synchronisation (needed after start-up from Reset) */
  103. RTC_WaitForSynchro();
  104. /* Clear interrupt flags */
  105. RTC_ClearITPendingBit(RTC_IT_WUT);
  106. EXTI->PR = 0x00400000;
  107. /* Get date and time */
  108. TM_RTC_GetDateTime(&datatime, TM_RTC_Format_BIN);
  109. }
  110. else if (status == RTC_STATUS_INIT_OK)
  111. {
  112. TM_RTC_Status = RTC_STATUS_INIT_OK;
  113. /* Start internal clock if we choose internal clock */
  114. if (source == TM_RTC_ClockSource_Internal)
  115. TM_RTC_Config(TM_RTC_ClockSource_Internal);
  116. /* Wait for RTC APB registers synchronisation (needed after start-up from Reset) */
  117. RTC_WaitForSynchro();
  118. /* Clear interrupt flags */
  119. RTC_ClearITPendingBit(RTC_IT_WUT);
  120. EXTI->PR = 0x00400000;
  121. /* Get date and time */
  122. //TM_RTC_GetDateTime(&datatime, TM_RTC_Format_BIN);
  123. }
  124. else
  125. {
  126. TM_RTC_Status = RTC_STATUS_ZERO;
  127. /* Return status = 0 -> RTC Never initialized before */
  128. stat = RTC_STATUS_ZERO;
  129. /* Config RTC */
  130. TM_RTC_Config(source);
  131. /* Set date and time */
  132. datatime.date = 1;
  133. datatime.day = 1;
  134. datatime.month = 1;
  135. datatime.year = 0;
  136. datatime.hours = 0;
  137. datatime.minutes = 0;
  138. datatime.seconds = 0;
  139. /* Set date and time */
  140. TM_RTC_SetDateTime(&datatime, TM_RTC_Format_BIN);
  141. /* Initialized OK */
  142. TM_RTC_Status = RTC_STATUS_INIT_OK;
  143. }
  144. /* If first time initialized */
  145. if (stat == RTC_STATUS_ZERO)
  146. return 0;
  147. return TM_RTC_Status;
  148. }
  149. void TM_RTC_SetDataTimeUnix(uint32_t unixTime)
  150. {
  151. TM_RTC_t data;
  152. TM_RTC_GetDateTimeFromUnix(&data, unixTime);
  153. TM_RTC_SetDateTime(&data, TM_RTC_Format_BIN);
  154. }
  155. /**
  156. * @brief Кореектировака времени.
  157. * @param Часовой пояс
  158. * @retval
  159. */
  160. void TM_RTC_Correction(float utc)
  161. {
  162. TM_RTC_t data;
  163. TM_RTC_t newData;
  164. int utcSec;
  165. uint32_t unixTime;
  166. /* Получаем текущее время */
  167. TM_RTC_GetDateTime(&data, TM_RTC_Format_BIN);
  168. /* Рассчитываем поправку */
  169. utcSec = (int)(3600.0*utc);
  170. unixTime = data.unix + utcSec;
  171. /* Устанавливаем новое время */
  172. TM_RTC_GetDateTimeFromUnix(&newData, unixTime);
  173. TM_RTC_SetDateTime(&newData, TM_RTC_Format_BIN);
  174. }
  175. TM_RTC_Result_t TM_RTC_SetDateTime(TM_RTC_t* data, TM_RTC_Format_t format) {
  176. TM_RTC_t tmp;
  177. /* Check date and time validation */
  178. if (format == TM_RTC_Format_BCD) {
  179. tmp.date = TM_RTC_BCD2BIN(data->date);
  180. tmp.month = TM_RTC_BCD2BIN(data->month);
  181. tmp.year = TM_RTC_BCD2BIN(data->year);
  182. tmp.hours = TM_RTC_BCD2BIN(data->hours);
  183. tmp.minutes = TM_RTC_BCD2BIN(data->minutes);
  184. tmp.seconds = TM_RTC_BCD2BIN(data->seconds);
  185. tmp.day = TM_RTC_BCD2BIN(data->day);
  186. } else {
  187. tmp.date = data->date;
  188. tmp.month = data->month;
  189. tmp.year = data->year;
  190. tmp.hours = data->hours;
  191. tmp.minutes = data->minutes;
  192. tmp.seconds = data->seconds;
  193. tmp.day = data->day;
  194. }
  195. /* Check year and month */
  196. if (
  197. tmp.year > 99 ||
  198. tmp.month == 0 ||
  199. tmp.month > 12 ||
  200. tmp.date == 0 ||
  201. tmp.date > TM_RTC_Months[TM_RTC_LEAP_YEAR(2000 + tmp.year) ? 1 : 0][tmp.month - 1] ||
  202. tmp.hours > 23 ||
  203. tmp.minutes > 59 ||
  204. tmp.seconds > 59 ||
  205. tmp.day == 0 ||
  206. tmp.day > 7
  207. ) {
  208. /* Invalid date */
  209. return TM_RTC_Result_Error;
  210. }
  211. /* Fill time */
  212. RTC_TimeStruct.RTC_Hours = data->hours;
  213. RTC_TimeStruct.RTC_Minutes = data->minutes;
  214. RTC_TimeStruct.RTC_Seconds = data->seconds;
  215. /* Fill date */
  216. RTC_DateStruct.RTC_Date = data->date;
  217. RTC_DateStruct.RTC_Month = data->month;
  218. RTC_DateStruct.RTC_Year = data->year;
  219. RTC_DateStruct.RTC_WeekDay = data->day;
  220. /* Set the RTC time base to 1s and hours format to 24h */
  221. RTC_InitStruct.RTC_HourFormat = RTC_HourFormat_24;
  222. RTC_InitStruct.RTC_AsynchPrediv = RTC_ASYNC_PREDIV;
  223. RTC_InitStruct.RTC_SynchPrediv = RTC_SYNC_PREDIV;
  224. RTC_Init(&RTC_InitStruct);
  225. /* Set time */
  226. if (format == TM_RTC_Format_BCD) {
  227. RTC_SetTime(RTC_Format_BCD, &RTC_TimeStruct);
  228. } else {
  229. RTC_SetTime(RTC_Format_BIN, &RTC_TimeStruct);
  230. }
  231. /* Set date */
  232. if (format == TM_RTC_Format_BCD) {
  233. RTC_SetDate(RTC_Format_BCD, &RTC_DateStruct);
  234. } else {
  235. RTC_SetDate(RTC_Format_BIN, &RTC_DateStruct);
  236. }
  237. if (TM_RTC_Status != RTC_STATUS_ZERO) {
  238. /* Write backup registers */
  239. RTC_WriteBackupRegister(RTC_STATUS_REG, RTC_STATUS_TIME_OK);
  240. }
  241. /* Return OK */
  242. return TM_RTC_Result_Ok;
  243. }
  244. TM_RTC_Result_t TM_RTC_SetDateTimeString(char* str) {
  245. TM_RTC_t tmp;
  246. uint8_t i = 0;
  247. /* Get date */
  248. tmp.date = 0;
  249. while (TM_RTC_CHARISNUM(*(str + i))) {
  250. tmp.date = tmp.date * 10 + TM_RTC_CHAR2NUM(*(str + i));
  251. i++;
  252. }
  253. i++;
  254. /* Get month */
  255. tmp.month = 0;
  256. while (TM_RTC_CHARISNUM(*(str + i))) {
  257. tmp.month = tmp.month * 10 + TM_RTC_CHAR2NUM(*(str + i));
  258. i++;
  259. }
  260. i++;
  261. /* Get year */
  262. tmp.year = 0;
  263. while (TM_RTC_CHARISNUM(*(str + i))) {
  264. tmp.year = tmp.year * 10 + TM_RTC_CHAR2NUM(*(str + i));
  265. i++;
  266. }
  267. i++;
  268. /* Get day in a week */
  269. tmp.day = 0;
  270. while (TM_RTC_CHARISNUM(*(str + i))) {
  271. tmp.day = tmp.day * 10 + TM_RTC_CHAR2NUM(*(str + i));
  272. i++;
  273. }
  274. i++;
  275. /* Get hours */
  276. tmp.hours = 0;
  277. while (TM_RTC_CHARISNUM(*(str + i))) {
  278. tmp.hours = tmp.hours * 10 + TM_RTC_CHAR2NUM(*(str + i));
  279. i++;
  280. }
  281. i++;
  282. /* Get minutes */
  283. tmp.minutes = 0;
  284. while (TM_RTC_CHARISNUM(*(str + i))) {
  285. tmp.minutes = tmp.minutes * 10 + TM_RTC_CHAR2NUM(*(str + i));
  286. i++;
  287. }
  288. i++;
  289. /* Get seconds */
  290. tmp.seconds = 0;
  291. while (TM_RTC_CHARISNUM(*(str + i))) {
  292. tmp.seconds = tmp.seconds * 10 + TM_RTC_CHAR2NUM(*(str + i));
  293. i++;
  294. }
  295. i++;
  296. /* Return status from set date time function */
  297. return TM_RTC_SetDateTime(&tmp, TM_RTC_Format_BIN);
  298. }
  299. void TM_RTC_GetDateTime(TM_RTC_t* data, TM_RTC_Format_t format) {
  300. uint32_t unix;
  301. /* Get time */
  302. if (format == TM_RTC_Format_BIN) {
  303. RTC_GetTime(RTC_Format_BIN, &RTC_TimeStruct);
  304. } else {
  305. RTC_GetTime(RTC_Format_BCD, &RTC_TimeStruct);
  306. }
  307. /* Format hours */
  308. data->hours = RTC_TimeStruct.RTC_Hours;
  309. data->minutes = RTC_TimeStruct.RTC_Minutes;
  310. data->seconds = RTC_TimeStruct.RTC_Seconds;
  311. /* Get subseconds */
  312. data->subseconds = RTC->SSR;
  313. /* Get date */
  314. if (format == TM_RTC_Format_BIN) {
  315. RTC_GetDate(RTC_Format_BIN, &RTC_DateStruct);
  316. } else {
  317. RTC_GetDate(RTC_Format_BCD, &RTC_DateStruct);
  318. }
  319. /* Format date */
  320. data->year = RTC_DateStruct.RTC_Year;
  321. data->month = RTC_DateStruct.RTC_Month;
  322. data->date = RTC_DateStruct.RTC_Date;
  323. data->day = RTC_DateStruct.RTC_WeekDay;
  324. /* Calculate unix offset */
  325. unix = TM_RTC_GetUnixTimeStamp(data);
  326. data->unix = unix;
  327. }
  328. uint8_t TM_RTC_GetDaysInMonth(uint8_t month, uint8_t year) {
  329. /* Check input data */
  330. if (
  331. month == 0 ||
  332. month > 12
  333. ) {
  334. /* Error */
  335. return 0;
  336. }
  337. /* Return days in month */
  338. return TM_RTC_Months[TM_RTC_LEAP_YEAR(2000 + year) ? 1 : 0][month - 1];
  339. }
  340. uint16_t TM_RTC_GetDaysInYear(uint8_t year) {
  341. /* Return days in year */
  342. return TM_RTC_DAYS_IN_YEAR(2000 + year);
  343. }
  344. void TM_RTC_Config(TM_RTC_ClockSource_t source) {
  345. if (source == TM_RTC_ClockSource_Internal) {
  346. /* Enable the LSI OSC */
  347. RCC_LSICmd(ENABLE);
  348. /* Wait till LSI is ready */
  349. while (RCC_GetFlagStatus(RCC_FLAG_LSIRDY) == RESET);
  350. /* Select the RTC Clock Source */
  351. RCC_RTCCLKConfig(RCC_RTCCLKSource_LSI);
  352. } else if (source == TM_RTC_ClockSource_External) {
  353. /* Enable the LSE OSC */
  354. RCC_LSEConfig(RCC_LSE_ON);
  355. /* Wait till LSE is ready */
  356. while (RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET);
  357. /* Select the RTC Clock Source */
  358. RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);
  359. }
  360. /* Enable the RTC Clock */
  361. RCC_RTCCLKCmd(ENABLE);
  362. /* Wait for register synchronization */
  363. RTC_WaitForSynchro();
  364. /* Write status */
  365. RTC_WriteBackupRegister(RTC_STATUS_REG, RTC_STATUS_INIT_OK);
  366. }
  367. void TM_RTC_Interrupts(TM_RTC_Int_t int_value) {
  368. uint32_t int_val;
  369. /* Clear pending bit */
  370. EXTI->PR = 0x00400000;
  371. /* Disable wakeup interrupt */
  372. RTC_WakeUpCmd(DISABLE);
  373. /* Disable RTC interrupt flag */
  374. RTC_ITConfig(RTC_IT_WUT, DISABLE);
  375. /* NVIC init for RTC */
  376. NVIC_InitStruct.NVIC_IRQChannel = RTC_WKUP_IRQn;
  377. NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = RTC_PRIORITY;
  378. NVIC_InitStruct.NVIC_IRQChannelSubPriority = RTC_WAKEUP_SUBPRIORITY;
  379. NVIC_InitStruct.NVIC_IRQChannelCmd = DISABLE;
  380. NVIC_Init(&NVIC_InitStruct);
  381. /* RTC connected to EXTI_Line22 */
  382. EXTI_InitStruct.EXTI_Line = EXTI_Line22;
  383. EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
  384. EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
  385. EXTI_InitStruct.EXTI_LineCmd = DISABLE;
  386. EXTI_Init(&EXTI_InitStruct);
  387. if (int_value != TM_RTC_Int_Disable) {
  388. /* Enable NVIC */
  389. NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
  390. NVIC_Init(&NVIC_InitStruct);
  391. /* Enable EXT1 interrupt */
  392. EXTI_InitStruct.EXTI_LineCmd = ENABLE;
  393. EXTI_Init(&EXTI_InitStruct);
  394. /* First disable wake up command */
  395. RTC_WakeUpCmd(DISABLE);
  396. if (int_value == TM_RTC_Int_60s) {
  397. int_val = 0x3BFFF; /* 60 seconds = 60 * 4096 / 1 = 245760 */
  398. } else if (int_value == TM_RTC_Int_30s) {
  399. int_val = 0x1DFFF; /* 30 seconds */
  400. } else if (int_value == TM_RTC_Int_15s) {
  401. int_val = 0xEFFF; /* 15 seconds */
  402. } else if (int_value == TM_RTC_Int_10s) {
  403. int_val = 0x9FFF; /* 10 seconds */
  404. } else if (int_value == TM_RTC_Int_5s) {
  405. int_val = 0x4FFF; /* 5 seconds */
  406. } else if (int_value == TM_RTC_Int_2s) {
  407. int_val = 0x1FFF; /* 2 seconds */
  408. } else if (int_value == TM_RTC_Int_1s) {
  409. int_val = 0x0FFF; /* 1 second */
  410. } else if (int_value == TM_RTC_Int_500ms) {
  411. int_val = 0x7FF; /* 500 ms */
  412. } else if (int_value == TM_RTC_Int_250ms) {
  413. int_val = 0x3FF; /* 250 ms */
  414. } else if (int_value == TM_RTC_Int_125ms) {
  415. int_val = 0x1FF; /* 125 ms */
  416. }
  417. /* Clock divided by 8, 32768 / 8 = 4096 */
  418. /* 4096 ticks for 1second interrupt */
  419. RTC_WakeUpClockConfig(RTC_WakeUpClock_RTCCLK_Div8);
  420. /* Set RTC wakeup counter */
  421. RTC_SetWakeUpCounter(int_val);
  422. /* Enable wakeup interrupt */
  423. RTC_ITConfig(RTC_IT_WUT, ENABLE);
  424. /* Enable wakeup command */
  425. RTC_WakeUpCmd(ENABLE);
  426. }
  427. }
  428. uint32_t TM_RTC_GetUnixTimeStamp(TM_RTC_t* data) {
  429. uint32_t days = 0, seconds = 0;
  430. uint16_t i;
  431. uint16_t year = (uint16_t) (data->year + 2000);
  432. /* Year is below offset year */
  433. if (year < TM_RTC_OFFSET_YEAR) {
  434. return 0;
  435. }
  436. /* Days in back years */
  437. for (i = TM_RTC_OFFSET_YEAR; i < year; i++) {
  438. days += TM_RTC_DAYS_IN_YEAR(i);
  439. }
  440. /* Days in current year */
  441. for (i = 1; i < data->month; i++) {
  442. days += TM_RTC_Months[TM_RTC_LEAP_YEAR(year)][i - 1];
  443. }
  444. /* Day starts with 1 */
  445. days += data->date - 1;
  446. seconds = days * TM_RTC_SECONDS_PER_DAY;
  447. seconds += data->hours * TM_RTC_SECONDS_PER_HOUR;
  448. seconds += data->minutes * TM_RTC_SECONDS_PER_MINUTE;
  449. seconds += data->seconds;
  450. /* seconds = days * 86400; */
  451. return seconds;
  452. }
  453. void TM_RTC_GetDateTimeFromUnix(TM_RTC_t* data, uint32_t unix) {
  454. uint16_t year;
  455. /* Store unix time to unix in struct */
  456. data->unix = unix;
  457. /* Get seconds from unix */
  458. data->seconds = unix % 60;
  459. /* Go to minutes */
  460. unix /= 60;
  461. /* Get minutes */
  462. data->minutes = unix % 60;
  463. /* Go to hours */
  464. unix /= 60;
  465. /* Get hours */
  466. data->hours = unix % 24;
  467. /* Go to days */
  468. unix /= 24;
  469. /* Get week day */
  470. /* Monday is day one */
  471. data->day = (unix + 3) % 7 + 1;
  472. /* Get year */
  473. year = 1970;
  474. while (1) {
  475. if (TM_RTC_LEAP_YEAR(year)) {
  476. if (unix >= 366) {
  477. unix -= 366;
  478. } else {
  479. break;
  480. }
  481. } else if (unix >= 365) {
  482. unix -= 365;
  483. } else {
  484. break;
  485. }
  486. year++;
  487. }
  488. /* Get year in xx format */
  489. data->year = (uint8_t) (year - 2000);
  490. /* Get month */
  491. for (data->month = 0; data->month < 12; data->month++) {
  492. if (TM_RTC_LEAP_YEAR(year) && unix >= (uint32_t)TM_RTC_Months[1][data->month]) {
  493. unix -= TM_RTC_Months[1][data->month];
  494. } else if (unix >= (uint32_t)TM_RTC_Months[0][data->month]) {
  495. unix -= TM_RTC_Months[0][data->month];
  496. } else {
  497. break;
  498. }
  499. }
  500. /* Get month */
  501. /* Month starts with 1 */
  502. data->month++;
  503. /* Get date */
  504. /* Date starts with 1 */
  505. data->date = unix + 1;
  506. }
  507. void TM_RTC_SetAlarm(TM_RTC_Alarm_t Alarm, TM_RTC_AlarmTime_t* DataTime, TM_RTC_Format_t format) {
  508. RTC_AlarmTypeDef RTC_AlarmStruct;
  509. /* Disable alarm first */
  510. TM_RTC_DisableAlarm(Alarm);
  511. /* Set RTC alarm settings */
  512. /* Set alarm time */
  513. RTC_AlarmStruct.RTC_AlarmTime.RTC_Hours = DataTime->hours;
  514. RTC_AlarmStruct.RTC_AlarmTime.RTC_Minutes = DataTime->minutes;
  515. RTC_AlarmStruct.RTC_AlarmTime.RTC_Seconds = DataTime->seconds;
  516. RTC_AlarmStruct.RTC_AlarmMask = RTC_AlarmMask_DateWeekDay;
  517. /* Alarm type is every week the same day in a week */
  518. if (DataTime->alarmtype == TM_RTC_AlarmType_DayInWeek) {
  519. /* Alarm trigger every week the same day in a week */
  520. RTC_AlarmStruct.RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_WeekDay;
  521. /* Week day can be between 1 and 7 */
  522. if (DataTime->day == 0) {
  523. RTC_AlarmStruct.RTC_AlarmDateWeekDay = 1;
  524. } else if (DataTime->day > 7) {
  525. RTC_AlarmStruct.RTC_AlarmDateWeekDay = 7;
  526. } else {
  527. RTC_AlarmStruct.RTC_AlarmDateWeekDay = DataTime->day;
  528. }
  529. } else { /* Alarm type is every month the same day */
  530. /* Alarm trigger every month the same day in a month */
  531. RTC_AlarmStruct.RTC_AlarmDateWeekDaySel = RTC_AlarmDateWeekDaySel_Date;
  532. /* Month day can be between 1 and 31 */
  533. if (DataTime->day == 0) {
  534. RTC_AlarmStruct.RTC_AlarmDateWeekDay = 1;
  535. } else if (DataTime->day > 31) {
  536. RTC_AlarmStruct.RTC_AlarmDateWeekDay = 31;
  537. } else {
  538. RTC_AlarmStruct.RTC_AlarmDateWeekDay = DataTime->day;
  539. }
  540. }
  541. switch (Alarm) {
  542. case TM_RTC_Alarm_A:
  543. /* Configure the RTC Alarm A */
  544. RTC_SetAlarm(format, RTC_Alarm_A, &RTC_AlarmStruct);
  545. /* Enable Alarm A */
  546. RTC_AlarmCmd(RTC_Alarm_A, ENABLE);
  547. /* Enable Alarm A interrupt */
  548. RTC_ITConfig(RTC_IT_ALRA, ENABLE);
  549. /* Clear Alarm A pending bit */
  550. RTC_ClearFlag(RTC_IT_ALRA);
  551. break;
  552. case TM_RTC_Alarm_B:
  553. /* Configure the RTC Alarm B */
  554. RTC_SetAlarm(format, RTC_Alarm_B, &RTC_AlarmStruct);
  555. /* Enable Alarm B */
  556. RTC_AlarmCmd(RTC_Alarm_B, ENABLE);
  557. /* Enable Alarm B interrupt */
  558. RTC_ITConfig(RTC_IT_ALRB, ENABLE);
  559. /* Clear Alarm B pending bit */
  560. RTC_ClearFlag(RTC_IT_ALRB);
  561. break;
  562. default:
  563. break;
  564. }
  565. }
  566. void TM_RTC_DisableAlarm(TM_RTC_Alarm_t Alarm) {
  567. switch (Alarm) {
  568. case TM_RTC_Alarm_A:
  569. /* Disable Alarm A */
  570. RTC_AlarmCmd(RTC_Alarm_A, DISABLE);
  571. /* Disable Alarm A interrupt */
  572. RTC_ITConfig(RTC_IT_ALRA, DISABLE);
  573. /* Clear Alarm A pending bit */
  574. RTC_ClearFlag(RTC_IT_ALRA);
  575. break;
  576. case TM_RTC_Alarm_B:
  577. /* Disable Alarm B */
  578. RTC_AlarmCmd(RTC_Alarm_B, DISABLE);
  579. /* Disable Alarm B interrupt */
  580. RTC_ITConfig(RTC_IT_ALRB, DISABLE);
  581. /* Clear Alarm B pending bit */
  582. RTC_ClearFlag(RTC_IT_ALRB);
  583. break;
  584. default:
  585. break;
  586. }
  587. /* Clear RTC Alarm pending bit */
  588. EXTI->PR = 0x00020000;
  589. /* Configure EXTI 17 as interrupt */
  590. EXTI_InitStruct.EXTI_Line = EXTI_Line17;
  591. EXTI_InitStruct.EXTI_Mode = EXTI_Mode_Interrupt;
  592. EXTI_InitStruct.EXTI_Trigger = EXTI_Trigger_Rising;
  593. EXTI_InitStruct.EXTI_LineCmd = ENABLE;
  594. /* Initialite Alarm EXTI interrupt */
  595. EXTI_Init(&EXTI_InitStruct);
  596. /* Configure the RTC Alarm Interrupt */
  597. NVIC_InitStruct.NVIC_IRQChannel = RTC_Alarm_IRQn;
  598. NVIC_InitStruct.NVIC_IRQChannelPreemptionPriority = RTC_PRIORITY;
  599. NVIC_InitStruct.NVIC_IRQChannelSubPriority = RTC_ALARM_SUBPRIORITY;
  600. NVIC_InitStruct.NVIC_IRQChannelCmd = ENABLE;
  601. /* Initialize RTC Alarm Interrupt */
  602. NVIC_Init(&NVIC_InitStruct);
  603. }
  604. void TM_RTC_WriteBackupRegister(uint8_t location, uint32_t value) {
  605. /* Check input, 0 to 18 registers are allowed */
  606. if (location > 18) {
  607. return;
  608. }
  609. /* Write data to backup register */
  610. *(uint32_t *)((&RTC->BKP0R) + 4 * location) = value;
  611. }
  612. uint32_t TM_RTC_ReadBackupRegister(uint8_t location){
  613. /* Check input, 0 to 18 registers are allowed */
  614. if (location > 18) {
  615. return 0;
  616. }
  617. /* Read data from backup register */
  618. return *(uint32_t *)((&RTC->BKP0R) + 4 * location);
  619. }
  620. /* Callbacks */
  621. __weak void TM_RTC_RequestHandler(void) {
  622. /* If user needs this function, then they should be defined separatelly in your project */
  623. }
  624. __weak void TM_RTC_AlarmAHandler(void) {
  625. /* If user needs this function, then they should be defined separatelly in your project */
  626. }
  627. __weak void TM_RTC_AlarmBHandler(void) {
  628. /* If user needs this function, then they should be defined separatelly in your project */
  629. }
  630. /* Private RTC IRQ handlers */
  631. void RTC_WKUP_IRQHandler(void) {
  632. /* Check for RTC interrupt */
  633. if (RTC_GetITStatus(RTC_IT_WUT) != RESET) {
  634. /* Clear interrupt flags */
  635. RTC_ClearITPendingBit(RTC_IT_WUT);
  636. /* Call user function */
  637. TM_RTC_RequestHandler();
  638. }
  639. /* Clear EXTI line 22 bit */
  640. EXTI->PR = 0x00400000;
  641. }
  642. void RTC_Alarm_IRQHandler(void) {
  643. /* RTC Alarm A check */
  644. if (RTC_GetITStatus(RTC_IT_ALRA) != RESET) {
  645. /* Clear RTC Alarm A interrupt flag */
  646. RTC_ClearITPendingBit(RTC_IT_ALRA);
  647. /* Call user function for Alarm A */
  648. TM_RTC_AlarmAHandler();
  649. }
  650. /* RTC Alarm B check */
  651. if (RTC_GetITStatus(RTC_IT_ALRB) != RESET) {
  652. /* Clear RTC Alarm A interrupt flag */
  653. RTC_ClearITPendingBit(RTC_IT_ALRB);
  654. /* Call user function for Alarm B */
  655. TM_RTC_AlarmBHandler();
  656. }
  657. /* Clear EXTI line 17 bit */
  658. EXTI->PR = 0x00020000;
  659. }
  660. /**
  661. * @brief Установливает время срабатывания профилактики сульфатации для отладки
  662. * @retval
  663. */
  664. void RTC_SetDebugProfTime(void)
  665. {
  666. TM_RTC_t currentTime;
  667. uint32_t unixTime;
  668. TM_RTC_GetDateTime(&currentTime, TM_RTC_Format_BIN);
  669. unixTime = TM_RTC_GetUnixTimeStamp(&currentTime);
  670. unixTime += 30;
  671. TM_RTC_WriteBackupRegister(RTC_BKP_DR0, unixTime);
  672. }
  673. /**
  674. * @brief Установливает время срабатывания профилактики сульфатации
  675. */
  676. void RTC_SetProfTime(char *str)
  677. {
  678. TM_RTC_t tmp;
  679. uint32_t unixTime;
  680. uint8_t i = 0;
  681. /* Get date */
  682. tmp.date = 0;
  683. while (TM_RTC_CHARISNUM(*(str + i))) {
  684. tmp.date = tmp.date * 10 + TM_RTC_CHAR2NUM(*(str + i));
  685. i++;
  686. }
  687. i++;
  688. /* Get month */
  689. tmp.month = 0;
  690. while (TM_RTC_CHARISNUM(*(str + i))) {
  691. tmp.month = tmp.month * 10 + TM_RTC_CHAR2NUM(*(str + i));
  692. i++;
  693. }
  694. //i++;
  695. i+=3;
  696. /* Get year */
  697. tmp.year = 0;
  698. while (TM_RTC_CHARISNUM(*(str + i))) {
  699. tmp.year = tmp.year * 10 + TM_RTC_CHAR2NUM(*(str + i));
  700. i++;
  701. }
  702. i++;
  703. i++;
  704. /* Get hours */
  705. tmp.hours = 0;
  706. while (TM_RTC_CHARISNUM(*(str + i))) {
  707. tmp.hours = tmp.hours * 10 + TM_RTC_CHAR2NUM(*(str + i));
  708. i++;
  709. }
  710. i++;
  711. /* Get minutes */
  712. tmp.minutes = 0;
  713. while (TM_RTC_CHARISNUM(*(str + i))) {
  714. tmp.minutes = tmp.minutes * 10 + TM_RTC_CHAR2NUM(*(str + i));
  715. i++;
  716. }
  717. i++;
  718. /* Get seconds */
  719. tmp.seconds = 0;
  720. /* Устанавливаем +1 для профилактики */
  721. tmp.year += 1;
  722. unixTime = TM_RTC_GetUnixTimeStamp(&tmp);
  723. TM_RTC_WriteBackupRegister(RTC_BKP_DR0, unixTime);
  724. }
  725. /**
  726. * @brief
  727. * @retval
  728. */
  729. uint32_t RTC_GetUnixTime(void)
  730. {
  731. TM_RTC_t currentTime;
  732. TM_RTC_GetDateTime(&currentTime, TM_RTC_Format_BIN);
  733. return TM_RTC_GetUnixTimeStamp(&currentTime);
  734. }