Skip to content

Commit 5fcb571

Browse files
committed
chore(examples): add RTCReset
Signed-off-by: Frederic Pillon <[email protected]>
1 parent 47631ef commit 5fcb571

File tree

1 file changed

+221
-0
lines changed

1 file changed

+221
-0
lines changed

examples/RTCReset/RTCReset.ino

Lines changed: 221 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,221 @@
1+
/*
2+
RTCReset
3+
4+
This sketch allows to test STM32RTC after a software reset or power off
5+
with VBat. Including Alarm A and B management.
6+
7+
Creation 17 jan 2023
8+
by Frederic Pillon for STMicroelectronics
9+
10+
This example code is in the public domain.
11+
12+
https://github.com/stm32duino/STM32RTC
13+
14+
*/
15+
#include <STM32RTC.h>
16+
17+
/* Get the rtc object */
18+
STM32RTC& rtc = STM32RTC::getInstance();
19+
20+
/* Change these values to set the current initial time
21+
22+
format: date: "Dec 31 2022" and time: "23:59:56"
23+
by default use built date and time
24+
*/
25+
static const char* mydate = __DATE__;
26+
static const char* mytime = __TIME__;
27+
//static const char* mydate = "Dec 31 2022";
28+
//static const char* mytime = "23:59:56";
29+
30+
/* Declare it volatile since it's incremented inside an interrupt */
31+
volatile int alarmMatch_counter = 0;
32+
volatile int alarmMatchB_counter = 0;
33+
34+
typedef struct {
35+
uint32_t next;
36+
bool alarm_a;
37+
} cb_data_t;
38+
39+
static cb_data_t atime = { 2222, true};
40+
#ifdef RTC_ALARM_B
41+
static cb_data_t btime = { 3333, false};
42+
#endif
43+
static byte seconds = 0;
44+
static byte minutes = 0;
45+
static byte hours = 0;
46+
static uint32_t subSeconds = 0;
47+
48+
static byte weekDay = 1;
49+
static byte day = 0;
50+
static byte month = 0;
51+
static byte year = 0;
52+
static STM32RTC::Hour_Format hourFormat = STM32RTC::HOUR_24;
53+
static STM32RTC::AM_PM period = STM32RTC::AM;
54+
55+
#ifndef USER_BTN
56+
#define USER_BTN PA0
57+
#endif
58+
59+
static uint8_t conv2d(const char* p) {
60+
uint8_t v = 0;
61+
if ('0' <= *p && *p <= '9')
62+
v = *p - '0';
63+
return 10 * v + *++p - '0';
64+
}
65+
66+
// sample input: date = "Dec 26 2009", time = "12:34:56"
67+
void initDateTime (void) {
68+
Serial.printf("Build date & time %s, %s\n", mydate, mytime);
69+
70+
year = conv2d(mydate + 9);
71+
// Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec
72+
switch (mydate[0]) {
73+
case 'J': month = (mydate[1] == 'a') ? 1 : ((mydate[2] == 'n') ? 6 : 7); break;
74+
case 'F': month = 2; break;
75+
case 'A': month = mydate[2] == 'r' ? 4 : 8; break;
76+
case 'M': month = mydate[2] == 'r' ? 3 : 5; break;
77+
case 'S': month = 9; break;
78+
case 'O': month = 10; break;
79+
case 'N': month = 11; break;
80+
case 'D': month = 12; break;
81+
}
82+
day = conv2d(mydate + 4);
83+
hours = conv2d(mytime);
84+
if (hourFormat == rtc.HOUR_12) {
85+
period = hours >= 12 ? rtc.PM : rtc.AM;
86+
hours = hours >= 13 ? hours - 12 : (hours < 1 ? hours + 12 : hours);
87+
}
88+
minutes = conv2d(mytime + 3);
89+
seconds = conv2d(mytime + 6);
90+
}
91+
92+
void setup()
93+
{
94+
pinMode(USER_BTN, INPUT_PULLUP);
95+
int32_t default_state = digitalRead(USER_BTN);
96+
97+
Serial.begin(9600);
98+
while (!Serial);
99+
// Wait user input to start
100+
while (digitalRead(USER_BTN) == default_state);
101+
// Convenient function to init date and time variables
102+
initDateTime();
103+
104+
// Select RTC clock source: LSI_CLOCK, LSE_CLOCK or HSE_CLOCK.
105+
// By default the LSI is selected as source.
106+
// rtc.setClockSource(STM32RTC::LSE_CLOCK);
107+
108+
// In any case attach a callback to the RTC alarm interrupt.
109+
rtc.attachInterrupt(alarmMatch, &atime);
110+
#ifdef RTC_ALARM_B
111+
rtc.attachInterrupt(alarmMatch, &btime, STM32RTC::ALARM_B);
112+
#endif
113+
rtc.begin(); // Initialize RTC 24H format
114+
if (!rtc.isTimeSet()) {
115+
Serial.printf("RTC time not set\n Set it.\n");
116+
// Set the time
117+
rtc.setTime(hours, minutes, seconds);
118+
rtc.setDate(weekDay, day, month, year);
119+
// ALARM_A (default argument)
120+
rtc.setAlarmDay(day);
121+
rtc.setAlarmTime(hours, minutes, seconds + 5, 567);
122+
rtc.enableAlarm(rtc.MATCH_DHHMMSS);
123+
#ifdef RTC_ALARM_B
124+
// ALARM_B
125+
rtc.setAlarmDay(day, STM32RTC::ALARM_B);
126+
rtc.setAlarmTime(hours, minutes, seconds + 5, 567, STM32RTC::ALARM_B);
127+
rtc.enableAlarm(rtc.MATCH_DHHMMSS, STM32RTC::ALARM_B);
128+
#endif
129+
} else {
130+
// RTC already initialized
131+
time_t epoc, alarm_epoc;
132+
if (rtc.isAlarmEnabled()) {
133+
rtc.enableAlarm(rtc.MATCH_DHHMMSS);
134+
alarm_epoc = rtc.getAlarmEpoch();
135+
epoc = rtc.getEpoch();
136+
if (difftime(alarm_epoc, epoc) <= 0) {
137+
Serial.printf("Alarm A was enabled and expired, force callback call\n");
138+
alarmMatch(&atime);
139+
} else {
140+
Serial.printf("Alarm A was enabled and restored\n");
141+
}
142+
}
143+
#ifdef RTC_ALARM_B
144+
// ALARM_B
145+
if (rtc.isAlarmEnabled(STM32RTC::ALARM_B)) {
146+
rtc.enableAlarm(rtc.MATCH_DHHMMSS, STM32RTC::ALARM_B);
147+
alarm_epoc = rtc.getAlarmEpoch(STM32RTC::ALARM_B);
148+
epoc = rtc.getEpoch();
149+
if (difftime(alarm_epoc, epoc) <= 0) {
150+
Serial.printf("Alarm B was enabled and expired, force callback call\n");
151+
alarmMatch(&btime);
152+
} else {
153+
Serial.printf("Alarm B was enabled and restored\n");
154+
}
155+
}
156+
#endif
157+
Serial.printf("RTC time already set\n");
158+
}
159+
Serial.printf("Alarm A enable status: %s\n", (rtc.isAlarmEnabled(STM32RTC::ALARM_A)) ? "True" : "False");
160+
#ifdef RTC_ALARM_B
161+
Serial.printf("Alarm B enable status: %s\n", (rtc.isAlarmEnabled(STM32RTC::ALARM_B)) ? "True" : "False");
162+
#else
163+
Serial.println("Alarm B not available.");
164+
#endif
165+
}
166+
167+
void loop()
168+
{
169+
rtc.getTime(&hours, &minutes, &seconds, &subSeconds, &period);
170+
// Print current date & time
171+
Serial.printf("\n%02d/%02d/%02d %02d:%02d:%02d.%03d\n", rtc.getDay(), rtc.getMonth(), rtc.getYear(), hours, minutes, seconds, subSeconds);
172+
// Print current alarm configuration
173+
Serial.printf("Alarm A: %02d %02d:%02d:%02d.%03d\n", rtc.getAlarmDay(), rtc.getAlarmHours(), rtc.getAlarmMinutes(), rtc.getAlarmSeconds(), rtc.getAlarmSubSeconds());
174+
#ifdef RTC_ALARM_B
175+
Serial.printf("Alarm B: %02d %02d:%02d:%02d.%03d\n", rtc.getAlarmDay(STM32RTC::ALARM_B), rtc.getAlarmHours(STM32RTC::ALARM_B), rtc.getAlarmMinutes(STM32RTC::ALARM_B), rtc.getAlarmSeconds(STM32RTC::ALARM_B), rtc.getAlarmSubSeconds(STM32RTC::ALARM_B));
176+
#endif
177+
delay(1000);
178+
}
179+
180+
void alarmMatch(void *data)
181+
{
182+
time_t epoc;
183+
uint32_t epoc_ms;
184+
uint32_t sec = 0;
185+
uint32_t _millis = 1000;
186+
cb_data_t cbdata = {.next = 1000, .alarm_a = true};
187+
if (data != NULL) {
188+
cbdata.next = ((cb_data_t*)data)->next;
189+
cbdata.alarm_a = ((cb_data_t*)data)->alarm_a;
190+
_millis = cbdata.next;
191+
}
192+
193+
sec = _millis / 1000;
194+
#if !defined(RTC_SSR_SS)
195+
// Minimum is 1 second
196+
if (sec == 0) {
197+
sec = 1;
198+
}
199+
epoc = rtc.getEpoch(&epoc_ms);
200+
#else
201+
_millis = _millis % 1000;
202+
epoc = rtc.getEpoch(&epoc_ms);
203+
204+
// Update epoch_ms - might need to add a second to epoch
205+
epoc_ms += _millis;
206+
if (epoc_ms >= 1000) {
207+
sec ++;
208+
epoc_ms -= 1000;
209+
}
210+
#endif
211+
if (cbdata.alarm_a) {
212+
Serial.printf("\t\t\tAlarm A Match %i\n", ++alarmMatch_counter);
213+
rtc.setAlarmEpoch(epoc + sec, STM32RTC::MATCH_SS, epoc_ms);
214+
}
215+
#ifdef RTC_ALARM_B
216+
else {
217+
Serial.printf("\t\t\tAlarm B Match %i\n", ++alarmMatchB_counter);
218+
rtc.setAlarmEpoch(epoc + sec, STM32RTC::MATCH_SS, epoc_ms, STM32RTC::ALARM_B);
219+
}
220+
#endif
221+
}

0 commit comments

Comments
 (0)