vendredi 11 janvier 2019

Utiliser l'horloge temps réel du STM32

Cet article a été mis à jour le 6 janvier 2021, de façon à être compatible avec le core officiel STM32 (l'ancienne version de l'article utilisait le core STM32Duino de Roger Clarke).

Un avantage intéressant des microcontrôleurs STM32, c'est qu'ils comportent une horloge temps réel (RTC ou Real time clock) intégrée qui vous permet de connaître la date et l'heure sans qu'il soit nécessaire de la relier à un module RTC externe.

Installation de la bibliothèque STM32RTC

En supposant que votre IDE Arduino est déjà équipé des fichiers nécessaires à la programmation des microcontrôleurs STM32, il vous reste à procéder à l'installation de la bibliothèque STM32RTC.

Exemple de sketch

Le sketch fourni à la fin de ce billet utilise l'horloge temps réel du STM32 pour afficher la date et l'heure dans le moniteur série (réglé à 9600 bauds). Je l'ai testé avec une carte STM32 Nucleo et avec une Blue Pill.

Lorsque vous démarrez le programme, votre STM32 prétendra probablement que vous êtes en pleine célébration du jour de l'an 2000, puisque l'heure de l'horloge temps réel n'a pas encore été réglée.



Pour remédier à la situation, le sketch contient une routine (receptionMessage()) qui permet à l'utilisateur de régler l'heure au moyen du moniteur série: il s'agit d'y entrer "l'heure Unix" et de cliquer sur le bouton "Envoyer".



Pour connaître l'heure Unix actuelle (qui est le nombre de secondes écoulées depuis le 1er janvier 1970), vous pouvez utiliser un outil en ligne comme par exemple le site Epoch Converter.


L'horloge indique maintenant l'heure actuelle.



Si l'heure affichée dans le moniteur série ne correspond toujours pas à votre heure locale, vérifiez si la variable fuseauHoraire, déclarée au début du sketch correspond bien au fuseau horaire dans lequel vous vous trouvez­. Il s'agit du nombre d'heures de décalage par rapport à l'heure GMT.

La routine afficheHeure() affiche la date et l'heure dans le moniteur série. Elle peut sembler un peu longue à première vue, mais une grande partie du code concerne des détails d'ajustement d'affichage (comme, par exemple, ajouter un zéro devant le nombre de secondes si la valeur est plus petite que 10).  Ce qu'il est important de savoir, c'est que:
  • day() retourne le jour (si nous sommes le 17 mars, day() vaut 17).
  • month() retourne le mois (1 pour janvier, 2 pour février, etc.)
  • year() retourne le nombre d'années écoulées depuis 1970.
  • hour() retourne l'heure
  • minute() contient le nombre de minutes
  • second() contient le nombre de secondes



Bien entendu, vous pouvez modifier le sketch pour rendre l'horloge complètement indépendante de l'ordinateur, en affichant l'heure sur un écran LCD, et en réglant l'heure au moyen de boutons poussoirs, par exemple.

Yves Pelletier   (TwitterFacebook)

4 commentaires:

  1. Bonjour,
    Horloge temps réel, moi je veux bien mais elle renvoie des secondes particulièrement fausses qui changent toutes les 2/3 secondes, une idée ?

    RépondreSupprimer
    Réponses
    1. Bonjour,
      Il faut utiliser : RTClock horloge (RTCSEL_LSI); et non -> RTClock horloge (RTCSEL_LSE);

      Puis ajouter dans le setup un prescaler, et l'initialiser :
      rtc_set_prescaler_load(0x6fff);
      rtc_set_count(0);

      Avec cela ça devrait être ajusté.
      Si vous modifiez la valeur, ie: 0x3fff, vous verrez que l'horloge interne est plus lente, ou plus rapide si vous ajustez le prescaler à une valeur plus grande.

      Supprimer
    2. Ok, merci.
      Cela semble logique si LSI sous-entend Interne alors que LSE se base sur l'horloge externe. Laquelle n'est pas configurée dans mon cas.

      Supprimer
    3. @Anonyme:

      Bonsoir,
      Toujours pas convaincu par cette horloge interne.
      J'ai appliqué ce que vous proposiez,
      RTClock horloge (RTCSEL_LSI), j'étais bien en RTCSEL_LSE
      et dans le setup,
      rtc_set_prescaler_load(0x95ff);
      rtc_set_count(0);
      J'ai bien sûr essayé diverses valeurs pour le prescaler.
      Avec la valeur donnée dans beaucoup d'exemple, 0x7fff, l'horloge a toujours le feu au fesses, pas mieux avec celle que vous proposez :(
      Cette dernière valeur semble donner pour moi des valeurs un peu plus proche de la réalité.
      Mais je reste surpris qu'une horloge interne pilotée soit si délicate à paramétrer.
      J'utilise régulièrement des DS3231 et il y a moins de soucis. Si ce n'est un décalage à la longue.
      Précision, mon code n'utilise pas d'interruption, comme le propose la plupart des exemples. Je fais cela volontairement pour tester la fiabilité sur le moniteur série.
      Il est dommage que ces valeurs de "precaler" ne soient commentées nul part.
      Je vais chercher, l'idée est quand même de se passer de DS3231.
      Merci quand même pour vos précisions, cela reste une piste intéressante.
      Bonne continuation.

      Supprimer