|
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
|
: Main program body More...
#include "main.h"#include <stdio.h>#include <stdbool.h>#include <string.h>#include "DS3231.h"#include "AT24C32.h"Go to the source code of this file.
Macros | |
| #define | CLOCK_ROW 11 |
| #define | ANSI_HIDE_CURSOR "\x1b[?25l" |
| #define | FORCE_SET_TIME 0 |
| #define | SET_TIME_OFFSET_SECONDS 0 |
Clock marker | |
The "clock already set" marker kept in the AT24C32: a magic number followed by its bitwise inverse, 8 bytes at address 0. A write cut short by a power loss leaves a pair that does not match, which is read as "no marker". See startClock(), readClockMarker() and writeClockMarker(). | |
| #define | CLOCK_MARKER_ADDRESS 0U |
| #define | CLOCK_MARKER_MAGIC 0x44533332U |
| #define | CLOCK_MARKER_SIZE 8U |
Functions | |
| static bool | reportOscillator (void) |
| Report whether the DS3231 oscillator stop flag is set. | |
| static bool | parseBuildTime (DS3231_TIME_t *time) |
| Convert the compile date and time (DATE and TIME) to a DS3231_TIME_t. | |
| static void | setClockFromBuildTime (void) |
| Set the DS3231 to the build time plus SET_TIME_OFFSET_SECONDS and clear the oscillator stop flag. | |
| static bool | readClockMarker (void) |
| Tell whether the EEPROM holds the "clock already set" marker. | |
| static void | writeClockMarker (void) |
| Store the "clock already set" marker in the EEPROM and read it back to check it. | |
| static void | startClock (void) |
| Decide at start-up whether to set the clock, and do it. | |
| static void | printTime (void) |
| Read the DS3231 and redraw the day, date and time on two terminal lines, for example "Wednesday, October 7, 2026" above a bold "23:30:58". | |
| int | main (void) |
| The application entry point. | |
Variables | |
| static DS3231_t | rtc |
| static AT24C32_t | eeprom |
| static const char *const | dayNames [8] |
| static const char *const | monthNames [13] |
: Main program body
Copyright (c) 2026 STMicroelectronics. All rights reserved.
This software is licensed under terms that can be found in the LICENSE file in the root directory of this software component. If no LICENSE file comes with this software, it is provided AS-IS.
Definition in file main.c.
| #define ANSI_HIDE_CURSOR "\x1b[?25l" |
| #define CLOCK_MARKER_ADDRESS 0U |
EEPROM address of the clock marker.
Definition at line 65 of file main.c.
Referenced by readClockMarker(), and writeClockMarker().
| #define CLOCK_MARKER_MAGIC 0x44533332U |
First half of the marker: the magic number (the ASCII letters "DS32"). The second half is its bitwise inverse.
Definition at line 68 of file main.c.
Referenced by readClockMarker(), and writeClockMarker().
| #define CLOCK_MARKER_SIZE 8U |
Size of the marker in bytes: the magic number plus its inverse, 4 bytes each.
Definition at line 71 of file main.c.
Referenced by readClockMarker(), and writeClockMarker().
| #define CLOCK_ROW 11 |
Terminal row of the date line of the clock (the time is on the row below); the start-up messages above it stay put while the clock redraws in place.
Definition at line 41 of file main.c.
Referenced by printTime().
| #define FORCE_SET_TIME 0 |
1 = at start-up, set the DS3231 from the time this file was compiled (DATE and TIME) even though the EEPROM marker says it was set before. Build and run once with it at 1, then set it back to 0 and rebuild, or every reset sets the clock back to the old build time. With 0 the clock is set only the first time, when the EEPROM holds no marker.
Definition at line 50 of file main.c.
Referenced by startClock().
| #define SET_TIME_OFFSET_SECONDS 0 |
Seconds added to the build time to cover the delay between compiling this file and the program starting (compile, link, flash). Measure the error once and enter it here; 0 is fine to start with.
Definition at line 54 of file main.c.
Referenced by setClockFromBuildTime().
| int main | ( | void | ) |
The application entry point.
| int |
Definition at line 144 of file main.c.
References ANSI_HIDE_CURSOR, AT24C32_OK, at24c32Init(), DS3231_OK, ds3231Init(), eeprom, AT24C32_t::lastStatus, DS3231_t::lastStatus, printTime(), rtc, and startClock().
|
static |
Convert the compile date and time (DATE and TIME) to a DS3231_TIME_t.
DATE looks like "Oct 8 2026" and TIME like "22:50:47"; both are the local time of the computer that compiled this file. The weekday member is not filled in (ds3231SetTime() works it out).
| time | Receives the build date and time. |
| true | if both strings were parsed into a valid date and time, false otherwise. |
Definition at line 457 of file main.c.
References DS3231_TIME_t::day, ds3231IsTimeValid(), DS3231_TIME_t::hour, DS3231_TIME_t::minute, DS3231_TIME_t::month, DS3231_TIME_t::second, DS3231_TIME_t::weekday, and DS3231_TIME_t::year.
Referenced by setClockFromBuildTime().
|
static |
Read the DS3231 and redraw the day, date and time on two terminal lines, for example "Wednesday, October 7, 2026" above a bold "23:30:58".
Moves the cursor to row CLOCK_ROW (date) and the row below (time) and clears each line before printing, so the clock updates in place instead of scrolling. Prints a message on that line instead when the registers hold no valid time yet. Flushes stdout after each redraw: the line has no newline, and stdout is line-buffered, so without the flush the text would sit in the buffer instead of appearing on the terminal. Halts through Error_Handler() if the read fails.
Definition at line 605 of file main.c.
References CLOCK_ROW, DS3231_TIME_t::day, dayNames, DS3231_ERR_INVALID_DATA, DS3231_OK, ds3231GetTime(), DS3231_TIME_t::hour, DS3231_TIME_t::minute, DS3231_TIME_t::month, monthNames, rtc, DS3231_TIME_t::second, DS3231_TIME_t::weekday, and DS3231_TIME_t::year.
Referenced by main().
|
static |
Tell whether the EEPROM holds the "clock already set" marker.
The marker is CLOCK_MARKER_MAGIC followed by its bitwise inverse; anything else, including a half written marker, counts as not found. Halts through Error_Handler() if the EEPROM cannot be read.
| true | if a valid marker is stored, false if not. |
Definition at line 521 of file main.c.
References AT24C32_OK, at24c32Read(), CLOCK_MARKER_ADDRESS, CLOCK_MARKER_MAGIC, CLOCK_MARKER_SIZE, and eeprom.
Referenced by startClock(), and writeClockMarker().
|
static |
Report whether the DS3231 oscillator stop flag is set.
A set flag means the oscillator has stopped since the flag was last cleared (first power-up, or both VCC and the battery were too low), so the stored time cannot be trusted. Halts through Error_Handler() if the status register cannot be read.
| true | if the oscillator stop flag is set, false if it is clear. |
Definition at line 431 of file main.c.
References DS3231_OK, ds3231IsOscillatorStopped(), and rtc.
Referenced by startClock().
|
static |
Set the DS3231 to the build time plus SET_TIME_OFFSET_SECONDS and clear the oscillator stop flag.
The chip then holds the local time of the computer that compiled this file (no time-zone conversion). Halts through Error_Handler() if the build time cannot be used or a write fails.
Definition at line 491 of file main.c.
References DS3231_TIME_t::day, DS3231_OK, ds3231ClearOscillatorStopFlag(), ds3231EpochToTime(), ds3231SetTime(), ds3231TimeToEpoch(), DS3231_TIME_t::hour, DS3231_TIME_t::minute, DS3231_TIME_t::month, parseBuildTime(), rtc, DS3231_TIME_t::second, SET_TIME_OFFSET_SECONDS, and DS3231_TIME_t::year.
Referenced by startClock().
|
static |
Decide at start-up whether to set the clock, and do it.
With no marker in the EEPROM (first run on this board) or with FORCE_SET_TIME at 1, the clock is set from the build time and the marker is written after that succeeded, so a failure leaves no marker. Otherwise the clock is left alone; if the oscillator stop flag is set anyway the clock lost power, and a message says to set FORCE_SET_TIME to 1.
Definition at line 566 of file main.c.
References FORCE_SET_TIME, readClockMarker(), reportOscillator(), setClockFromBuildTime(), and writeClockMarker().
Referenced by main().
|
static |
Store the "clock already set" marker in the EEPROM and read it back to check it.
Halts through Error_Handler() if the write fails or the marker does not read back as valid.
Definition at line 543 of file main.c.
References AT24C32_OK, at24c32Write(), CLOCK_MARKER_ADDRESS, CLOCK_MARKER_MAGIC, CLOCK_MARKER_SIZE, eeprom, and readClockMarker().
Referenced by startClock().
|
static |
Day names, indexed by the driver's weekday number: 1 = Monday to 7 = Sunday. Index 0 is unused.
Definition at line 96 of file main.c.
Referenced by printTime().
|
static |
The AT24C32 EEPROM on I2C1 (address pins all high, 0x57), set up by at24c32Init().
Definition at line 93 of file main.c.
Referenced by main(), readClockMarker(), and writeClockMarker().
|
static |
Month names, indexed by month number 1 to 12. Index 0 is unused.
Definition at line 102 of file main.c.
Referenced by printTime().
|
static |
The DS3231 on I2C1, set up by ds3231Init().
Definition at line 90 of file main.c.
Referenced by main(), printTime(), reportOscillator(), and setClockFromBuildTime().