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 File Reference

: 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]
 

Detailed Description

: Main program body

Attention

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.

Macro Definition Documentation

◆ ANSI_HIDE_CURSOR

#define ANSI_HIDE_CURSOR   "\x1b[?25l"

ANSI escape sequence that hides the terminal cursor so it does not flicker on the clock line.

Definition at line 44 of file main.c.

Referenced by main().

◆ CLOCK_MARKER_ADDRESS

#define CLOCK_MARKER_ADDRESS   0U

EEPROM address of the clock marker.

Definition at line 65 of file main.c.

Referenced by readClockMarker(), and writeClockMarker().

◆ CLOCK_MARKER_MAGIC

#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().

◆ CLOCK_MARKER_SIZE

#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().

◆ CLOCK_ROW

#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().

◆ FORCE_SET_TIME

#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().

◆ SET_TIME_OFFSET_SECONDS

#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().

Function Documentation

◆ main()

int main ( void )

The application entry point.

Return values
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().

◆ parseBuildTime()

static bool parseBuildTime ( DS3231_TIME_t * time)
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).

Parameters
timeReceives the build date and time.
Return values
trueif 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().

◆ printTime()

static void printTime ( void )
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().

◆ readClockMarker()

static bool readClockMarker ( void )
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.

Return values
trueif 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().

◆ reportOscillator()

static bool reportOscillator ( void )
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.

Return values
trueif 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().

◆ setClockFromBuildTime()

static void setClockFromBuildTime ( void )
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().

◆ startClock()

static void startClock ( void )
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().

◆ writeClockMarker()

static void writeClockMarker ( void )
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().

Variable Documentation

◆ dayNames

const char* const dayNames[8]
static
Initial value:
=
{
"", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"
}

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().

◆ eeprom

AT24C32_t eeprom
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().

◆ monthNames

const char* const monthNames[13]
static
Initial value:
=
{
"", "January", "February", "March", "April", "May", "June",
"July", "August", "September", "October", "November", "December"
}

Month names, indexed by month number 1 to 12. Index 0 is unused.

Definition at line 102 of file main.c.

Referenced by printTime().

◆ rtc

DS3231_t rtc
static

The DS3231 on I2C1, set up by ds3231Init().

Definition at line 90 of file main.c.

Referenced by main(), printTime(), reportOscillator(), and setClockFromBuildTime().