H753_CPP_I2C_DS3231_RTC_01 1.0
STM32H753 DS3231 real-time clock over I2C, with an AT24C32 EEPROM marker that stops the clock being set twice, built on the STM32_DS3231 and STM32_AT24C32 libraries
Loading...
Searching...
No Matches
main.c
Go to the documentation of this file.
1/* USER CODE BEGIN Header */
18/* USER CODE END Header */
19/* Includes ------------------------------------------------------------------*/
20#include "main.h"
21
22/* Private includes ----------------------------------------------------------*/
23/* USER CODE BEGIN Includes */
24#include <stdio.h>
25#include <stdbool.h>
26#include <string.h>
27#include "DS3231.h"
28#include "AT24C32.h"
29
30/* USER CODE END Includes */
31
32/* Private typedef -----------------------------------------------------------*/
33/* USER CODE BEGIN PTD */
34
35/* USER CODE END PTD */
36
37/* Private define ------------------------------------------------------------*/
38/* USER CODE BEGIN PD */
39
41#define CLOCK_ROW 11
42
44#define ANSI_HIDE_CURSOR "\x1b[?25l"
45
50#define FORCE_SET_TIME 0
51
54#define SET_TIME_OFFSET_SECONDS 0
55
65#define CLOCK_MARKER_ADDRESS 0U
66
68#define CLOCK_MARKER_MAGIC 0x44533332U
69
71#define CLOCK_MARKER_SIZE 8U
72
75/* USER CODE END PD */
76
77/* Private macro -------------------------------------------------------------*/
78/* USER CODE BEGIN PM */
79
80/* USER CODE END PM */
81
82/* Private variables ---------------------------------------------------------*/
83
84I2C_HandleTypeDef hi2c1;
85
86UART_HandleTypeDef huart1;
87
88/* USER CODE BEGIN PV */
91
94
96static const char *const dayNames[8] =
97{
98 "", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"
99};
100
102static const char *const monthNames[13] =
103{
104 "", "January", "February", "March", "April", "May", "June",
105 "July", "August", "September", "October", "November", "December"
106};
107/* USER CODE END PV */
108
109/* Private function prototypes -----------------------------------------------*/
110void SystemClock_Config(void);
111static void MX_GPIO_Init(void);
112static void MX_I2C1_Init(void);
113static void MX_USART1_UART_Init(void);
114/* USER CODE BEGIN PFP */
115static bool reportOscillator(void);
116static bool parseBuildTime(DS3231_TIME_t *time);
117static void setClockFromBuildTime(void);
118static bool readClockMarker(void);
119static void writeClockMarker(void);
120static void startClock(void);
121static void printTime(void);
122/* USER CODE END PFP */
123
124/* Private user code ---------------------------------------------------------*/
125/* USER CODE BEGIN 0 */
126
127#ifdef REDIRECT_PRINTF
128#define PUTCHAR_PROTOTYPE int __io_putchar(int ch)
129
130PUTCHAR_PROTOTYPE
131{
132 HAL_UART_Transmit(&huart1, (uint8_t *)&ch, 1, 0xFFFF);
133
134 return ch;
135}
136#endif
137
138/* USER CODE END 0 */
139
144int main(void)
145{
146
147 /* USER CODE BEGIN 1 */
148
149 /* USER CODE END 1 */
150
151 /* MCU Configuration--------------------------------------------------------*/
152
153 /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
154 HAL_Init();
155
156 /* USER CODE BEGIN Init */
157
158 /* USER CODE END Init */
159
160 /* Configure the system clock */
161 SystemClock_Config();
162
163 /* USER CODE BEGIN SysInit */
164
165 /* USER CODE END SysInit */
166
167 /* Initialize all configured peripherals */
168 MX_GPIO_Init();
169 MX_I2C1_Init();
170 MX_USART1_UART_Init();
171 /* USER CODE BEGIN 2 */
172
173 printf("\x1b[2J\x1b[H"); // Clear the dumb terminal screen
174 printf(ANSI_HIDE_CURSOR);
175 printf("\x1b[1mDS3231 real-time clock\x1b[0m\r\n-----------------------\r\n\r\n");
176 fflush(stdout); // no newline in the sequence, so push it out now
177
178 if (ds3231Init(&rtc, &hi2c1, 0) != DS3231_OK) {
179 printf("DS3231 not found on I2C1 (HAL status %d, I2C error 0x%02lX)\r\n",
180 (int)rtc.lastStatus, (unsigned long)HAL_I2C_GetError(&hi2c1));
181 Error_Handler();
182 }
183
184 if (at24c32Init(&eeprom, &hi2c1, 7, 0) != AT24C32_OK) {
185 printf("AT24C32 EEPROM not found on I2C1 (HAL status %d, I2C error 0x%02lX)\r\n",
186 (int)eeprom.lastStatus, (unsigned long)HAL_I2C_GetError(&hi2c1));
187 Error_Handler();
188 }
189
190 startClock();
191
192 /* USER CODE END 2 */
193
194 /* Infinite loop */
195 /* USER CODE BEGIN WHILE */
196 while (1)
197 {
198 /* USER CODE END WHILE */
199
200 /* USER CODE BEGIN 3 */
201 printTime();
202 HAL_Delay(1000);
203 }
204 /* USER CODE END 3 */
205}
206
211void SystemClock_Config(void)
212{
213 RCC_OscInitTypeDef RCC_OscInitStruct = {0};
214 RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};
215
218 HAL_PWREx_ConfigSupply(PWR_LDO_SUPPLY);
219
222 __HAL_PWR_VOLTAGESCALING_CONFIG(PWR_REGULATOR_VOLTAGE_SCALE0);
223
224 while(!__HAL_PWR_GET_FLAG(PWR_FLAG_VOSRDY)) {}
225
229 RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI;
230 RCC_OscInitStruct.HSIState = RCC_HSI_DIV1;
231 RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;
232 RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;
233 RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;
234 RCC_OscInitStruct.PLL.PLLM = 4;
235 RCC_OscInitStruct.PLL.PLLN = 60;
236 RCC_OscInitStruct.PLL.PLLP = 2;
237 RCC_OscInitStruct.PLL.PLLQ = 4;
238 RCC_OscInitStruct.PLL.PLLR = 2;
239 RCC_OscInitStruct.PLL.PLLRGE = RCC_PLL1VCIRANGE_3;
240 RCC_OscInitStruct.PLL.PLLVCOSEL = RCC_PLL1VCOWIDE;
241 RCC_OscInitStruct.PLL.PLLFRACN = 0;
242 if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)
243 {
244 Error_Handler();
245 }
246
249 RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK
250 |RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2
251 |RCC_CLOCKTYPE_D3PCLK1|RCC_CLOCKTYPE_D1PCLK1;
252 RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;
253 RCC_ClkInitStruct.SYSCLKDivider = RCC_SYSCLK_DIV1;
254 RCC_ClkInitStruct.AHBCLKDivider = RCC_HCLK_DIV2;
255 RCC_ClkInitStruct.APB3CLKDivider = RCC_APB3_DIV2;
256 RCC_ClkInitStruct.APB1CLKDivider = RCC_APB1_DIV2;
257 RCC_ClkInitStruct.APB2CLKDivider = RCC_APB2_DIV2;
258 RCC_ClkInitStruct.APB4CLKDivider = RCC_APB4_DIV2;
259
260 if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_4) != HAL_OK)
261 {
262 Error_Handler();
263 }
264}
265
271static void MX_I2C1_Init(void)
272{
273
274 /* USER CODE BEGIN I2C1_Init 0 */
275
276 /* USER CODE END I2C1_Init 0 */
277
278 /* USER CODE BEGIN I2C1_Init 1 */
279
280 /* USER CODE END I2C1_Init 1 */
281 hi2c1.Instance = I2C1;
282 hi2c1.Init.Timing = 0x307075B1;
283 hi2c1.Init.OwnAddress1 = 0;
284 hi2c1.Init.AddressingMode = I2C_ADDRESSINGMODE_7BIT;
285 hi2c1.Init.DualAddressMode = I2C_DUALADDRESS_DISABLE;
286 hi2c1.Init.OwnAddress2 = 0;
287 hi2c1.Init.OwnAddress2Masks = I2C_OA2_NOMASK;
288 hi2c1.Init.GeneralCallMode = I2C_GENERALCALL_DISABLE;
289 hi2c1.Init.NoStretchMode = I2C_NOSTRETCH_DISABLE;
290 if (HAL_I2C_Init(&hi2c1) != HAL_OK)
291 {
292 Error_Handler();
293 }
294
297 if (HAL_I2CEx_ConfigAnalogFilter(&hi2c1, I2C_ANALOGFILTER_ENABLE) != HAL_OK)
298 {
299 Error_Handler();
300 }
301
304 if (HAL_I2CEx_ConfigDigitalFilter(&hi2c1, 0) != HAL_OK)
305 {
306 Error_Handler();
307 }
308 /* USER CODE BEGIN I2C1_Init 2 */
309
310 /* USER CODE END I2C1_Init 2 */
311
312}
313
319static void MX_USART1_UART_Init(void)
320{
321
322 /* USER CODE BEGIN USART1_Init 0 */
323
324 /* USER CODE END USART1_Init 0 */
325
326 /* USER CODE BEGIN USART1_Init 1 */
327
328 /* USER CODE END USART1_Init 1 */
329 huart1.Instance = USART1;
330 huart1.Init.BaudRate = 19200;
331 huart1.Init.WordLength = UART_WORDLENGTH_8B;
332 huart1.Init.StopBits = UART_STOPBITS_1;
333 huart1.Init.Parity = UART_PARITY_NONE;
334 huart1.Init.Mode = UART_MODE_TX_RX;
335 huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
336 huart1.Init.OverSampling = UART_OVERSAMPLING_16;
337 huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
338 huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
339 huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
340 if (HAL_UART_Init(&huart1) != HAL_OK)
341 {
342 Error_Handler();
343 }
344 if (HAL_UARTEx_SetTxFifoThreshold(&huart1, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
345 {
346 Error_Handler();
347 }
348 if (HAL_UARTEx_SetRxFifoThreshold(&huart1, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
349 {
350 Error_Handler();
351 }
352 if (HAL_UARTEx_DisableFifoMode(&huart1) != HAL_OK)
353 {
354 Error_Handler();
355 }
356 /* USER CODE BEGIN USART1_Init 2 */
357
358 /* USER CODE END USART1_Init 2 */
359
360}
361
367static void MX_GPIO_Init(void)
368{
369 GPIO_InitTypeDef GPIO_InitStruct = {0};
370 /* USER CODE BEGIN MX_GPIO_Init_1 */
371
372 /* USER CODE END MX_GPIO_Init_1 */
373
374 /* GPIO Ports Clock Enable */
375 __HAL_RCC_GPIOC_CLK_ENABLE();
376 __HAL_RCC_GPIOH_CLK_ENABLE();
377 __HAL_RCC_GPIOD_CLK_ENABLE();
378 __HAL_RCC_GPIOA_CLK_ENABLE();
379 __HAL_RCC_GPIOB_CLK_ENABLE();
380
381 /*Configure GPIO pins : STLINK_RX_Pin STLINK_TX_Pin */
382 GPIO_InitStruct.Pin = STLINK_RX_Pin|STLINK_TX_Pin;
383 GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
384 GPIO_InitStruct.Pull = GPIO_NOPULL;
385 GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
386 GPIO_InitStruct.Alternate = GPIO_AF7_USART3;
387 HAL_GPIO_Init(GPIOD, &GPIO_InitStruct);
388
389 /* USER CODE BEGIN MX_GPIO_Init_2 */
390
391 /* USER CODE END MX_GPIO_Init_2 */
392}
393
394/* USER CODE BEGIN 4 */
395
396
403void _Error_Handler(const char *file, int line)
404{
405 __disable_irq();
406
407#ifdef REDIRECT_PRINTF
408 char buf[80];
409
410 snprintf(buf, sizeof(buf),
411 "Trapped in _Error_Handler(). Called from: %s, line: %d\r\n",
412 file, line);
413 printf("%s", buf);
414#endif
415
416 /* User can add an implementation to report the HAL error return state. */
417 while(1)
418 {
419 }
420}
421
422
431static bool reportOscillator(void)
432{
433 bool stopped = false;
434
435 if (ds3231IsOscillatorStopped(&rtc, &stopped) != DS3231_OK) {
436 printf("Could not read the DS3231 status register\r\n");
437 Error_Handler();
438 return false;
439 }
440
441 if (stopped) {
442 printf("Oscillator : stop flag SET, the time is not valid until the clock is set\r\n");
443 } else {
444 printf("Oscillator : stop flag clear, the time is valid\r\n");
445 }
446 return stopped;
447}
448
458{
459 static const char months[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
460 const char *date = __DATE__; /* "Mmm dd yyyy", day padded with a space */
461 const char *clock = __TIME__; /* "hh:mm:ss" */
462 const char *found = NULL;
463 uint8_t i;
464
465 for (i = 0U; i < 12U; i++) {
466 if (strncmp(&months[i * 3U], date, 3U) == 0) {
467 found = &months[i * 3U];
468 time->month = (uint8_t)(i + 1U);
469 }
470 }
471 if (found == NULL) {
472 return false;
473 }
474
475 time->day = (uint8_t)(((date[4] == ' ') ? 0 : (date[4] - '0')) * 10 + (date[5] - '0'));
476 time->year = (uint16_t)((date[7] - '0') * 1000 + (date[8] - '0') * 100 + (date[9] - '0') * 10 + (date[10] - '0'));
477 time->hour = (uint8_t)((clock[0] - '0') * 10 + (clock[1] - '0'));
478 time->minute = (uint8_t)((clock[3] - '0') * 10 + (clock[4] - '0'));
479 time->second = (uint8_t)((clock[6] - '0') * 10 + (clock[7] - '0'));
480 time->weekday = 0U;
481
482 return ds3231IsTimeValid(time);
483}
484
491static void setClockFromBuildTime(void)
492{
493 DS3231_TIME_t time;
494 uint32_t epoch;
495
496 if (!parseBuildTime(&time) || ds3231TimeToEpoch(&time, &epoch) != DS3231_OK ||
497 ds3231EpochToTime((uint32_t)((int32_t)epoch + SET_TIME_OFFSET_SECONDS), &time) != DS3231_OK) {
498 printf("The build time cannot be used to set the clock\r\n");
499 Error_Handler();
500 return;
501 }
502
504 printf("Setting the DS3231 failed\r\n");
505 Error_Handler();
506 return;
507 }
508
509 printf("Clock : set to the build time %04d-%02d-%02d %02d:%02d:%02d (offset %d s)\r\n",
510 (int)time.year, (int)time.month, (int)time.day,
511 (int)time.hour, (int)time.minute, (int)time.second, (int)SET_TIME_OFFSET_SECONDS);
512}
513
521static bool readClockMarker(void)
522{
523 uint8_t raw[CLOCK_MARKER_SIZE];
524 uint32_t magic;
525 uint32_t inverse;
526
527 if (at24c32Read(&eeprom, CLOCK_MARKER_ADDRESS, raw, sizeof(raw)) != AT24C32_OK) {
528 printf("Could not read the clock marker from the EEPROM\r\n");
529 Error_Handler();
530 return false;
531 }
532
533 memcpy(&magic, &raw[0], sizeof(magic));
534 memcpy(&inverse, &raw[4], sizeof(inverse));
535 return (magic == CLOCK_MARKER_MAGIC) && (inverse == (uint32_t)~CLOCK_MARKER_MAGIC);
536}
537
543static void writeClockMarker(void)
544{
545 uint8_t raw[CLOCK_MARKER_SIZE];
546 uint32_t magic = CLOCK_MARKER_MAGIC;
547 uint32_t inverse = (uint32_t)~CLOCK_MARKER_MAGIC;
548
549 memcpy(&raw[0], &magic, sizeof(magic));
550 memcpy(&raw[4], &inverse, sizeof(inverse));
551
552 if (at24c32Write(&eeprom, CLOCK_MARKER_ADDRESS, raw, sizeof(raw)) != AT24C32_OK || !readClockMarker()) {
553 printf("Writing the clock marker to the EEPROM failed\r\n");
554 Error_Handler();
555 }
556}
557
566static void startClock(void)
567{
568 bool stopped = reportOscillator();
569 bool markerFound = readClockMarker();
570
571 if (FORCE_SET_TIME) {
572 printf("EEPROM : FORCE_SET_TIME is 1, setting the clock\r\n");
573 } else if (markerFound) {
574 printf("EEPROM : marker found, the clock was set before\r\n");
575 printf("Clock : left alone\r\n");
576 if (stopped) {
577 printf("Warning : the oscillator stopped since the clock was set.\r\n");
578 printf(" Set FORCE_SET_TIME to 1 and rebuild to set it again.\r\n");
579 }
580 return;
581 } else {
582 printf("EEPROM : no marker, first run on this board\r\n");
583 }
584
587 printf("EEPROM : marker written\r\n");
588
589 if (FORCE_SET_TIME) {
590 printf("Reminder : set FORCE_SET_TIME to 0 and rebuild, or every reset\r\n");
591 printf(" sets the clock back to this build time.\r\n");
592 }
593}
594
605static void printTime(void)
606{
607 DS3231_TIME_t now;
608 DS3231_Status_t status = ds3231GetTime(&rtc, &now);
609
610 if (status == DS3231_ERR_INVALID_DATA) {
611 printf("\x1b[%d;1H\x1b[K The DS3231 does not hold a valid time yet\x1b[%d;1H\x1b[K", CLOCK_ROW, CLOCK_ROW + 1);
612 fflush(stdout);
613 return;
614 }
615 if (status != DS3231_OK) {
616 printf("ds3231GetTime failed, status %d\r\n", (int)status);
617 Error_Handler();
618 return;
619 }
620
621 if (now.weekday < 1U || now.weekday > 7U || now.month < 1U || now.month > 12U) {
622 printf("\x1b[%d;1H\x1b[K The DS3231 returned a date that cannot be named\x1b[%d;1H\x1b[K", CLOCK_ROW, CLOCK_ROW + 1);
623 fflush(stdout);
624 return;
625 }
626
627 printf("\x1b[%d;1H\x1b[K %s, %s %d, %04d\x1b[%d;1H\x1b[K \x1b[1m%02d:%02d:%02d\x1b[0m",
628 CLOCK_ROW, dayNames[now.weekday], monthNames[now.month], (int)now.day, (int)now.year,
629 CLOCK_ROW + 1, (int)now.hour, (int)now.minute, (int)now.second);
630 fflush(stdout);
631}
632
633/* USER CODE END 4 */
634
635
636#ifdef USE_FULL_ASSERT
644void assert_failed(uint8_t *file, uint32_t line)
645{
646 /* USER CODE BEGIN 6 */
647 /* assert_param() can fire from inside any HAL call -- including before
648 * REDIRECT_PRINTF's UART is fully set up, or from an unusual calling
649 * context -- so this only attempts to report when REDIRECT_PRINTF is
650 * available, then halts either way. Continuing after a failed HAL
651 * parameter check is undefined behavior, not something safe to log
652 * and ignore. */
653 __disable_irq();
654
655#ifdef REDIRECT_PRINTF
656 {
657 char buf[96];
658
659 snprintf(buf, sizeof(buf),
660 "assert_param failed: file %s, line %lu\r\n",
661 (char *)file, (unsigned long)line);
662 printf("%s", buf);
663 }
664#endif
665
666 while (1)
667 {
668 }
669 /* USER CODE END 6 */
670}
671#endif /* USE_FULL_ASSERT */
Types, constants and function prototypes of the STM32_AT24C32 driver.
AT24C32_Status_t at24c32Init(AT24C32_t *dev, I2C_HandleTypeDef *hi2c, uint8_t addressPins, uint8_t maxAttempts)
Set up a driver handle and check that an AT24C32 answers on the bus.
Definition AT24C32.c:131
AT24C32_Status_t at24c32Read(AT24C32_t *dev, uint16_t memAddress, uint8_t *data, uint16_t length)
Read bytes from the memory.
Definition AT24C32.c:166
@ AT24C32_OK
Definition AT24C32.h:101
AT24C32_Status_t at24c32Write(AT24C32_t *dev, uint16_t memAddress, const uint8_t *data, uint16_t length)
Write bytes to the memory.
Definition AT24C32.c:192
Types, constants and function prototypes of the STM32_DS3231 driver.
DS3231_Status_t ds3231SetTime(DS3231_t *dev, const DS3231_TIME_t *time)
Set the date and time.
Definition DS3231.c:419
DS3231_Status_t ds3231TimeToEpoch(const DS3231_TIME_t *time, uint32_t *epochSeconds)
Convert a date and time to seconds since 1970-01-01 00:00:00 (UTC, no leap seconds).
Definition DS3231.c:243
DS3231_Status_t ds3231EpochToTime(uint32_t epochSeconds, DS3231_TIME_t *time)
Convert seconds since 1970-01-01 00:00:00 (UTC, no leap seconds) to a date and time.
Definition DS3231.c:267
DS3231_Status_t
Definition DS3231.h:94
@ DS3231_OK
Definition DS3231.h:95
@ DS3231_ERR_INVALID_DATA
Definition DS3231.h:98
DS3231_Status_t ds3231GetTime(DS3231_t *dev, DS3231_TIME_t *time)
Read the current date and time.
Definition DS3231.c:343
bool ds3231IsTimeValid(const DS3231_TIME_t *time)
Check that a date and time are valid for the DS3231.
Definition DS3231.c:216
DS3231_Status_t ds3231ClearOscillatorStopFlag(DS3231_t *dev)
Clear the oscillator stop flag.
Definition DS3231.c:520
DS3231_Status_t ds3231IsOscillatorStopped(DS3231_t *dev, bool *stopped)
Find out whether the oscillator has stopped since the flag was last cleared.
Definition DS3231.c:494
DS3231_Status_t ds3231Init(DS3231_t *dev, I2C_HandleTypeDef *hi2c, uint8_t maxAttempts)
Set up a driver handle and check that a DS3231 answers on the bus.
Definition DS3231.c:302
static bool parseBuildTime(DS3231_TIME_t *time)
Convert the compile date and time (DATE and TIME) to a DS3231_TIME_t.
Definition main.c:457
static bool reportOscillator(void)
Report whether the DS3231 oscillator stop flag is set.
Definition main.c:431
#define FORCE_SET_TIME
Definition main.c:50
static AT24C32_t eeprom
Definition main.c:93
static void setClockFromBuildTime(void)
Set the DS3231 to the build time plus SET_TIME_OFFSET_SECONDS and clear the oscillator stop flag.
Definition main.c:491
#define ANSI_HIDE_CURSOR
Definition main.c:44
int main(void)
The application entry point.
Definition main.c:144
#define CLOCK_MARKER_MAGIC
Definition main.c:68
static const char *const dayNames[8]
Definition main.c:96
#define CLOCK_MARKER_ADDRESS
Definition main.c:65
static void startClock(void)
Decide at start-up whether to set the clock, and do it.
Definition main.c:566
static bool readClockMarker(void)
Tell whether the EEPROM holds the "clock already set" marker.
Definition main.c:521
#define CLOCK_ROW
Definition main.c:41
static void writeClockMarker(void)
Store the "clock already set" marker in the EEPROM and read it back to check it.
Definition main.c:543
#define CLOCK_MARKER_SIZE
Definition main.c:71
static const char *const monthNames[13]
Definition main.c:102
#define SET_TIME_OFFSET_SECONDS
Definition main.c:54
static DS3231_t rtc
Definition main.c:90
static void printTime(void)
Read the DS3231 and redraw the day, date and time on two terminal lines, for example "Wednesday,...
Definition main.c:605
: Header for main.c file. This file contains the common defines of the application.
HAL_StatusTypeDef lastStatus
Definition AT24C32.h:112
A calendar date and time, always 24-hour clock.
Definition DS3231.h:109
uint8_t second
Definition DS3231.h:116
uint8_t weekday
Definition DS3231.h:113
uint8_t month
Definition DS3231.h:111
uint8_t minute
Definition DS3231.h:115
uint8_t hour
Definition DS3231.h:114
uint16_t year
Definition DS3231.h:110
uint8_t day
Definition DS3231.h:112
HAL_StatusTypeDef lastStatus
Definition DS3231.h:123