La Real Time Clock

Ce tutoriel explique comment mettre en oeuvre l’horloge temps réel du STM32WB55 en C.

L’horloge temps réel (Real-Time Clock en anglais, abrégée RTC) est un circuit électronique intégré dans le microcontrôleur STM32WB55 remplissant les fonctions d’une horloge très précise pour des problématiques d’horodatage, de gestions d’alarmes déclenchées suivant un calendrier et capable de mettre le microcontrôleur en sommeil ou de le réveiller, etc. Afin qu’elle soit aussi précise et stable que possible, la RTC peut utiliser comme source de fréquence un quartz vibrant à 32kHz.

Utilisation

En premier, il est nécessaire d’importer les bibliothèques :
Elle se télécharge depuis le gestionnaire arduino sous Croquis > Inclure une bibliothèque > Gérer les bibliothèques et en cherchant STM32duino RTC.

// Importation des bibliothèques
#include <STM32RTC.h>

Ensuite nous déclarons la RTC

STM32RTC& rtc = STM32RTC::getInstance();

Puis nous la démarront

rtc.begin();

Nous pouvons maintenant nous servir de la RTC.
Les profils des fonctions principales sont les suivants :

void setHours(uint8_t hours);
void setMinutes(uint8_t minutes);
void setSeconds(uint8_t seconds);
void setTime(uint8_t hours, uint8_t minutes, uint8_t seconds, uint32_t subSeconds = 1000, AM_PM period = AM);

void setWeekDay(uint8_t weekDay);	// 1 pour lundi et 7 pour dimanche
void setDay(uint8_t day);
void setMonth(uint8_t month);
void setYear(uint8_t year);
void setDate(uint8_t weekDay, uint8_t day, uint8_t month, uint8_t year);

uint8_t getHours();
uint8_t getMinutes();
uint8_t getSeconds();
void getTime(uint8_t *hours, uint8_t *minutes, uint8_t *seconds, uint32_t *subSeconds, AM_PM *period = nullptr);

uint8_t getWeekDay();	// 1 pour lundi et 7 pour dimanche
uint8_t getDay();
uint8_t getMonth();
uint8_t getYear();
void getDate(uint8_t *weekDay, uint8_t *day, uint8_t *month, uint8_t *year);

Pour les valeurs non-souhaitées de getTime et getDate il suffit de mettre NULL lors de l’appel. Par exemple getTime(&hours, &minutes, &seconds, NULL); permet de récupérer les heures, minutes et secondes sans les sous-secondes.

La date du samedi 2 janvier 2021 à 12h21 51s peut alors être définie comme ceci :

rtc.setTime(12, 21, 51);
rtc.setDate(6, 2, 1, 21);

et elle peut être récupérée comme cela :

uint8_t hours, minutes, seconds, weekDay, day, month, year;
rtc.getTime(&hours, &minutes, &seconds, NULL);
rtc.getDate(&weekDay, &day, &month, &year);

Exemples

Ainsi un premier code pour afficher sur le terminal serait :

// Importation des bibliothèques
#include <STM32RTC.h>

// on declare la RTC
STM32RTC& rtc = STM32RTC::getInstance();

void setup(){
	// on démarre la rtc
	rtc.begin();

	// on initialise l'heure et la date
	rtc.setTime(12, 21, 51);
	rtc.setDate(6, 2, 1, 21);
}

void loop() {
  uint8_t hours, minutes, seconds, weekDay, day, month, year;
  // on récupère la date et l'heure
  rtc.getTime(&hours, &minutes, &seconds, NULL);
  rtc.getDate(&weekDay, &day, &month, &year);

  // on affiche
  printf("%d -- %d/%d/%d -- %02d:%02d:%02d\n", weekDay, day, month, year, hours, month, seconds);

  // toutes les secondes
  delay(1000);
}

En se servant du tutoriel de l’afficheur 8x7-segments TM1638 on peut réaliser une horloge avec affichage LED avec le code d’exemple suivant :

// Importation des bibliothèques
#include <STM32RTC.h>
#include <TM1638plus.h>

// Déclaration de la RTC
STM32RTC& rtc = STM32RTC::getInstance();

// Déclaration de la carte
//           STB  CLK  DIO
TM1638plus tm(D2, D3 , D4);

void setup() {
  // on démarre la rtc
  rtc.begin();

  // on initialise l'heure et la date
  rtc.setTime(0, 0, 0);
  rtc.setDate(5, 1, 1, 21);

  // début de l'affichage
  tm.displayBegin();
  
  // on réduit la luminosité
  tm.brightness(0);
}

void loop() {
  uint8_t hours, minutes, seconds, weekDay, day, month, year, boutons;
  char str[9];
  // on récupère la date et l'heure
  rtc.getTime(&hours, &minutes, &seconds, NULL);

  if (seconds % 2){
    sprintf(str, "%02dh%02d .%02d", hours, minutes, seconds);
    tm.displayText(str);
  }
  else{
    sprintf(str, "%02dh%02d %02d", hours, minutes, seconds);
    tm.displayText(str);
  }
  // on récupère l'information sur les boutons
  boutons = tm.readButtons();
    
  // on compare bit à bit pour identifier le bouton
  if (boutons & 1) { 
    hours++;
    if (hours > 23) {
      hours = 0;
    }
    rtc.setHours(hours);
  }
  if (boutons & 1<<1) {
    minutes++;
    if (minutes > 59) {
      minutes = 0;
    }
    rtc.setMinutes(minutes);
  }
  if (boutons & 1<<2) {
    seconds++;
    if (seconds > 59) {
      seconds = 0;
    }
    rtc.setSeconds(seconds);
  }
    
  // on actualise toute les 100 milisecondes (pour un lecture des boutons plus sensible, peut être modifié)
  delay(100);
}