├── examples ├── images │ └── minimal_connections.bmp ├── stm32f4xx_it.c └── main.c ├── LICENSE ├── README.md ├── ds3231_for_stm32_hal.h └── ds3231_for_stm32_hal.c /examples/images/minimal_connections.bmp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/eepj/stm32-ds3231/HEAD/examples/images/minimal_connections.bmp -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2020 Pan 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # DS3231_for_STM32_HAL 2 | An STM32 HAL library for the DS3231 real-time clock IC. 3 | 4 | ## Quick start 5 | ### Minimal setup 6 | ![Setup](./examples/images/minimal_connections.bmp) 7 | 8 | ### STM32CubeMX setup 9 | * In STM32CubeMX, set I2C1 to "I2C" and USART1 to "asynchronous" 10 | * Set up an external interrupt pin (say PB0) in GPIO settings, use "external interrupt mode with falling edge trigger detection" and "pull-up" settings. 11 | * Activate the external interrupt in NVIC settings by checking the corresponding box. 12 | * Connect pin 3 (INT#/SQW) of the DS3231 to this external interrupt pin. 13 | * Save and generate code. 14 | 15 | ### IDE setup 16 | * In your IDE, include [`ds3231_for_stm32_hal.h`](./ds3231_for_stm32_hal.h) and [`ds3231_for_stm32_hal.c`](./ds3231_for_stm32_hal.c). 17 | 18 | ### Main program 19 | #### Includes 20 | * In `main.c` (main program body file), include: 21 | ```c 22 | #include "ds3231_for_stm32_hal.h" 23 | ``` 24 | 25 | #### Initialization 26 | * Initialization function: 27 | ```c 28 | void DS3231_Init(I2C_HandleTypeDef *hi2c); 29 | ``` 30 | 31 | * In `main.c`, before the main loop and after the system inits, call the DS3231 init function, and pass the corresponding I2C handle: 32 | ```c 33 | DS3231_Init(&hi2c1); 34 | ``` 35 | #### Date and time settings 36 | * Date functions: 37 | ```c 38 | void DS3231_SetDayOfWeek(uint8_t dow); // <-- Number of days since Sunday, 1 to 7. 39 | void DS3231_SetDate(uint8_t date); 40 | void DS3231_SetMonth(uint8_t month); 41 | void DS3231_SetYear(uint16_t year); 42 | void DS3231_SetFullDate(uint8_t date, uint8_t month, uint8_t dow, uint16_t year); 43 | ``` 44 | * Time functions: 45 | ```c 46 | void DS3231_SetHour(uint8_t hour_24mode); 47 | void DS3231_SetMinute(uint8_t minute); 48 | void DS3231_SetSecond(uint8_t second); 49 | void DS3231_SetFullTime(uint8_t hour_24mode, uint8_t minute, uint8_t second); 50 | ``` 51 | 52 | #### Interrupt modes 53 | * Set interrupt mode with: 54 | ```c 55 | void DS3231_SetInterruptMode(DS3231_InterruptMode mode); 56 | ``` 57 | * Options: square wave interrupt and alarm interrupt. 58 | ```c 59 | typedef enum DS3231_InterruptMode{ 60 | DS3231_SQUARE_WAVE_INTERRUPT, DS3231_ALARM_INTERRUPT 61 | }DS3231_InterruptMode; 62 | ``` 63 | #### Square wave output 64 | * With square wave interrupt mode selected, select interrupting rate with: 65 | ```c 66 | void DS3231_SetRateSelect(DS3231_Rate rate); 67 | ``` 68 | * Options: 1 Hz, 1.024 kHz, 4.096 kHz or 8.912 kHz. 69 | ```c 70 | typedef enum DS3231_Rate{ 71 | DS3231_1HZ, DS3231_1024HZ, DS3231_4096HZ, DS3231_8192HZ 72 | }DS3231_Rate; 73 | ``` 74 | 75 | #### Alarms 76 | * With alarm interrupt mode selected, enable/disable alarms with: 77 | ```c 78 | void DS3231_EnableAlarm1(DS3231_State enable); 79 | void DS3231_EnableAlarm2(DS3231_State enable); 80 | ``` 81 | * Set alarm mode with: 82 | ```c 83 | void DS3231_SetAlarm1Mode(DS3231_Alarm1Mode alarmMode); 84 | void DS3231_SetAlarm2Mode(DS3231_Alarm2Mode alarmMode); 85 | ``` 86 | * Options modes: (refer to table 2 of [datasheets](https://datasheets.maximintegrated.com/en/ds/DS3231.pdf)): 87 | ```c 88 | typedef enum D3231_Alarm1Mode{ 89 | DS3231_A1_EVERY_S = 0x0f, DS3231_A1_MATCH_S = 0x0e, DS3231_A1_MATCH_S_M = 0x0c, 90 | DS3231_A1_MATCH_S_M_H = 0x08, DS3231_A1_MATCH_S_M_H_DATE = 0x00, DS3231_A1_MATCH_S_M_H_DAY = 0x80, 91 | }DS3231_Alarm1Mode; 92 | 93 | typedef enum D3231_Alarm2Mode{ 94 | DS3231_A2_EVERY_M = 0x07, DS3231_A2_MATCH_M = 0x06, DS3231_A2_MATCH_M_H = 0x04, 95 | DS3231_A2_MATCH_M_H_DATE = 0x00, DS3231_A2_MATCH_M_H_DAY = 0x80, 96 | }DS3231_Alarm2Mode; 97 | ``` 98 | 99 | ### Interrupts 100 | #### Includes 101 | * In `stm32f*xx_it.c` (interrupt service routine file), include: 102 | ```c 103 | #include "ds3231_for_stm32_hal.h" 104 | ``` 105 | #### Checking for an alarm 106 | * Check for an alarm flag with: 107 | ```c 108 | uint8_t DS3231_IsAlarm1Triggered(); 109 | uint8_t DS3231_IsAlarm2Triggered(); 110 | ``` 111 | #### Clearing an alarm 112 | * Clear an alarm flag with: 113 | ```c 114 | void DS3231_ClearAlarm1Flag(); 115 | void DS3231_ClearAlarm2Flag(); 116 | ``` 117 | 118 | ### Misc 119 | * Enable 32kHz output: 120 | ```c 121 | void DS3231_Enable32kHzOutput(DS3231_State enable); 122 | ``` 123 | * Check for status: 124 | ```c 125 | uint8_t DS3231_IsOscillatorStopped(); 126 | uint8_t DS3231_Is32kHzEnabled(); 127 | ``` 128 | * Temperature functions: 129 | ```c 130 | int8_t DS3231_GetTemperatureInteger(); 131 | uint8_t DS3231_GetTemperatureFraction(); 132 | ``` 133 | * Refer to [./examples](./examples) ([`main.c`](./examples/main.c), [`stm32f4xx_it.c`](./examples/stm32f4xx_it.c)) and [datasheets](https://datasheets.maximintegrated.com/en/ds/DS3231.pdf) for further information. 134 | -------------------------------------------------------------------------------- /ds3231_for_stm32_hal.h: -------------------------------------------------------------------------------- 1 | 2 | /* An STM32 HAL library written for the DS3231 real-time clock IC. */ 3 | /* Library by @eepj www.github.com/eepj */ 4 | #ifndef DS3231_FOR_STM32_HAL_H 5 | #define DS3231_FOR_STM32_HAL_H 6 | #include "main.h" 7 | /*----------------------------------------------------------------------------*/ 8 | #define DS3231_I2C_ADDR 0x68 9 | 10 | #define DS3231_REG_SECOND 0x00 11 | #define DS3231_REG_MINUTE 0x01 12 | #define DS3231_REG_HOUR 0x02 13 | #define DS3231_REG_DOW 0x03 14 | 15 | #define DS3231_REG_DATE 0x04 16 | #define DS3231_REG_MONTH 0x05 17 | #define DS3231_CENTURY 7 18 | #define DS3231_REG_YEAR 0x06 19 | 20 | #define DS3231_A1_SECOND 0x07 21 | #define DS3231_A1_MINUTE 0x08 22 | #define DS3231_A1_HOUR 0x09 23 | #define DS3231_A1_DATE 0x0a 24 | 25 | #define DS3231_A2_MINUTE 0x0b 26 | #define DS3231_A2_HOUR 0x0c 27 | #define DS3231_A2_DATE 0x0d 28 | 29 | #define DS3231_AXMY 7 30 | #define DS3231_DYDT 6 31 | 32 | #define DS3231_REG_CONTROL 0x0e 33 | #define DS3231_EOSC 7 34 | #define DS3231_BBSQW 6 35 | #define DS3231_CONV 5 36 | #define DS3231_RS2 4 37 | #define DS3231_RS1 3 38 | #define DS3231_INTCN 2 39 | #define DS3231_A2IE 1 40 | #define DS3231_A1IE 0 41 | 42 | #define DS3231_REG_STATUS 0x0f 43 | #define DS3231_OSF 7 44 | #define DS3231_EN32KHZ 3 45 | #define DS3231_BSY 2 46 | #define DS3231_A2F 1 47 | #define DS3231_A1F 0 48 | 49 | #define DS3231_AGING 0x10 50 | 51 | #define DS3231_TEMP_MSB 0x11 52 | #define DS3231_TEMP_LSB 0x12 53 | 54 | #define DS3231_TIMEOUT HAL_MAX_DELAY 55 | /*----------------------------------------------------------------------------*/ 56 | typedef enum DS3231_Rate{ 57 | DS3231_1HZ, DS3231_1024HZ, DS3231_4096HZ, DS3231_8192HZ 58 | }DS3231_Rate; 59 | 60 | typedef enum DS3231_InterruptMode{ 61 | DS3231_SQUARE_WAVE_INTERRUPT, DS3231_ALARM_INTERRUPT 62 | }DS3231_InterruptMode; 63 | 64 | typedef enum DS3231_State{ 65 | DS3231_DISABLED, DS3231_ENABLED 66 | }DS3231_State; 67 | 68 | typedef enum D3231_Alarm1Mode{ 69 | DS3231_A1_EVERY_S = 0x0f, DS3231_A1_MATCH_S = 0x0e, DS3231_A1_MATCH_S_M = 0x0c, DS3231_A1_MATCH_S_M_H = 0x08, DS3231_A1_MATCH_S_M_H_DATE = 0x00, DS3231_A1_MATCH_S_M_H_DAY = 0x80, 70 | }DS3231_Alarm1Mode; 71 | 72 | typedef enum D3231_Alarm2Mode{ 73 | DS3231_A2_EVERY_M = 0x07, DS3231_A2_MATCH_M = 0x06, DS3231_A2_MATCH_M_H = 0x04, DS3231_A2_MATCH_M_H_DATE = 0x00, DS3231_A2_MATCH_M_H_DAY = 0x80, 74 | }DS3231_Alarm2Mode; 75 | 76 | extern I2C_HandleTypeDef *_ds3231_ui2c; 77 | 78 | void DS3231_Init(I2C_HandleTypeDef *hi2c); 79 | 80 | void DS3231_SetRegByte(uint8_t regAddr, uint8_t val); 81 | uint8_t DS3231_GetRegByte(uint8_t regAddr); 82 | 83 | uint8_t DS3231_GetDayOfWeek(void); 84 | uint8_t DS3231_GetDate(void); 85 | uint8_t DS3231_GetMonth(void); 86 | uint16_t DS3231_GetYear(void); 87 | 88 | uint8_t DS3231_GetHour(void); 89 | uint8_t DS3231_GetMinute(void); 90 | uint8_t DS3231_GetSecond(void); 91 | 92 | void DS3231_SetDayOfWeek(uint8_t dow); 93 | void DS3231_SetDate(uint8_t date); 94 | void DS3231_SetMonth(uint8_t month); 95 | void DS3231_SetYear(uint16_t year); 96 | 97 | void DS3231_SetHour(uint8_t hour_24mode); 98 | void DS3231_SetMinute(uint8_t minute); 99 | void DS3231_SetSecond(uint8_t second); 100 | 101 | void DS3231_SetFullTime(uint8_t hour_24mode, uint8_t minute, uint8_t second); 102 | void DS3231_SetFullDate(uint8_t date, uint8_t month, uint8_t dow, uint16_t year); 103 | 104 | uint8_t DS3231_DecodeBCD(uint8_t bin); 105 | uint8_t DS3231_EncodeBCD(uint8_t dec); 106 | 107 | void DS3231_EnableBatterySquareWave(DS3231_State enable); 108 | void DS3231_SetInterruptMode(DS3231_InterruptMode mode); 109 | void DS3231_SetRateSelect(DS3231_Rate rate); 110 | void DS3231_EnableOscillator(DS3231_State enable); 111 | 112 | void DS3231_EnableAlarm2(DS3231_State enable); 113 | void DS3231_SetAlarm2Mode(DS3231_Alarm2Mode alarmMode); 114 | void DS3231_ClearAlarm2Flag(); 115 | void DS3231_SetAlarm2Minute(uint8_t minute); 116 | void DS3231_SetAlarm2Hour(uint8_t hour_24mode); 117 | void DS3231_SetAlarm2Date(uint8_t date); 118 | void DS3231_SetAlarm2Day(uint8_t day); 119 | 120 | void DS3231_EnableAlarm1(DS3231_State enable); 121 | void DS3231_SetAlarm1Mode(DS3231_Alarm1Mode alarmMode); 122 | void DS3231_ClearAlarm1Flag(); 123 | void DS3231_SetAlarm1Second(uint8_t second); 124 | void DS3231_SetAlarm1Minute(uint8_t minute); 125 | void DS3231_SetAlarm1Hour(uint8_t hour_24mode); 126 | void DS3231_SetAlarm1Date(uint8_t date); 127 | void DS3231_SetAlarm1Day(uint8_t day); 128 | 129 | void DS3231_Enable32kHzOutput(DS3231_State enable); 130 | 131 | uint8_t DS3231_IsOscillatorStopped(); 132 | uint8_t DS3231_Is32kHzEnabled(); 133 | uint8_t DS3231_IsAlarm1Triggered(); 134 | uint8_t DS3231_IsAlarm2Triggered(); 135 | 136 | int8_t DS3231_GetTemperatureInteger(); 137 | uint8_t DS3231_GetTemperatureFraction(); 138 | 139 | #endif 140 | -------------------------------------------------------------------------------- /examples/stm32f4xx_it.c: -------------------------------------------------------------------------------- 1 | /* USER CODE BEGIN Header */ 2 | /** 3 | ****************************************************************************** 4 | * @file stm32f4xx_it.c 5 | * @brief Interrupt Service Routines. 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | *

© Copyright (c) 2020 STMicroelectronics. 10 | * All rights reserved.

11 | * 12 | * This software component is licensed by ST under BSD 3-Clause license, 13 | * the "License"; You may not use this file except in compliance with the 14 | * License. You may obtain a copy of the License at: 15 | * opensource.org/licenses/BSD-3-Clause 16 | * 17 | ****************************************************************************** 18 | */ 19 | /* USER CODE END Header */ 20 | 21 | /* Includes ------------------------------------------------------------------*/ 22 | #include "main.h" 23 | #include "stm32f4xx_it.h" 24 | /* Private includes ----------------------------------------------------------*/ 25 | /* USER CODE BEGIN Includes */ 26 | /* USER CODE END Includes */ 27 | 28 | /* Private typedef -----------------------------------------------------------*/ 29 | /* USER CODE BEGIN TD */ 30 | 31 | /* USER CODE END TD */ 32 | 33 | /* Private define ------------------------------------------------------------*/ 34 | /* USER CODE BEGIN PD */ 35 | 36 | /* USER CODE END PD */ 37 | 38 | /* Private macro -------------------------------------------------------------*/ 39 | /* USER CODE BEGIN PM */ 40 | 41 | /* USER CODE END PM */ 42 | 43 | /* Private variables ---------------------------------------------------------*/ 44 | /* USER CODE BEGIN PV */ 45 | 46 | /* USER CODE END PV */ 47 | 48 | /* Private function prototypes -----------------------------------------------*/ 49 | /* USER CODE BEGIN PFP */ 50 | 51 | /* USER CODE END PFP */ 52 | 53 | /* Private user code ---------------------------------------------------------*/ 54 | /* USER CODE BEGIN 0 */ 55 | #include "ds3231_for_stm32_hal.h" 56 | #include 57 | /* USER CODE END 0 */ 58 | 59 | /* External variables --------------------------------------------------------*/ 60 | 61 | /* USER CODE BEGIN EV */ 62 | 63 | /* USER CODE END EV */ 64 | 65 | /******************************************************************************/ 66 | /* Cortex-M4 Processor Interruption and Exception Handlers */ 67 | /******************************************************************************/ 68 | /** 69 | * @brief This function handles Non maskable interrupt. 70 | */ 71 | void NMI_Handler(void) 72 | { 73 | /* USER CODE BEGIN NonMaskableInt_IRQn 0 */ 74 | 75 | /* USER CODE END NonMaskableInt_IRQn 0 */ 76 | /* USER CODE BEGIN NonMaskableInt_IRQn 1 */ 77 | 78 | /* USER CODE END NonMaskableInt_IRQn 1 */ 79 | } 80 | 81 | /** 82 | * @brief This function handles Hard fault interrupt. 83 | */ 84 | void HardFault_Handler(void) 85 | { 86 | /* USER CODE BEGIN HardFault_IRQn 0 */ 87 | 88 | /* USER CODE END HardFault_IRQn 0 */ 89 | while (1) 90 | { 91 | /* USER CODE BEGIN W1_HardFault_IRQn 0 */ 92 | /* USER CODE END W1_HardFault_IRQn 0 */ 93 | } 94 | } 95 | 96 | /** 97 | * @brief This function handles Memory management fault. 98 | */ 99 | void MemManage_Handler(void) 100 | { 101 | /* USER CODE BEGIN MemoryManagement_IRQn 0 */ 102 | 103 | /* USER CODE END MemoryManagement_IRQn 0 */ 104 | while (1) 105 | { 106 | /* USER CODE BEGIN W1_MemoryManagement_IRQn 0 */ 107 | /* USER CODE END W1_MemoryManagement_IRQn 0 */ 108 | } 109 | } 110 | 111 | /** 112 | * @brief This function handles Pre-fetch fault, memory access fault. 113 | */ 114 | void BusFault_Handler(void) 115 | { 116 | /* USER CODE BEGIN BusFault_IRQn 0 */ 117 | 118 | /* USER CODE END BusFault_IRQn 0 */ 119 | while (1) 120 | { 121 | /* USER CODE BEGIN W1_BusFault_IRQn 0 */ 122 | /* USER CODE END W1_BusFault_IRQn 0 */ 123 | } 124 | } 125 | 126 | /** 127 | * @brief This function handles Undefined instruction or illegal state. 128 | */ 129 | void UsageFault_Handler(void) 130 | { 131 | /* USER CODE BEGIN UsageFault_IRQn 0 */ 132 | 133 | /* USER CODE END UsageFault_IRQn 0 */ 134 | while (1) 135 | { 136 | /* USER CODE BEGIN W1_UsageFault_IRQn 0 */ 137 | /* USER CODE END W1_UsageFault_IRQn 0 */ 138 | } 139 | } 140 | 141 | /** 142 | * @brief This function handles System service call via SWI instruction. 143 | */ 144 | void SVC_Handler(void) 145 | { 146 | /* USER CODE BEGIN SVCall_IRQn 0 */ 147 | 148 | /* USER CODE END SVCall_IRQn 0 */ 149 | /* USER CODE BEGIN SVCall_IRQn 1 */ 150 | 151 | /* USER CODE END SVCall_IRQn 1 */ 152 | } 153 | 154 | /** 155 | * @brief This function handles Debug monitor. 156 | */ 157 | void DebugMon_Handler(void) 158 | { 159 | /* USER CODE BEGIN DebugMonitor_IRQn 0 */ 160 | 161 | /* USER CODE END DebugMonitor_IRQn 0 */ 162 | /* USER CODE BEGIN DebugMonitor_IRQn 1 */ 163 | 164 | /* USER CODE END DebugMonitor_IRQn 1 */ 165 | } 166 | 167 | /** 168 | * @brief This function handles Pendable request for system service. 169 | */ 170 | void PendSV_Handler(void) 171 | { 172 | /* USER CODE BEGIN PendSV_IRQn 0 */ 173 | 174 | /* USER CODE END PendSV_IRQn 0 */ 175 | /* USER CODE BEGIN PendSV_IRQn 1 */ 176 | 177 | /* USER CODE END PendSV_IRQn 1 */ 178 | } 179 | 180 | /** 181 | * @brief This function handles System tick timer. 182 | */ 183 | void SysTick_Handler(void) 184 | { 185 | /* USER CODE BEGIN SysTick_IRQn 0 */ 186 | 187 | /* USER CODE END SysTick_IRQn 0 */ 188 | HAL_IncTick(); 189 | /* USER CODE BEGIN SysTick_IRQn 1 */ 190 | 191 | /* USER CODE END SysTick_IRQn 1 */ 192 | } 193 | 194 | /******************************************************************************/ 195 | /* STM32F4xx Peripheral Interrupt Handlers */ 196 | /* Add here the Interrupt Handlers for the used peripherals. */ 197 | /* For the available peripheral interrupt handler names, */ 198 | /* please refer to the startup file (startup_stm32f4xx.s). */ 199 | /******************************************************************************/ 200 | 201 | /** 202 | * @brief This function handles EXTI line0 interrupt. 203 | */ 204 | void EXTI0_IRQHandler(void) 205 | { 206 | /* USER CODE BEGIN EXTI0_IRQn 0 */ 207 | //Day of week array 208 | char *day[7] = { "MON", "TUE", "WED", "THU", "FRI", "SAT", "SUN" }; 209 | //ISO8601 format 210 | printf("ISO8601 FORMAT: %04d-%02d-%02dT%02d:%02d:%02d %s %d.%02d\n", DS3231_GetYear(), 211 | DS3231_GetMonth(), DS3231_GetDate(), DS3231_GetHour(), DS3231_GetMinute(), DS3231_GetSecond(), day[DS3231_GetDayOfWeek()-1], 212 | DS3231_GetTemperatureInteger(), DS3231_GetTemperatureFraction()); 213 | //Check if any alarm is triggered 214 | if(DS3231_IsAlarm1Triggered()){ 215 | printf("Alarm 1 triggered\n"); 216 | }else if(DS3231_IsAlarm2Triggered()){ 217 | DS3231_ClearAlarm2Flag(); 218 | printf("Alarm 2 triggered\n"); 219 | } 220 | //For demonstration purpose, clear all flags 221 | DS3231_ClearAlarm1Flag(); 222 | DS3231_ClearAlarm2Flag(); 223 | //Toggle LED, comment out if unnecessary 224 | HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13); 225 | /* USER CODE END EXTI0_IRQn 0 */ 226 | HAL_GPIO_EXTI_IRQHandler(GPIO_PIN_0); 227 | /* USER CODE BEGIN EXTI0_IRQn 1 */ 228 | 229 | /* USER CODE END EXTI0_IRQn 1 */ 230 | } 231 | 232 | /* USER CODE BEGIN 1 */ 233 | 234 | /* USER CODE END 1 */ 235 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 236 | -------------------------------------------------------------------------------- /examples/main.c: -------------------------------------------------------------------------------- 1 | /* USER CODE BEGIN Header */ 2 | /** 3 | ****************************************************************************** 4 | * @file : main.c 5 | * @brief : Main program body 6 | ****************************************************************************** 7 | * @attention 8 | * 9 | *

© Copyright (c) 2020 STMicroelectronics. 10 | * All rights reserved.

11 | * 12 | * This software component is licensed by ST under BSD 3-Clause license, 13 | * the "License"; You may not use this file except in compliance with the 14 | * License. You may obtain a copy of the License at: 15 | * opensource.org/licenses/BSD-3-Clause 16 | * 17 | ****************************************************************************** 18 | */ 19 | /* USER CODE END Header */ 20 | 21 | /* Includes ------------------------------------------------------------------*/ 22 | #include "main.h" 23 | 24 | /* Private includes ----------------------------------------------------------*/ 25 | /* USER CODE BEGIN Includes */ 26 | #include 27 | #include "ds3231_for_stm32_hal.h" 28 | /* USER CODE END Includes */ 29 | 30 | /* Private typedef -----------------------------------------------------------*/ 31 | /* USER CODE BEGIN PTD */ 32 | 33 | /* USER CODE END PTD */ 34 | 35 | /* Private define ------------------------------------------------------------*/ 36 | /* USER CODE BEGIN PD */ 37 | /* USER CODE END PD */ 38 | 39 | /* Private macro -------------------------------------------------------------*/ 40 | /* USER CODE BEGIN PM */ 41 | 42 | /* USER CODE END PM */ 43 | 44 | /* Private variables ---------------------------------------------------------*/ 45 | I2C_HandleTypeDef hi2c1; 46 | 47 | UART_HandleTypeDef huart1; 48 | 49 | /* USER CODE BEGIN PV */ 50 | 51 | /* USER CODE END PV */ 52 | 53 | /* Private function prototypes -----------------------------------------------*/ 54 | void SystemClock_Config(void); 55 | static void MX_GPIO_Init(void); 56 | static void MX_USART1_UART_Init(void); 57 | static void MX_I2C1_Init(void); 58 | /* USER CODE BEGIN PFP */ 59 | 60 | /* USER CODE END PFP */ 61 | 62 | /* Private user code ---------------------------------------------------------*/ 63 | /* USER CODE BEGIN 0 */ 64 | void printr(uint8_t reg) { 65 | printf("Reg 0x%02x = ", reg); 66 | uint8_t val; 67 | HAL_I2C_Master_Transmit(_ds3231_ui2c, DS3231_I2C_ADDR << 1, ®, 1, 68 | DS3231_TIMEOUT); 69 | HAL_StatusTypeDef s = HAL_I2C_Master_Receive(_ds3231_ui2c, 70 | DS3231_I2C_ADDR << 1, &val, 1, DS3231_TIMEOUT); 71 | for (uint8_t i = 0; i < 8; i++) { 72 | printf("%d", (val >> (7 - i)) & 1); 73 | } 74 | printf(" With status %d", s); 75 | printf("\n"); 76 | } 77 | /* USER CODE END 0 */ 78 | 79 | /** 80 | * @brief The application entry point. 81 | * @retval int 82 | */ 83 | int main(void) { 84 | /* USER CODE BEGIN 1 */ 85 | __disable_irq(); 86 | /* USER CODE END 1 */ 87 | 88 | /* MCU Configuration--------------------------------------------------------*/ 89 | 90 | /* Reset of all peripherals, Initializes the Flash interface and the Systick. */ 91 | HAL_Init(); 92 | 93 | /* USER CODE BEGIN Init */ 94 | 95 | /* USER CODE END Init */ 96 | 97 | /* Configure the system clock */ 98 | SystemClock_Config(); 99 | 100 | /* USER CODE BEGIN SysInit */ 101 | 102 | /* USER CODE END SysInit */ 103 | 104 | /* Initialize all configured peripherals */ 105 | MX_GPIO_Init(); 106 | MX_USART1_UART_Init(); 107 | MX_I2C1_Init(); 108 | /* USER CODE BEGIN 2 */ 109 | //DS3231 init function. Pass I2C handle. 110 | DS3231_Init(&hi2c1); 111 | //Disable interrupts while we set interrupt configs. 112 | __disable_irq(); 113 | //Set interrupt mode to square wave mode, enable square wave interrupt at pin 3. 114 | DS3231_SetInterruptMode(DS3231_SQUARE_WAVE_INTERRUPT); 115 | //Set interrupting frequency to 1 Hz. 116 | DS3231_SetRateSelect(DS3231_1HZ); 117 | //Set time. 118 | DS3231_SetFullTime(23, 59, 50); 119 | //Set date. 120 | DS3231_SetFullDate(10, 11, 2, 2020); 121 | //Print all register values, for demonstration purpose 122 | for(uint8_t i = 0x00; i < 0x13; i++) 123 | printr(i); 124 | //Enable interrupts after finishing. 125 | __enable_irq(); 126 | 127 | //Should show 5 interrupts, once every second. 128 | HAL_Delay(5000); 129 | 130 | //Set to alarm interrupt mode. 131 | DS3231_SetInterruptMode(DS3231_ALARM_INTERRUPT); 132 | DS3231_ClearAlarm1Flag(); 133 | 134 | //Test alarm 1 135 | DS3231_EnableAlarm1(DS3231_ENABLED); 136 | DS3231_SetAlarm1Mode(DS3231_A1_MATCH_S_M_H_DATE); 137 | DS3231_SetAlarm1Second(3); 138 | DS3231_SetAlarm1Minute(0); 139 | DS3231_SetAlarm1Hour(0); 140 | DS3231_SetAlarm1Date(11); 141 | 142 | //Test alarm 2 143 | DS3231_ClearAlarm2Flag(); 144 | DS3231_EnableAlarm2(DS3231_ENABLED); 145 | DS3231_SetAlarm2Mode(DS3231_A2_MATCH_M_H_DAY); 146 | DS3231_SetAlarm2Minute(0); 147 | DS3231_SetAlarm2Hour(0); 148 | DS3231_SetAlarm2Day(3); 149 | 150 | //Check if alarm behavior is correct 151 | __enable_irq(); 152 | HAL_Delay(5000); 153 | DS3231_SetFullTime(1, 59, 59); 154 | DS3231_SetDate(11); 155 | DS3231_SetDayOfWeek(3); 156 | HAL_Delay(5000); 157 | DS3231_SetFullTime(23, 59, 59); 158 | DS3231_SetDate(10); 159 | DS3231_SetDayOfWeek(2); 160 | HAL_Delay(5000); 161 | DS3231_SetFullTime(23, 59, 59); 162 | DS3231_SetDate(11); 163 | DS3231_SetDayOfWeek(3); 164 | HAL_Delay(5000); 165 | 166 | /* USER CODE END 2 */ 167 | 168 | /* Infinite loop */ 169 | /* USER CODE BEGIN WHILE */ 170 | while (1) { 171 | 172 | /* USER CODE END WHILE */ 173 | 174 | /* USER CODE BEGIN 3 */ 175 | } 176 | /* USER CODE END 3 */ 177 | } 178 | 179 | /** 180 | * @brief System Clock Configuration 181 | * @retval None 182 | */ 183 | void SystemClock_Config(void) { 184 | RCC_OscInitTypeDef RCC_OscInitStruct = { 0 }; 185 | RCC_ClkInitTypeDef RCC_ClkInitStruct = { 0 }; 186 | 187 | /** Configure the main internal regulator output voltage 188 | */ 189 | __HAL_RCC_PWR_CLK_ENABLE(); 190 | __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE2); 191 | /** Initializes the CPU, AHB and APB busses clocks 192 | */ 193 | RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE; 194 | RCC_OscInitStruct.HSEState = RCC_HSE_ON; 195 | RCC_OscInitStruct.PLL.PLLState = RCC_PLL_NONE; 196 | if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK) { 197 | Error_Handler(); 198 | } 199 | /** Initializes the CPU, AHB and APB busses clocks 200 | */ 201 | RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK 202 | | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2; 203 | RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_HSE; 204 | RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1; 205 | RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1; 206 | RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1; 207 | 208 | if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_0) != HAL_OK) { 209 | Error_Handler(); 210 | } 211 | } 212 | 213 | /** 214 | * @brief I2C1 Initialization Function 215 | * @param None 216 | * @retval None 217 | */ 218 | static void MX_I2C1_Init(void) { 219 | 220 | /* USER CODE BEGIN I2C1_Init 0 */ 221 | 222 | /* USER CODE END I2C1_Init 0 */ 223 | 224 | /* USER CODE BEGIN I2C1_Init 1 */ 225 | 226 | /* USER CODE END I2C1_Init 1 */ 227 | hi2c1.Instance = I2C1; 228 | hi2c1.Init.ClockSpeed = 100000; 229 | hi2c1.Init.DutyCycle = I2C_DUTYCYCLE_2; 230 | hi2c1.Init.OwnAddress1 = 0; 231 | hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT; 232 | hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE; 233 | hi2c1.Init.OwnAddress2 = 0; 234 | hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE; 235 | hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE; 236 | if (HAL_I2C_Init(&hi2c1) != HAL_OK) { 237 | Error_Handler(); 238 | } 239 | /* USER CODE BEGIN I2C1_Init 2 */ 240 | 241 | /* USER CODE END I2C1_Init 2 */ 242 | 243 | } 244 | 245 | /** 246 | * @brief USART1 Initialization Function 247 | * @param None 248 | * @retval None 249 | */ 250 | static void MX_USART1_UART_Init(void) { 251 | 252 | /* USER CODE BEGIN USART1_Init 0 */ 253 | 254 | /* USER CODE END USART1_Init 0 */ 255 | 256 | /* USER CODE BEGIN USART1_Init 1 */ 257 | 258 | /* USER CODE END USART1_Init 1 */ 259 | huart1.Instance = USART1; 260 | huart1.Init.BaudRate = 115200; 261 | huart1.Init.WordLength = UART_WORDLENGTH_8B; 262 | huart1.Init.StopBits = UART_STOPBITS_1; 263 | huart1.Init.Parity = UART_PARITY_NONE; 264 | huart1.Init.Mode = UART_MODE_TX_RX; 265 | huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE; 266 | huart1.Init.OverSampling = UART_OVERSAMPLING_16; 267 | if (HAL_UART_Init(&huart1) != HAL_OK) { 268 | Error_Handler(); 269 | } 270 | /* USER CODE BEGIN USART1_Init 2 */ 271 | 272 | /* USER CODE END USART1_Init 2 */ 273 | 274 | } 275 | 276 | /** 277 | * @brief GPIO Initialization Function 278 | * @param None 279 | * @retval None 280 | */ 281 | static void MX_GPIO_Init(void) { 282 | GPIO_InitTypeDef GPIO_InitStruct = { 0 }; 283 | 284 | /* GPIO Ports Clock Enable */ 285 | __HAL_RCC_GPIOC_CLK_ENABLE(); 286 | __HAL_RCC_GPIOH_CLK_ENABLE(); 287 | __HAL_RCC_GPIOA_CLK_ENABLE(); 288 | __HAL_RCC_GPIOB_CLK_ENABLE(); 289 | 290 | /*Configure GPIO pin Output Level */ 291 | HAL_GPIO_WritePin(GPIOC, GPIO_PIN_13, GPIO_PIN_RESET); 292 | 293 | /*Configure GPIO pin : PC13 */ 294 | GPIO_InitStruct.Pin = GPIO_PIN_13; 295 | GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; 296 | GPIO_InitStruct.Pull = GPIO_NOPULL; 297 | GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; 298 | HAL_GPIO_Init(GPIOC, &GPIO_InitStruct); 299 | 300 | /*Configure GPIO pin : PA0 */ 301 | GPIO_InitStruct.Pin = GPIO_PIN_0; 302 | GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING; 303 | GPIO_InitStruct.Pull = GPIO_NOPULL; 304 | HAL_GPIO_Init(GPIOA, &GPIO_InitStruct); 305 | 306 | /* EXTI interrupt init*/ 307 | HAL_NVIC_SetPriority(EXTI0_IRQn, 1, 0); 308 | HAL_NVIC_EnableIRQ(EXTI0_IRQn); 309 | 310 | } 311 | 312 | /* USER CODE BEGIN 4 */ 313 | int __io_putchar(int ch) { 314 | uint8_t temp[1] = { ch }; 315 | HAL_UART_Transmit(&huart1, temp, 1, HAL_MAX_DELAY); 316 | return ch; 317 | } 318 | /* USER CODE END 4 */ 319 | 320 | /** 321 | * @brief This function is executed in case of error occurrence. 322 | * @retval None 323 | */ 324 | void Error_Handler(void) { 325 | /* USER CODE BEGIN Error_Handler_Debug */ 326 | /* User can add his own implementation to report the HAL error return state */ 327 | 328 | /* USER CODE END Error_Handler_Debug */ 329 | } 330 | 331 | #ifdef USE_FULL_ASSERT 332 | /** 333 | * @brief Reports the name of the source file and the source line number 334 | * where the assert_param error has occurred. 335 | * @param file: pointer to the source file name 336 | * @param line: assert_param error line source number 337 | * @retval None 338 | */ 339 | void assert_failed(uint8_t *file, uint32_t line) 340 | { 341 | /* USER CODE BEGIN 6 */ 342 | /* User can add his own implementation to report the file name and line number, 343 | tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */ 344 | /* USER CODE END 6 */ 345 | } 346 | #endif /* USE_FULL_ASSERT */ 347 | 348 | /************************ (C) COPYRIGHT STMicroelectronics *****END OF FILE****/ 349 | -------------------------------------------------------------------------------- /ds3231_for_stm32_hal.c: -------------------------------------------------------------------------------- 1 | 2 | /* An STM32 HAL library written for the DS3231 real-time clock IC. */ 3 | /* Library by @eepj www.github.com/eepj */ 4 | #include "ds3231_for_stm32_hal.h" 5 | #include "main.h" 6 | #ifdef __cplusplus 7 | extern "C"{ 8 | #endif 9 | 10 | I2C_HandleTypeDef *_ds3231_ui2c; 11 | 12 | /** 13 | * @brief Initializes the DS3231 module. Set clock halt bit to 0 to start timing. 14 | * @param hi2c User I2C handle pointer. 15 | */ 16 | void DS3231_Init(I2C_HandleTypeDef *hi2c) { 17 | _ds3231_ui2c = hi2c; 18 | DS3231_EnableAlarm1(DS3231_DISABLED); 19 | DS3231_EnableAlarm2(DS3231_DISABLED); 20 | DS3231_ClearAlarm1Flag(); 21 | DS3231_ClearAlarm2Flag(); 22 | DS3231_SetInterruptMode(DS3231_ALARM_INTERRUPT); 23 | } 24 | 25 | /** 26 | * @brief Set the byte in the designated DS3231 register to value. 27 | * @param regAddr Register address to write. 28 | * @param val Value to set, 0 to 255. 29 | */ 30 | void DS3231_SetRegByte(uint8_t regAddr, uint8_t val) { 31 | uint8_t bytes[2] = { regAddr, val }; 32 | HAL_I2C_Master_Transmit(_ds3231_ui2c, DS3231_I2C_ADDR << 1, bytes, 2, DS3231_TIMEOUT); 33 | } 34 | 35 | /** 36 | * @brief Gets the byte in the designated DS3231 register. 37 | * @param regAddr Register address to read. 38 | * @return Value stored in the register, 0 to 255. 39 | */ 40 | uint8_t DS3231_GetRegByte(uint8_t regAddr) { 41 | uint8_t val; 42 | HAL_I2C_Master_Transmit(_ds3231_ui2c, DS3231_I2C_ADDR << 1, ®Addr, 1, DS3231_TIMEOUT); 43 | HAL_I2C_Master_Receive(_ds3231_ui2c, DS3231_I2C_ADDR << 1, &val, 1, DS3231_TIMEOUT); 44 | return val; 45 | } 46 | 47 | /** 48 | * @brief Enables battery-backed square wave output at the INT#/SQW pin. 49 | * @param enable Enable, DS3231_ENABLED or DS3231_DISABLED. 50 | */ 51 | void DS3231_EnableBatterySquareWave(DS3231_State enable){ 52 | uint8_t control = DS3231_GetRegByte(DS3231_REG_CONTROL); 53 | DS3231_SetRegByte(DS3231_REG_CONTROL, (control & 0xbf) | ((enable & 0x01) << DS3231_BBSQW)); 54 | } 55 | 56 | /** 57 | * @brief Set the interrupt mode to either alarm interrupt or square wave interrupt. 58 | * @param mode Interrupt mode to set, DS3231_ALARM_INTERRUPT or DS3231_SQUARE_WAVE_INTERRUPT. 59 | */ 60 | void DS3231_SetInterruptMode(DS3231_InterruptMode mode){ 61 | uint8_t control = DS3231_GetRegByte(DS3231_REG_CONTROL); 62 | DS3231_SetRegByte(DS3231_REG_CONTROL, (control & 0xfb) | ((mode & 0x01) << DS3231_INTCN)); 63 | } 64 | 65 | /** 66 | * @brief Set frequency of the square wave output 67 | * @param rate Frequency to set, DS3231_1HZ, DS3231_1024HZ, DS3231_4096HZ or DS3231_8192HZ. 68 | */ 69 | void DS3231_SetRateSelect(DS3231_Rate rate){ 70 | uint8_t control = DS3231_GetRegByte(DS3231_REG_CONTROL); 71 | DS3231_SetRegByte(DS3231_REG_CONTROL, (control & 0xe7) | ((rate & 0x03) << DS3231_RS1)); 72 | } 73 | 74 | /** 75 | * @brief Enables clock oscillator. 76 | * @param enable Enable, DS3231_ENABLED or DS3231_DISABLED. 77 | */ 78 | void DS3231_EnableOscillator(DS3231_State enable){ 79 | uint8_t control = DS3231_GetRegByte(DS3231_REG_CONTROL); 80 | DS3231_SetRegByte(DS3231_REG_CONTROL, (control & 0x7f) | ((!enable & 0x01) << DS3231_EOSC)); 81 | } 82 | 83 | /** 84 | * @brief Enables alarm 2. 85 | * @param enable Enable, DS3231_ENABLED or DS3231_DISABLED. 86 | */ 87 | void DS3231_EnableAlarm2(DS3231_State enable){ 88 | uint8_t control = DS3231_GetRegByte(DS3231_REG_CONTROL); 89 | DS3231_SetRegByte(DS3231_REG_CONTROL, (control & 0xfd) | ((enable & 0x01) << DS3231_A2IE)); 90 | DS3231_SetInterruptMode(DS3231_ALARM_INTERRUPT); 91 | } 92 | 93 | /** 94 | * @brief Clears alarm 2 matched flag. Matched flags must be cleared before the next match or the next interrupt will be masked. 95 | */ 96 | void DS3231_ClearAlarm2Flag(){ 97 | uint8_t status = DS3231_GetRegByte(DS3231_REG_STATUS) & 0xfd; 98 | DS3231_SetRegByte(DS3231_REG_STATUS, status & ~(0x01 << DS3231_A2F)); 99 | } 100 | 101 | /** 102 | * @brief Set alarm 2 minute to match. Does not change alarm 2 matching mode. 103 | * @param minute Minute, 0 to 59. 104 | */ 105 | void DS3231_SetAlarm2Minute(uint8_t minute){ 106 | uint8_t temp = DS3231_GetRegByte(DS3231_A2_MINUTE) & 0x80; 107 | uint8_t a2m2 = temp | (DS3231_EncodeBCD(minute) & 0x3f); 108 | DS3231_SetRegByte(DS3231_A2_MINUTE, a2m2); 109 | } 110 | 111 | /** 112 | * @brief Set alarm 2 hour to match. Does not change alarm 2 matching mode. 113 | * @param hour Hour to match in 24h format, 0 to 23. 114 | */ 115 | void DS3231_SetAlarm2Hour(uint8_t hour_24mode){ 116 | uint8_t temp = DS3231_GetRegByte(DS3231_A2_HOUR) & 0x80; 117 | uint8_t a2m3 = temp | (DS3231_EncodeBCD(hour_24mode) & 0x3f); 118 | DS3231_SetRegByte(DS3231_A2_HOUR, a2m3); 119 | } 120 | 121 | /** 122 | * @brief Set alarm 2 date. Alarm 2 can only be set to match either date or day. Does not change alarm 2 matching mode. 123 | * @param date Date, 0 to 31. 124 | */ 125 | void DS3231_SetAlarm2Date(uint8_t date){ 126 | uint8_t temp = DS3231_GetRegByte(DS3231_A2_DATE) & 0x80; 127 | uint8_t a2m4 = temp | (DS3231_EncodeBCD(date) & 0x3f); 128 | DS3231_SetRegByte(DS3231_A2_DATE, a2m4); 129 | } 130 | 131 | /** 132 | * @brief Set alarm 2 day. Alarm 2 can only be set to match either date or day. Does not change alarm 2 matching mode. 133 | * @param day Days since last Sunday, 1 to 7. 134 | */ 135 | void DS3231_SetAlarm2Day(uint8_t day){ 136 | uint8_t temp = DS3231_GetRegByte(DS3231_A2_DATE) & 0x80; 137 | uint8_t a2m4 = temp | (0x01 << DS3231_DYDT) | (DS3231_EncodeBCD(day) & 0x3f); 138 | DS3231_SetRegByte(DS3231_A2_DATE, a2m4); 139 | } 140 | 141 | /** 142 | * @brief Set alarm 2 mode. 143 | * @param alarmMode Alarm 2 mode, DS3231_A2_EVERY_M, DS3231_A2_MATCH_M, DS3231_A2_MATCH_M_H, DS3231_A2_MATCH_M_H_DATE or DS3231_A2_MATCH_M_H_DAY. 144 | */ 145 | void DS3231_SetAlarm2Mode(DS3231_Alarm2Mode alarmMode){ 146 | uint8_t temp; 147 | temp = DS3231_GetRegByte(DS3231_A1_MINUTE) & 0x7f; 148 | DS3231_SetRegByte(DS3231_A2_MINUTE, temp | (((alarmMode >> 0) & 0x01) << DS3231_AXMY)); 149 | temp = DS3231_GetRegByte(DS3231_A1_HOUR) & 0x7f; 150 | DS3231_SetRegByte(DS3231_A2_HOUR, temp | (((alarmMode >> 1) & 0x01) << DS3231_AXMY)); 151 | temp = DS3231_GetRegByte(DS3231_A1_DATE) & 0x7f; 152 | DS3231_SetRegByte(DS3231_A2_DATE, temp | (((alarmMode >> 2) & 0x01) << DS3231_AXMY) | (alarmMode & 0x80)); 153 | } 154 | 155 | /** 156 | * @brief Enables alarm 1. 157 | * @param enable Enable, DS3231_ENABLED or DS3231_DISABLED. 158 | */ 159 | void DS3231_EnableAlarm1(DS3231_State enable){ 160 | uint8_t control = DS3231_GetRegByte(DS3231_REG_CONTROL); 161 | DS3231_SetRegByte(DS3231_REG_CONTROL, (control & 0xfe) | ((enable & 0x01) << DS3231_A1IE)); 162 | DS3231_SetInterruptMode(DS3231_ALARM_INTERRUPT); 163 | } 164 | 165 | /** 166 | * @brief Clears alarm 1 matched flag. Matched flags must be cleared before the next match or the next interrupt will be masked. 167 | */ 168 | void DS3231_ClearAlarm1Flag(){ 169 | uint8_t status = DS3231_GetRegByte(DS3231_REG_STATUS) & 0xfe; 170 | DS3231_SetRegByte(DS3231_REG_STATUS, status & ~(0x01 << DS3231_A1F)); 171 | } 172 | 173 | /** 174 | * @brief Set alarm 1 second to match. Does not change alarm 1 matching mode. 175 | * @param second Second, 0 to 59. 176 | */ 177 | void DS3231_SetAlarm1Second(uint8_t second){ 178 | uint8_t temp = DS3231_GetRegByte(DS3231_A1_SECOND) & 0x80; 179 | uint8_t a1m1 = temp | (DS3231_EncodeBCD(second) & 0x3f); 180 | DS3231_SetRegByte(DS3231_A1_SECOND, a1m1); 181 | } 182 | 183 | /** 184 | * @brief Set alarm 1 minute to match. Does not change alarm 1 matching mode. 185 | * @param minute Minute, 0 to 59. 186 | */ 187 | void DS3231_SetAlarm1Minute(uint8_t minute){ 188 | uint8_t temp = DS3231_GetRegByte(DS3231_A1_MINUTE) & 0x80; 189 | uint8_t a1m2 = temp | (DS3231_EncodeBCD(minute) & 0x3f); 190 | DS3231_SetRegByte(DS3231_A1_MINUTE, a1m2); 191 | } 192 | 193 | /** 194 | * @brief Set alarm 1 hour to match. Does not change alarm 1 matching mode. 195 | * @param hour Hour, 0 to 59. 196 | */ 197 | void DS3231_SetAlarm1Hour(uint8_t hour_24mode){ 198 | uint8_t temp = DS3231_GetRegByte(DS3231_A1_HOUR) & 0x80; 199 | uint8_t a1m3 = temp | (DS3231_EncodeBCD(hour_24mode) & 0x3f); 200 | DS3231_SetRegByte(DS3231_A1_HOUR, a1m3); 201 | } 202 | 203 | /** 204 | * @brief Set alarm 1 date. Alarm 1 can only be set to match either date or day. Does not change alarm 1 matching mode. 205 | * @param date Date, 0 to 31. 206 | */ 207 | void DS3231_SetAlarm1Date(uint8_t date){ 208 | uint8_t temp = DS3231_GetRegByte(DS3231_A1_DATE) & 0x80; 209 | uint8_t a1m4 = temp | (DS3231_EncodeBCD(date) & 0x3f); 210 | DS3231_SetRegByte(DS3231_A1_DATE, a1m4); 211 | } 212 | 213 | /** 214 | * @brief Set alarm 1 day. Alarm 1 can only be set to match either date or day. Does not change alarm 1 matching mode. 215 | * @param day Days since last Sunday, 1 to 7. 216 | */ 217 | void DS3231_SetAlarm1Day(uint8_t day){ 218 | uint8_t temp = DS3231_GetRegByte(DS3231_A1_DATE) & 0x80; 219 | uint8_t a1m4 = temp | (0x01 << DS3231_DYDT) | (DS3231_EncodeBCD(day) & 0x3f); 220 | DS3231_SetRegByte(DS3231_A1_DATE, a1m4); 221 | } 222 | 223 | /** 224 | * @brief Set alarm 1 mode. 225 | * @param alarmMode Alarm 1 mode, DS3231_A1_EVERY_S, DS3231_A1_MATCH_S, DS3231_A1_MATCH_S_M, DS3231_A1_MATCH_S_M_H, DS3231_A1_MATCH_S_M_H_DATE or DS3231_A1_MATCH_S_M_H_DAY. 226 | */ 227 | void DS3231_SetAlarm1Mode(DS3231_Alarm1Mode alarmMode){ 228 | uint8_t temp; 229 | temp = DS3231_GetRegByte(DS3231_A1_SECOND) & 0x7f; 230 | DS3231_SetRegByte(DS3231_A1_SECOND, temp | (((alarmMode >> 0) & 0x01) << DS3231_AXMY)); 231 | temp = DS3231_GetRegByte(DS3231_A1_MINUTE) & 0x7f; 232 | DS3231_SetRegByte(DS3231_A1_MINUTE, temp | (((alarmMode >> 1) & 0x01) << DS3231_AXMY)); 233 | temp = DS3231_GetRegByte(DS3231_A1_HOUR) & 0x7f; 234 | DS3231_SetRegByte(DS3231_A1_HOUR, temp | (((alarmMode >> 2) & 0x01) << DS3231_AXMY)); 235 | temp = DS3231_GetRegByte(DS3231_A1_DATE) & 0x7f; 236 | DS3231_SetRegByte(DS3231_A1_DATE, temp | (((alarmMode >> 3) & 0x01) << DS3231_AXMY) | (alarmMode & 0x80)); 237 | } 238 | 239 | /** 240 | * @brief Check whether the clock oscillator is stopped. 241 | * @return Oscillator stopped flag (OSF) bit, 0 or 1. 242 | */ 243 | uint8_t DS3231_IsOscillatorStopped(){ 244 | return (DS3231_GetRegByte(DS3231_REG_STATUS) >> DS3231_OSF) & 0x01; 245 | } 246 | 247 | /** 248 | * @brief Check whether the 32kHz output is enabled. 249 | * @return EN32kHz flag bit, 0 or 1. 250 | */ 251 | uint8_t DS3231_Is32kHzEnabled(){ 252 | return (DS3231_GetRegByte(DS3231_REG_STATUS) >> DS3231_EN32KHZ) & 0x01; 253 | } 254 | 255 | /** 256 | * @brief Check if alarm 1 is triggered. 257 | * @return A1F flag bit, 0 or 1. 258 | */ 259 | uint8_t DS3231_IsAlarm1Triggered(){ 260 | return (DS3231_GetRegByte(DS3231_REG_STATUS) >> DS3231_A1F) & 0x01; 261 | } 262 | 263 | /** 264 | * @brief Check if alarm 2 is triggered. 265 | * @return A2F flag bit, 0 or 1. 266 | */ 267 | uint8_t DS3231_IsAlarm2Triggered(){ 268 | return (DS3231_GetRegByte(DS3231_REG_STATUS) >> DS3231_A2F) & 0x01; 269 | } 270 | 271 | /** 272 | * @brief Gets the current day of week. 273 | * @return Days from last Sunday, 0 to 6. 274 | */ 275 | uint8_t DS3231_GetDayOfWeek(void) { 276 | return DS3231_DecodeBCD(DS3231_GetRegByte(DS3231_REG_DOW)); 277 | } 278 | 279 | /** 280 | * @brief Gets the current day of month. 281 | * @return Day of month, 1 to 31. 282 | */ 283 | uint8_t DS3231_GetDate(void) { 284 | return DS3231_DecodeBCD(DS3231_GetRegByte(DS3231_REG_DATE)); 285 | } 286 | 287 | /** 288 | * @brief Gets the current month. 289 | * @return Month, 1 to 12. 290 | */ 291 | uint8_t DS3231_GetMonth(void) { 292 | return DS3231_DecodeBCD(DS3231_GetRegByte(DS3231_REG_MONTH) & 0x7f); 293 | } 294 | 295 | /** 296 | * @brief Gets the current year. 297 | * @return Year, 2000 to 2199. 298 | */ 299 | uint16_t DS3231_GetYear(void) { 300 | uint8_t decYear = DS3231_DecodeBCD(DS3231_GetRegByte(DS3231_REG_YEAR)); 301 | uint16_t century = (DS3231_GetRegByte(DS3231_REG_MONTH) >> DS3231_CENTURY) * 100 + 2000; 302 | return century + decYear; 303 | } 304 | 305 | /** 306 | * @brief Gets the current hour in 24h format. 307 | * @return Hour in 24h format, 0 to 23. 308 | */ 309 | uint8_t DS3231_GetHour(void) { 310 | return DS3231_DecodeBCD(DS3231_GetRegByte(DS3231_REG_HOUR)); 311 | } 312 | 313 | /** 314 | * @brief Gets the current minute. 315 | * @return Minute, 0 to 59. 316 | */ 317 | uint8_t DS3231_GetMinute(void) { 318 | return DS3231_DecodeBCD(DS3231_GetRegByte(DS3231_REG_MINUTE)); 319 | } 320 | 321 | /** 322 | * @brief Gets the current second. Clock halt bit not included. 323 | * @return Second, 0 to 59. 324 | */ 325 | uint8_t DS3231_GetSecond(void) { 326 | return DS3231_DecodeBCD(DS3231_GetRegByte(DS3231_REG_SECOND)); 327 | } 328 | 329 | /** 330 | * @brief Set the current day of week. 331 | * @param dayOfWeek Days since last Sunday, 1 to 7. 332 | */ 333 | void DS3231_SetDayOfWeek(uint8_t dayOfWeek) { 334 | DS3231_SetRegByte(DS3231_REG_DOW, DS3231_EncodeBCD(dayOfWeek)); 335 | } 336 | 337 | /** 338 | * @brief Set the current day of month. 339 | * @param date Day of month, 1 to 31. 340 | */ 341 | void DS3231_SetDate(uint8_t date) { 342 | DS3231_SetRegByte(DS3231_REG_DATE, DS3231_EncodeBCD(date)); 343 | } 344 | 345 | /** 346 | * @brief Set the current month. 347 | * @param month Month, 1 to 12. 348 | */ 349 | void DS3231_SetMonth(uint8_t month) { 350 | uint8_t century = DS3231_GetRegByte(DS3231_REG_MONTH) & 0x80; 351 | DS3231_SetRegByte(DS3231_REG_MONTH, DS3231_EncodeBCD(month) | century); 352 | } 353 | 354 | /** 355 | * @brief Set the current year. 356 | * @param year Year, 2000 to 2199. 357 | */ 358 | void DS3231_SetYear(uint16_t year) { 359 | uint8_t century = (year / 100) % 20; 360 | uint8_t monthReg = (DS3231_GetRegByte(DS3231_REG_MONTH) & 0x7f) | (century << DS3231_CENTURY); 361 | DS3231_SetRegByte(DS3231_REG_MONTH, monthReg); 362 | DS3231_SetRegByte(DS3231_REG_YEAR, DS3231_EncodeBCD(year % 100)); 363 | } 364 | 365 | /** 366 | * @brief Set the current hour, in 24h format. 367 | * @param hour_24mode Hour in 24h format, 0 to 23. 368 | */ 369 | void DS3231_SetHour(uint8_t hour_24mode) { 370 | DS3231_SetRegByte(DS3231_REG_HOUR, DS3231_EncodeBCD(hour_24mode & 0x3f)); 371 | } 372 | 373 | /** 374 | * @brief Set the current minute. 375 | * @param minute Minute, 0 to 59. 376 | */ 377 | void DS3231_SetMinute(uint8_t minute) { 378 | DS3231_SetRegByte(DS3231_REG_MINUTE, DS3231_EncodeBCD(minute)); 379 | } 380 | 381 | /** 382 | * @brief Set the current second. 383 | * @param second Second, 0 to 59. 384 | */ 385 | void DS3231_SetSecond(uint8_t second) { 386 | DS3231_SetRegByte(DS3231_REG_SECOND, DS3231_EncodeBCD(second)); 387 | } 388 | 389 | /** 390 | * @brief Set the current time. 391 | * @param hour_24mode Hour in 24h format, 0 to 23. 392 | * @param minute Minute, 0 to 59. 393 | * @param second Second, 0 to 59. 394 | */ 395 | void DS3231_SetFullTime(uint8_t hour_24mode, uint8_t minute, uint8_t second){ 396 | DS3231_SetHour(hour_24mode); 397 | DS3231_SetMinute(minute); 398 | DS3231_SetSecond(second); 399 | } 400 | 401 | /** 402 | * @brief Set the current date, month, day of week and year. 403 | * @param date Date, 0 to 31. 404 | * @param month Month, 1 to 12. 405 | * @param dow Days since last Sunday, 1 to 7. 406 | * @param year Year, 2000 to 2199. 407 | */ 408 | void DS3231_SetFullDate(uint8_t date, uint8_t month, uint8_t dow, uint16_t year){ 409 | DS3231_SetDate(date); 410 | DS3231_SetMonth(month); 411 | DS3231_SetDayOfWeek(dow); 412 | DS3231_SetYear(year); 413 | } 414 | 415 | /** 416 | * @brief Decodes the raw binary value stored in registers to decimal format. 417 | * @param bin Binary-coded decimal value retrieved from register, 0 to 255. 418 | * @return Decoded decimal value. 419 | */ 420 | uint8_t DS3231_DecodeBCD(uint8_t bin) { 421 | return (((bin & 0xf0) >> 4) * 10) + (bin & 0x0f); 422 | } 423 | 424 | /** 425 | * @brief Encodes a decimal number to binaty-coded decimal for storage in registers. 426 | * @param dec Decimal number to encode. 427 | * @return Encoded binary-coded decimal value. 428 | */ 429 | uint8_t DS3231_EncodeBCD(uint8_t dec) { 430 | return (dec % 10 + ((dec / 10) << 4)); 431 | } 432 | 433 | /** 434 | * @brief Enable the 32kHz output. 435 | * @param enable Enable, DS3231_ENABLE or DS3231_DISABLE. 436 | */ 437 | void DS3231_Enable32kHzOutput(DS3231_State enable){ 438 | uint8_t status = DS3231_GetRegByte(DS3231_REG_STATUS) & 0xfb; 439 | DS3231_SetRegByte(DS3231_REG_STATUS, status | (enable << DS3231_EN32KHZ)); 440 | } 441 | 442 | /** 443 | * @brief Get the integer part of the temperature. 444 | * @return Integer part of the temperature, -127 to 127. 445 | */ 446 | int8_t DS3231_GetTemperatureInteger(){ 447 | return DS3231_GetRegByte(DS3231_TEMP_MSB); 448 | } 449 | 450 | /** 451 | * @brief Get the fractional part of the temperature to 2 decimal places. 452 | * @return Fractional part of the temperature, 0, 25, 50 or 75. 453 | */ 454 | uint8_t DS3231_GetTemperatureFraction(){ 455 | return (DS3231_GetRegByte(DS3231_TEMP_LSB) >> 6) * 25; 456 | } 457 | 458 | #ifdef __cplusplus 459 | } 460 | #endif 461 | --------------------------------------------------------------------------------