├── 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 | 
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 |
--------------------------------------------------------------------------------