DIY Logging Volt/Ampmeter
rtc.c File Reference

RTC functionality for high-precision logging voltage/current meter. More...

#include "rtc.h"
#include <stdint.h>
#include "stm32f1xx_ll_bus.h"
#include "stm32f1xx_ll_rcc.h"
#include "stm32f1xx_ll_pwr.h"
#include "stm32f1xx_ll_rtc.h"
#include "stm32f1xx_ll_exti.h"
#include "stm32f1xx_ll_cortex.h"
#include "util.h"

Go to the source code of this file.

Macros

#define RTC_TIMEOUT_MS   ((uint32_t)1000)
 
#define RTC_ASYNCH_PREDIV   ((uint32_t)0x7FFF)
 

Functions

static void RTCcounter_to_dateTime (uint32_t counter)
 Function to convert the RTC counter value to date-time values in the struct. More...
 
static uint32_t dateTime_to_RTCcounter (void)
 Function to convert the date-time values in the struct to a corresponding RTC counter value. More...
 
void RTC_Init (void)
 Function to initialize the Real Time Clock. More...
 
void readFromRTC (void)
 Function to update the RTC data in the struct. More...
 
void writeToRTC (void)
 Function to update the RTC values according to the data in the struct. More...
 

Variables

static uint32_t Timeout = 0
 

Detailed Description

RTC functionality for high-precision logging voltage/current meter.

Version
1.0
Author
Brecht Van Eeckhoudt

Versions

  • v1.0: Initial version.

Todo:
Future improvements:

License

Copyright (C) 2021 - Brecht Van Eeckhoudt

This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.

This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details.

A copy of the GNU General Public License can be found in the LICENSE file along with this source code.


Some methods also use code obtained from examples from STMicroelectronics.

Copyright (c) 2020 STMicroelectronics. All rights reserved.

These sections are licensed by ST under BSD 3-Clause license, the "License"; One may not use these example files except in compliance with the License. One may obtain a copy of the License at: opensource.org/licenses/BSD-3-Clause


Some methods also use code obtained from https://github.com/mkdxdx/stm32f103_logger


These seem to be heavily based on https://github.com/LonelyWolf/stm32/blob/master/stm32l-dosfs/RTC.c

Definition in file rtc.c.

Macro Definition Documentation

◆ RTC_ASYNCH_PREDIV

#define RTC_ASYNCH_PREDIV   ((uint32_t)0x7FFF)

ck_apre = LSEFreq / (ASYNC prediv + 1) = 1Hz with LSEFreq = 32768Hz

Definition at line 80 of file rtc.c.

◆ RTC_TIMEOUT_MS

#define RTC_TIMEOUT_MS   ((uint32_t)1000)

Oscillator time-out values

Definition at line 77 of file rtc.c.

Function Documentation

◆ dateTime_to_RTCcounter()

static uint32_t dateTime_to_RTCcounter ( void  )
static

Function to convert the date-time values in the struct to a corresponding RTC counter value.

Note
This is a static method because it's only internally used in this file and called by other methods if necessary.
Returns
The corresponding RTC counter value (uint32_t)

Definition at line 255 of file rtc.c.

256 {
257  uint8_t a;
258  uint16_t y;
259  uint8_t m;
260  uint32_t JDN;
261 
262  if (rtc.latest == 0)
263  {
264  a=(14-rtc.month0)/12;
265  y=rtc.year0+4800-a;
266  m=rtc.month0+(12*a)-3;
267 
268  JDN=rtc.day0;
269  JDN+=(153*m+2)/5;
270  JDN+=365*y;
271  JDN+=y/4;
272  JDN+=-y/100;
273  JDN+=y/400;
274  JDN = JDN -32045;
275  JDN = JDN - JULIAN_DATE_BASE;
276  JDN*=86400;
277  JDN+=(rtc.hour0*3600);
278  JDN+=(rtc.min0*60);
279  JDN+=(rtc.sec0);
280  }
281  else if (rtc.latest == 1)
282  {
283  a=(14-rtc.month1)/12;
284  y=rtc.year1+4800-a;
285  m=rtc.month1+(12*a)-3;
286 
287  JDN=rtc.day1;
288  JDN+=(153*m+2)/5;
289  JDN+=365*y;
290  JDN+=y/4;
291  JDN+=-y/100;
292  JDN+=y/400;
293  JDN = JDN -32045;
294  JDN = JDN - JULIAN_DATE_BASE;
295  JDN*=86400;
296  JDN+=(rtc.hour1*3600);
297  JDN+=(rtc.min1*60);
298  JDN+=(rtc.sec1);
299  }
300 
301  return (JDN);
302 }

◆ readFromRTC()

void readFromRTC ( void  )

Function to update the RTC data in the struct.

Definition at line 309 of file rtc.c.

310 {
311  RTCcounter_to_dateTime(LL_RTC_TIME_Get(RTC));
312 }

◆ RTC_Init()

void RTC_Init ( void  )

Function to initialize the Real Time Clock.

Definition at line 97 of file rtc.c.

98 {
99  /* Enable the PWR Clock and access to the backup domain */
100  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_PWR);
101  LL_APB1_GRP1_EnableClock(LL_APB1_GRP1_PERIPH_BKP);
102  LL_PWR_EnableBkUpAccess();
103 
104  /* Enable LSE only if disabled.*/
105  if (LL_RCC_LSE_IsReady() != 1)
106  {
107  LL_RCC_ForceBackupDomainReset();
108  LL_RCC_ReleaseBackupDomainReset();
109  LL_RCC_LSE_Enable();
110 
112 
113  while (LL_RCC_LSE_IsReady() != 1)
114  {
116 
117  if (Timeout == 0) while(1); /* LSE activation error */
118  }
119  }
120 
121  /* Set LSE as the clock source for the RTC if not already the case */
122  if (LL_RCC_GetRTCClockSource() != LL_RCC_RTC_CLKSOURCE_LSE)
123  {
124  LL_RCC_SetRTCClockSource(LL_RCC_RTC_CLKSOURCE_LSE);
125  }
126 
127  /* Enable RTC peripheral Clock */
128  LL_RCC_EnableRTC();
129 
130 
131  /* Disable RTC registers write protection */
132  LL_RTC_DisableWriteProtection(RTC);
133 
134  /* Enter in initialization mode */
135  if (LL_RTC_EnterInitMode(RTC) != 0)
136  {
137  while(1); /* Initialization Error */
138  }
139 
140  /* Configure RTC prescaler, set Asynch Prediv value according to source clock */
141  LL_RTC_SetAsynchPrescaler(RTC, RTC_ASYNCH_PREDIV);
142 
143  /* RTC_Alarm Interrupt Configuration: EXTI configuration */
144  LL_EXTI_EnableIT_0_31(LL_EXTI_LINE_17);
145  LL_EXTI_EnableRisingTrig_0_31(LL_EXTI_LINE_17);
146 
147  /* Configure the NVIC for RTC Alarm */
150 
151  /* Enable Second Interrupt */
152  LL_RTC_EnableIT_SEC(RTC);
153 
154  /* Exit of initialization mode */
155  LL_RTC_ExitInitMode(RTC);
156 
157  /* Enable RTC registers write protection */
158  LL_RTC_EnableWriteProtection(RTC);
159 
160 
161  /* Signal logic so the hour/min/second fields have to be converted to chars after RTC initialization (~boot) */
162  rtc.firstUpdate = 1;
163 }

◆ RTCcounter_to_dateTime()

static void RTCcounter_to_dateTime ( uint32_t  counter)
static

Function to convert the RTC counter value to date-time values in the struct.

Note
This is a static method because it's only internally used in this file and called by other methods if necessary.
Parameters
[in]counterRTC counter-value (uint32_t).

Definition at line 177 of file rtc.c.

178 {
179  unsigned long time;
180  unsigned long t1, a, b, c, d, e, m;
181  int year = 0;
182  int mon = 0;
183  int wday = 0;
184  int mday = 0;
185  int hour = 0;
186  int min = 0;
187  int sec = 0;
188  uint64_t jd = 0;;
189  uint64_t jdn = 0;
190 
191  jd = ((counter+43200)/(86400>>1)) + (2440587<<1) + 1;
192  jdn = jd>>1;
193 
194  time = counter;
195  t1 = time/60;
196  sec = time - t1*60;
197 
198  time = t1;
199  t1 = time/60;
200  min = time - t1*60;
201 
202  time = t1;
203  t1 = time/24;
204  hour = time - t1*24;
205 
206  wday = jdn%7;
207 
208  a = jdn + 32044;
209  b = (4*a+3)/146097;
210  c = a - (146097*b)/4;
211  d = (4*c+3)/1461;
212  e = c - (1461*d)/4;
213  m = (5*e+2)/153;
214  mday = e - (153*m+2)/5 + 1;
215  mon = m + 3 - 12*(m/10);
216  year = 100*b + d - 4800 + (m/10);
217 
218  if (rtc.latest == 0)
219  {
220  rtc.year1 = year;
221  rtc.month1 = mon;
222  rtc.day1 = mday;
223  rtc.hour1 = hour;
224  rtc.min1 = min;
225  rtc.sec1 = sec;
226  rtc.latest = 1;
227  }
228  else if (rtc.latest == 1)
229  {
230  rtc.year0 = year;
231  rtc.month0 = mon;
232  rtc.day0 = mday;
233  rtc.hour0 = hour;
234  rtc.min0 = min;
235  rtc.sec0 = sec;
236  rtc.latest = 0;
237  }
238 
239  rtc.wday = wday;
240 }

◆ writeToRTC()

void writeToRTC ( void  )

Function to update the RTC values according to the data in the struct.

Definition at line 319 of file rtc.c.

320 {
321  /* Disable RTC registers write protection */
322  LL_RTC_DisableWriteProtection(RTC);
323 
324  /* Enter in initialization mode */
325  if (LL_RTC_EnterInitMode(RTC) != 0)
326  {
327  while(1); /* Initialization Error */
328  }
329 
330  /* Set time and date according to struct values, which have been converted to onee uint32_t value */
331  LL_RTC_TIME_SetCounter(RTC, dateTime_to_RTCcounter());
332 
333  /* Clear RSF flag */
334  LL_RTC_ClearFlag_RS(RTC);
335 
337 
338  /* Wait until the RTC Time and Date registers (RTC_TR and RTC_DR) are synchronized with RTC APB clock */
339  while(LL_RTC_IsActiveFlag_RS(RTC) != 1)
340  {
342 
343  if (Timeout == 0) while(1); /* Initialization Error */
344  }
345 
346  /* Exit of initialization mode */
347  if (LL_RTC_ExitInitMode(RTC) != 0)
348  {
349  while(1); /* Initialization Error */
350  }
351 
352  /* Enable RTC registers write protection */
353  LL_RTC_EnableWriteProtection(RTC);
354 }

Variable Documentation

◆ Timeout

uint32_t Timeout = 0
static

Variable used for Timeout management

Definition at line 85 of file rtc.c.

RTC_dateTime_t::hour0
uint8_t hour0
Definition: rtc.h:55
Timeout
static uint32_t Timeout
Definition: rtc.c:85
RTC
#define RTC
Definition: stm32f103xb.h:651
RTC_dateTime_t::min1
uint8_t min1
Definition: rtc.h:61
LL_SYSTICK_IsActiveCounterFlag
__STATIC_INLINE uint32_t LL_SYSTICK_IsActiveCounterFlag(void)
This function checks if the Systick counter flag is active or not.
Definition: stm32f1xx_ll_cortex.h:231
RTC_IRQn
@ RTC_IRQn
Definition: stm32f103xb.h:86
RTC_TIMEOUT_MS
#define RTC_TIMEOUT_MS
Definition: rtc.c:77
rtc
struct RTC_dateTime_t rtc
dateTime_to_RTCcounter
static uint32_t dateTime_to_RTCcounter(void)
Function to convert the date-time values in the struct to a corresponding RTC counter value.
Definition: rtc.c:255
RTCcounter_to_dateTime
static void RTCcounter_to_dateTime(uint32_t counter)
Function to convert the RTC counter value to date-time values in the struct.
Definition: rtc.c:177
RTC_dateTime_t::year0
uint16_t year0
Definition: rtc.h:82
JULIAN_DATE_BASE
#define JULIAN_DATE_BASE
Definition: rtc.h:47
RTC_dateTime_t::min0
uint8_t min0
Definition: rtc.h:60
LSE_TIMEOUT_VALUE
#define LSE_TIMEOUT_VALUE
Definition: stm32_hal_legacy.h:3300
RTC_dateTime_t::month0
uint8_t month0
Definition: rtc.h:77
RTC_dateTime_t::year1
uint16_t year1
Definition: rtc.h:83
RTC_dateTime_t::sec1
uint8_t sec1
Definition: rtc.h:66
RTC_dateTime_t::day0
uint8_t day0
Definition: rtc.h:70
RTC_dateTime_t::sec0
uint8_t sec0
Definition: rtc.h:65
RTC_dateTime_t::latest
uint8_t latest
Definition: rtc.h:53
NVIC_SetPriority
#define NVIC_SetPriority
Definition: core_armv8mbl.h:1197
RTC_dateTime_t::day1
uint8_t day1
Definition: rtc.h:71
RTC_dateTime_t::wday
uint8_t wday
Definition: rtc.h:75
NVIC_EnableIRQ
#define NVIC_EnableIRQ
Definition: core_armv8mbl.h:1190
RTC_ASYNCH_PREDIV
#define RTC_ASYNCH_PREDIV
Definition: rtc.c:80
RTC_dateTime_t::hour1
uint8_t hour1
Definition: rtc.h:56
RTC_dateTime_t::month1
uint8_t month1
Definition: rtc.h:78
RTC_dateTime_t::firstUpdate
uint8_t firstUpdate
Definition: rtc.h:52