/** * @author Tilen Majerle * @email tilen@majerle.eu * @website http://stm32f4-discovery.com * @link http://stm32f4-discovery.com/2014/07/library-19-use-internal-rtc-on-stm32f4xx-devices/ * @version 1.7.1 * @ide Keil uVision * @license GNU GPL v3 * @brief Internal RTC library for STM32F4xx devices * @verbatim ---------------------------------------------------------------------- Copyright (C) Tilen Majerle, 2015 This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . ---------------------------------------------------------------------- @endverbatim */ #ifndef TM_RTC_H #define TM_RTC_H 171 /* C++ detection */ #ifdef __cplusplus extern C { #endif /** * @addtogroup TM_STM32F4xx_Libraries * @{ */ /** * @defgroup TM_RTC * @brief RTC Library for STM32F4xx devices - http://stm32f4-discovery.com/2014/07/library-19-use-internal-rtc-on-stm32f4xx-devices/ * @{ * * \par Features * @verbatim - Support Internal or external clock source - PC14 and PC15 pins are used for external crystal oscillator - STM32F4/429 Discovery does not have RTC crystal onboard. Check board's manual on how to set it up - Support wakeup interrupt - Support to set 2 internal alarms to trigger interrupts - They can also wake up STM32F4 from any low power mode - Get seconds from 01.01.1970 00:00:00 - Get readable time from seconds from 01.01.1970 00:00:00 - Support to save/get data in binary or BCD format - Support for read/write data to/from RTC backup registers - Support for subsecond - Support to write data in string format - Date and time are checked before saved for valid input data - Get days in month and year @endverbatim * * \par Pinout for RTC external 32768Hz crystal * @verbatim STM32F4XX Oscillator Description PC14 OSC1 Oscillator terminal 1 PC15 OSC2 Oscillator terminal 2 @endverbatim * * \par Changelog * @verbatim Version 1.7.1 - March 25, 2015 - Fixed issue with RTC wakeup interrupts Version 1.7 - March 15, 2015 - Added support for read/write data to/from RTC backup registers Version 1.6 - February 17, 2015 - Created typedef TM_RTC_t from TM_RTC_Time_t Version 1.5 - December 21, 2014 - Added 2 new functions: TM_RTC_GetDaysInMonth: returns number of days in specific month and year TM_RTC_GetDaysInYear: returns number of days in specific year Version 1.4 - December 21, 2014 - TM_RTC_SetDateTime now checks for valid input data before save - Added function TM_RTC_SetDateTimeString which allows you to set your date and time using string format Version 1.3 - December 03, 2014 - Fixed bug when reading month in december was set to 0 Version 1.2 - October 27, 2014 - Added support to read subseconds from time - This can be used for stopwatch Version 1.1 - October 20, 2014 - Added support for Alarm set Version 1.0.2 - September 24, 2014 - TM_RTC_RequestHandler function has now "__weak" attribute to prevent errors, if function is not implemented by user Version 1.0.1 - September 01, 2014 - Date to unix convert bug fix Version 1.0 - First release @endverbatim * * \par Dependencies * @verbatim - STM32F4xx - STM32F4xx RCC - STM32F4xx RTC - STM32F4xx PWR - STM32F4xx EXTI - MISC - defines.h - attributes.h @endverbatim */ #include "stm32f4xx.h" #include "attributes.h" /** * @defgroup TM_RTC_Macros * @brief Library defines * * All these settings can be overwritten in defines.h file if necessary * * @{ */ /* RTC clock is: f_clk = RTCCLK(LSI or LSE) / ((RTC_SYNC_PREDIV + 1) * (RTC_ASYNC_PREDIV + 1)) */ /* Sync pre division for clock */ #ifndef RTC_SYNC_PREDIV #define RTC_SYNC_PREDIV 0x3FF #endif /* Async pre division for clock */ #ifndef RTC_ASYNC_PREDIV #define RTC_ASYNC_PREDIV 0x1F #endif /* NVIC global Priority set */ #ifndef RTC_PRIORITY #define RTC_PRIORITY 0x04 #endif /* Sub priority for wakeup trigger */ #ifndef RTC_WAKEUP_SUBPRIORITY #define RTC_WAKEUP_SUBPRIORITY 0x00 #endif /* Sub priority for alarm trigger */ #ifndef RTC_ALARM_SUBPRIORITY #define RTC_ALARM_SUBPRIORITY 0x01 #endif /** * @} */ /** * @defgroup TM_RTC_Typedefs * @brief Library Typedefs * @{ */ /** * @brief RTC Struct for date/time */ typedef struct { uint8_t seconds; /*!< Seconds parameter, from 00 to 59 */ uint16_t subseconds; /*!< Subsecond downcounter. When it reaches zero, it's reload value is the same as @ref RTC_SYNC_PREDIV, so in our case 0x3FF = 1023, 1024 steps in one second */ uint8_t minutes; /*!< Minutes parameter, from 00 to 59 */ uint8_t hours; /*!< Hours parameter, 24Hour mode, 00 to 23 */ uint8_t day; /*!< Day in a week, from 1 to 7 */ uint8_t date; /*!< Date in a month, 1 to 31 */ uint8_t month; /*!< Month in a year, 1 to 12 */ uint8_t year; /*!< Year parameter, 00 to 99, 00 is 2000 and 99 is 2099 */ uint32_t unix; /*!< Seconds from 01.01.1970 00:00:00 */ } TM_RTC_t; /** * @brief Backward compatibility for RTC time */ typedef TM_RTC_t TM_RTC_Time_t; /** * @brief RTC Result enumeration */ typedef enum { TM_RTC_Result_Ok, /*!< Everything OK */ TM_RTC_Result_Error /*!< An error occurred */ } TM_RTC_Result_t; /** * @brief RTC date and time format */ typedef enum { TM_RTC_Format_BIN = 0x00, /*!< RTC data in binary format */ TM_RTC_Format_BCD /*!< RTC data in binary-coded decimal format */ } TM_RTC_Format_t; /** * @brief RTC Interrupt enumeration */ typedef enum { TM_RTC_Int_Disable = 0x00, /*!< Disable RTC wakeup interrupts */ TM_RTC_Int_60s, /*!< RTC Wakeup interrupt every 60 seconds */ TM_RTC_Int_30s, /*!< RTC Wakeup interrupt every 30 seconds */ TM_RTC_Int_15s, /*!< RTC Wakeup interrupt every 15 seconds */ TM_RTC_Int_10s, /*!< RTC Wakeup interrupt every 10 seconds */ TM_RTC_Int_5s, /*!< RTC Wakeup interrupt every 5 seconds */ TM_RTC_Int_2s, /*!< RTC Wakeup interrupt every 2 seconds */ TM_RTC_Int_1s, /*!< RTC Wakeup interrupt every 1 seconds */ TM_RTC_Int_500ms, /*!< RTC Wakeup interrupt every 500 milliseconds */ TM_RTC_Int_250ms, /*!< RTC Wakeup interrupt every 250 milliseconds */ TM_RTC_Int_125ms /*!< RTC Wakeup interrupt every 125 milliseconds */ } TM_RTC_Int_t; /** * @brief Select RTC clock source * @note Internal clock is not accurate and should not be used in production */ typedef enum { TM_RTC_ClockSource_Internal = 0x00, /*!< Use internal clock source for RTC (LSI oscillator) */ TM_RTC_ClockSource_External /*!< Use external clock source for RTC (LSE oscillator) */ } TM_RTC_ClockSource_t; /** * @brief RTC Alarm type */ typedef enum { TM_RTC_AlarmType_DayInWeek, /*!< Trigger alarm every day in a week, days from 1 to 7 (Monday to Sunday) */ TM_RTC_AlarmType_DayInMonth /*!< Trigger alarm every month */ } TM_RTC_AlarmType_t; /** * @brief Alarm identifier you will use for Alarm functions */ typedef enum { TM_RTC_Alarm_A = 0x00, /*!< Work with alarm A */ TM_RTC_Alarm_B /*!< Work with alarm B */ } TM_RTC_Alarm_t; /** * @brief RTC structure for alarm time */ typedef struct { TM_RTC_AlarmType_t alarmtype; /*!< Alarm type setting. @ref TM_RTC_AlarmType_t for more info */ uint8_t seconds; /*!< Alarm seconds value */ uint8_t minutes; /*!< Alarm minutes value */ uint8_t hours; /*!< Alarm hours value */ uint8_t day; /*!< Alarm day value. If you select trigger for alarm every week, then this parameter has value between 1 and 7, representing days in a week, Monday to Sunday If you select trigger for alarm every month, then this parameter has value between 1 - 31, representing days in a month. */ } TM_RTC_AlarmTime_t; /** * @} */ /** * @defgroup TM_RTC_Functions * @brief Library Functions * @{ */ void TM_RTC_SetDataTimeUnix(uint32_t unixTime); /** * @brief Кореектировака времени. */ void TM_RTC_Correction(float utc); /** * @brief Initializes RTC and starts counting * @param source. RTC Clock source @ref TM_RTC_ClockSource_t to be used for RTC * @note Internal clock source is not so accurate * @note If you reset your MCU and RTC still has power, it will count independent of MCU status * @retval Returns RTC status. * - 1: RTC has already been initialized and time is set * - 0: RTC was now initialized first time. Now you can set your first clock */ uint32_t TM_RTC_Init(TM_RTC_ClockSource_t source); /** * @brief Get number of seconds from date and time since 01.01.1970 00:00:00 * @param *data: Pointer to @ref TM_RTC_t data structure * @retval Calculated seconds from date and time since 01.01.1970 00:00:00 */ uint32_t TM_RTC_GetUnixTimeStamp(TM_RTC_t* data); /** * @brief Get formatted time from seconds till 01.01.1970 00:00:00 * It fills struct with valid data * @note Valid if year is greater or equal (>=) than 2000 * @param *data: Pointer to @ref TM_RTC_Time_t struct to store formatted data in * @param unix: Seconds from 01.01.1970 00:00:00 to calculate user friendly time * @retval None */ void TM_RTC_GetDateTimeFromUnix(TM_RTC_t* data, uint32_t unix); /** * @brief Select RTC wakeup interrupts interval * @note This function can also be used to disable interrupt * @param int_value: Look for @ref TM_RTC_Int_t for valid inputs * @retval None */ void TM_RTC_Interrupts(TM_RTC_Int_t int_value); /** * @brief Set date and time to internal RTC registers * @param *data: Pointer to filled @ref TM_RTC_t structure with date and time * @param format: Format of your structure. This parameter can be a value of @ref TM_RTC_Format_t enumeration * @retval RTC datetime status @ref TM_RTC_Result_t: * - @ref TM_RTC_Result_Ok: Date and Time set OK * - @ref TM_RTC_Result_Error: Date and time is wrong */ TM_RTC_Result_t TM_RTC_SetDateTime(TM_RTC_t* data, TM_RTC_Format_t format); /** * @brief Set date and time using string formatted date time * @note Valid string format is: dd.mm.YY.x;HH:ii:ss * - dd: date, 2 digits, decimal * - mm: month, 2 digits, decimal * - YY: year, last 2 digits, decimal * - x: day in a week: 1 digit, 1 = Monday, 7 = Sunday * - HH: hours, 24-hour mode, 2 digits, decimal * - ii: minutes, 2 digits, decimal * - ss: seconds, 2 digits, decimal * @param *str: Pointer to string with datetime format * @retval RTC datetime status @ref TM_RTC_Result_t: * - @ref TM_RTC_Result_Ok: Date and Time set OK * - @ref TM_RTC_Result_Error: Date and time is wrong */ TM_RTC_Result_t TM_RTC_SetDateTimeString(char* str); /** * @brief Get date and time from internal RTC registers * @param *data: Pointer to @ref TM_RTC_t structure to save data to * @param format: Format of your structure. This parameter can be a value of @ref TM_RTC_Format_t enumeration * @retval None */ void TM_RTC_GetDateTime(TM_RTC_t* data, TM_RTC_Format_t format); /** * @brief Get number of days in month * @note This function also detects if it is leap year and returns different number for February * @param month: Month number in year, valid numbers are 1 - 12 * @param year: Year number where you want to get days in month, last 2 digits * @retval Number of days in specific month and year */ uint8_t TM_RTC_GetDaysInMonth(uint8_t month, uint8_t year); /** * @brief Get number of days in specific year * @note This function also detects if it is leap year * @param year: Year number where you want to get days in month, last 2 digits * @retval Number of days in year */ uint16_t TM_RTC_GetDaysInYear(uint8_t year); /** * @brief Write RTC backup register value. * This method allows you to write 32bit value from backup register 0 - 18. * @note RTC has 20 backup registers where you can store data which will be available all the time RTC is running and has power. * * @note My library uses register 19 to store info about RTC settings and is not available for USER to store data there. * * @note RTC HAS to be initialized first before you can use this method. * @param location: RTC backup register location. 0 to 18 are valid * @param value: 32-bit long value to be stored in RTC backup register * @retval Value at specific RTC backup register location */ void TM_RTC_WriteBackupRegister(uint8_t location, uint32_t value); /** * @brief Read RTC backup register value. * This method allows you to read 32bit value from backup register 0 - 18. * @note RTC has 20 backup registers where you can store data which will be available all the time RTC is running and has power. * * @note My library uses register 19 to store info about RTC settings and is not available for USER to store data there. * * @note RTC HAS to be initialized first before you can use this method. * @param location: RTC backup register location. 0 to 18 are valid * @retval Value at specific RTC backup register location */ uint32_t TM_RTC_ReadBackupRegister(uint8_t location); /** * @brief Enables alarm A or alarm B * @param Alarm: Specify which alarm to set. This parameter can be a value of @ref TM_RTC_Alarm_t enumeration * @param *AlarmTime: Pointer to @ref TM_RTC_AlarmTime_t structure to get data from. * @param format: RTC date and time format. This parameter can be a value of @ref TM_RTC_Format_t enumeration. * @retval None */ void TM_RTC_SetAlarm(TM_RTC_Alarm_t Alarm, TM_RTC_AlarmTime_t* AlarmTime, TM_RTC_Format_t format); /** * @brief Disables specific alarm * @param Alarm: Select which alarm you want to disable. This parameter can be a value of @ref TM_RTC_Alarm_t enumeration * @retval None */ void TM_RTC_DisableAlarm(TM_RTC_Alarm_t Alarm); /** * @brief RTC Wakeup handler function. Called when wakeup interrupt is triggered * @note Called from my RTC library * @param None * @retval None * @note With __weak parameter to prevent link errors if not defined by user */ void TM_RTC_RequestHandler(void); /** * @brief RTC Alarm A handler function. Called when interrupt is triggered for alarm A * @note Called from my RTC library * @param None * @retval None * @note With __weak parameter to prevent link errors if not defined by user */ void TM_RTC_AlarmAHandler(void); /** * @brief RTC Alarm B handler function. Called when interrupt is triggered for alarm B. * @note Called from my RTC library * @param None * @retval None * @note With __weak parameter to prevent link errors if not defined by user */ void TM_RTC_AlarmBHandler(void); /** * @brief Установливает время срабатывания профилактики сульфатации для отладки * @retval */ void RTC_SetDebugProfTime(void); /** * @brief */ void RTC_SetProfTime(char *date); /** * @brief * @retval */ uint32_t RTC_GetUnixTime(void); /* C++ detection */ #ifdef __cplusplus } #endif #endif