Horloge RTC et calendrier I2C

La page est créée Antoine Dupont
 
CONTINUER À LIRE
Horloge RTC et calendrier I2C

                 Extrait du PoBot
                 http://www.pobot.org

       Horloge RTC et calendrier I2C
                                             - Robopedia - Composants - Les entrées - Autres capteurs -

                                                                                 Date de mise en ligne : samedi 2 décembre 2006

Description :
description du composant DS1307 et mise en oeuvre sur un Atmel grâce à la liaison I2C

                                                                        PoBot

Copyright © PoBot                                                                                                                 Page 1/5
Horloge RTC et calendrier I2C

Sommaire
 • Description du composant
 • Datasheet
 • Exemples de programme

Avoir un robot à l'heure n'est pas toujours une priorité, mais arriver à contrôler une puce en I2C est un exercice
intéressant.

En particulier, la puce RTC (Real Time Clock) permet d'avoir à disposition de notre programme une horloge
autonome, ce qui peut être utile pour synchroniser des étapes du programme sans reposer sur les compteurs internes
qui sont souvent surchargés.

C'est également l'occasion de décortiquer une datasheet de A à Z et enfin c'est le premier composant que j'avais à
disposition pour tester la communication I2C ;-)

        Edition 2010 : ce composant est désormais disponible pour une dizaine d'euros avec toute son électronique,
       sous forme d'une extension pour Arduino prête à l'emploi.

Description du composant
On va parler ici du Dallas DS1307, une horloge RTC archi-connue disponible pour quelques euros. C'est une puce (en
boitier DIL sur la photo) à 8 pattes.
                                     Pin Nom      Rôle

                                   1      X1          cristal

                                   2      X2          cristal

                                   3      Vbat        tension batterie

                                   4      GND         masse

Copyright © PoBot                                                                                               Page 2/5
Horloge RTC et calendrier I2C
                                  5      SDA        ligne des données (data) I²C

                                  6      SCL        ligne d'horloge (clock) I²C

                                  7      SQW/out    sortie signal carré

                                  8      Vcc        tension logique 5V

Le cristal quartz utilisé pour une horloge de ce type n'est pas comparable à ceux qu'on utilise pour les
microcontrôleurs : on utilise une valeur particulière, par exemple 32,763 kHz, qui est plus adaptée pour compter des
millisecondes. C'est un composant cylindrique très fin qu'on trouve dans les montres.

Datasheet
La datasheet nous apprend qu'il s'agit en fait d'une mémoire (d'une taille 64 octets de 8 bits) avec un programme
capable de tenir à jour un calendrier grâce à une pile de 3V et d'un oscillateur.

Datasheet DS1307

On parle avec ce composant grâce à une liaison série à deux fils (c'est de l'I2C qui ne veut pas dire son nom) et le
DS1307 est considéré comme esclave d'adresse 1101000 (0x68 pour les intimes). C'est bien sûr le microcontrôleur
qui sera le maitre et notre programme interrogera la puce qui lui répondra l'heure qu'il est.

En résumé, il faut connecter à ce composant :

   un cristal (semblable à ceux qu'on trouve dans les montres à quartz, et pour cause !)
   une batterie 3V (on utilise une pile lithium CR2032)
   une tension d'alimentation 5V (celle du µC)
   la connexion au bus I2C
   deux résistances de pull-up sur le bus I2C

Copyright © PoBot                                                                                            Page 3/5
Horloge RTC et calendrier I2C

Exemple de circuit

Exemples de programme
Comme dit plus haut, il s'agit d'une mémoire à registres. La lecture se fait donc en deux temps :
  écrire le registre auquel on souhaite accéder
  demander la lecture de ce registre

Il y a 8 registres consacrés à l'horloge temps réel (Real Time Clock) dans ce composant (dans cet ordre) :
    les secondes (de 0 à 59)
    les minutes (de 0 à 59)
    les heures (de 0 à 23)
    le jour de la semaine (de 1 à 7)
    la date du jour (dans le mois, de 1 à 31)
    le mois (de 1 à 12)
    l'année (à partir de 0, il suffit de lui ajouter 2000)
    la configuration

Certains des octets comportent des bits de configuration : par exemple pour l'heure, les bits qui ne servent pas à
coder l'heure sont utilisés pour changer le mode 12 heures ou 24 heures et le cas échéant pour stocker si c'est le
matin (AM) ou l'après-midi (PM).

Attention, les valeurs des octets que vous allez écrire ou récupérer sont codés en BCD ou binary coded decimal, il
faut donc utiliser des routines de conversion, assez simples (division ou multiplication par 10, reste de la division
entière, et des décalages de 4 bits pour charger ou récupérer la partie haute de l'octet).

 /** * Transform a binary value into BCD coded value * */ u08 transformToBcd(u08 val) { // 4 higher bits are the
integer result of division by 10 // 4 lower bits are the remaining part return ((val/10) >4) + (bcd &
0x0F); }

Les appels aux fonctions I2C dépendent des librairies que vous utilisez. Voici ce que ça donne avec AVRlib :

 #define CLOCK_ADDRESS0xD0 // useful constants for easy reminding of RTC bytes' order #define DS1307_SEC 0
#define DS1307_MIN 1 #define DS1307_HR 2 #define DS1307_DOW 3 #define DS1307_DATE 4 #define
DS1307_MTH 5 #define DS1307_YR 6 // bytes array for the sending to the I2C device u08 cmd[] = "012345678"; //
how many bytes are to be sent (max index of previous array) u08 cmdSize; // buffer to store the received bytes u08
buffer[] = "0123456789"; // specific array for the RTC values (hour, minutes, month, ..) decoded u08 rtc[7]; int
main(void) { // initialization of libraries (AVRlib) timerInit(); uartInit(); uartSetBaudRate(9600);
rprintfInit(uartSendByte); vt100Init(); vt100ClearScreen(); i2cInit(); // infinite loop that reads and display current date
& time while (1) { // First, announce that you're requestion the RTC values cmd[0] = 0x00; cmdSize = 1;
i2cMasterSend(CLOCK_ADDRESS,cmdSize,cmd); // Second, receive the 7 bcd bytes from RTC

Copyright © PoBot                                                                                                 Page 4/5
Horloge RTC et calendrier I2C
i2cMasterReceive(CLOCK_ADDRESS,7,buffer); // decode buffer into rtc array rtc[DS1307_SEC] =
transformFromBcd(buffer[DS1307_SEC]); rtc[DS1307_MIN] = transformFromBcd(buffer[DS1307_MIN]);
rtc[DS1307_HR] = transformFromBcd(buffer[DS1307_HR]); rtc[DS1307_DOW] = buffer[DS1307_DOW];
rtc[DS1307_DATE] = transformFromBcd(buffer[DS1307_DATE]); rtc[DS1307_MTH] =
transformFromBcd(buffer[DS1307_MTH]); rtc[DS1307_YR] = transformFromBcd(buffer[DS1307_YR]); // At last,
display it in the serial console rprintf("%d/%d/%d @
%d:%d:%d",rtc[DS1307_DATE],rtc[DS1307_MTH],2000+rtc[DS1307_YR],rtc[DS1307_HR],rtc[DS1307_MIN],rtc[DS13
07_SEC]); rprintfCRLF(); delay_ms(1000); } return 0; }

Il est important de noter qu'ici, l'adresse I2C (sur 7 bits) a été convertie en 8 bits (ajout d'un zéro à la fin) et devient D0.
La librairie I2C gère la différence entre une écriture et une lecture. C'est le point le plus "pénible" de la communication
I2C, car on hésite toujours sur le format de l'adresse selon le matériel ou le logiciel qu'on utilise. Pour l'instant, nous
avons sous la main un analyseur logique qui nous permet de vérifier :

Pour la première utilisation d'une horloge (ou lors du remplacement de la pile), il est nécessaire d'enregistrer l'heure
courante. Voici le code correspondant, qui utilise la fonction de codage BCD présentée ci-dessus et qui va tout
simplement écrire les 7 octets à la suite du registre 0 qui reste toujours nécessaire pour garder la logique "mémoire"
du composant DS1307.

 /* * */ void initClock(void) { // init clock ("real" values) rtc[DS1307_SEC] = 0; rtc[DS1307_MIN] = 48;
rtc[DS1307_HR] = 22; rtc[DS1307_DOW] = 5; rtc[DS1307_DATE] = 26; rtc[DS1307_MTH] = 12; rtc[DS1307_YR] =
8; // transform into BCD ready for sending (using the buffer) cmd[DS1307_SEC+1] =
transformToBcd(rtc[DS1307_SEC]); cmd[DS1307_MIN+1] = transformToBcd(rtc[DS1307_MIN]);
cmd[DS1307_HR+1] = transformToBcd(rtc[DS1307_HR]); cmd[DS1307_DOW+1] = rtc[DS1307_DOW];
cmd[DS1307_DATE+1] = transformToBcd(rtc[DS1307_DATE]); cmd[DS1307_MTH+1] =
transformToBcd(rtc[DS1307_MTH]); cmd[DS1307_YR+1] = transformToBcd(rtc[DS1307_YR]); // prepare sending
by setting register 0 in first byte + 7 other bytes cmd[0] = 0; cmdSize = 8; // send to the clock
i2cMasterSend(CLOCK_ADDRESS,cmdSize,cmd); }

On teste, ça fonctionne !

Au final, c'est un code assez simple. Nous n'avons présenté que l'utilisation de base, avec un code sans protection
(vérification des valeurs minimums et maximums lors de l'écriture, etc...) et sans gérer l'arrêt et le démarrage de
l'horloge (bit de poids le plus fort à 0 pour start ou 1 pour stop sur l'octet des secondes).

Il existe des bibliothèques de code pour différents microcontrôleurs et différents langages. Ainsi pour les cartes et
l'environnement Arduino, je vous conseille la discussion très intéressante sur leur forum (dont je me suis inspiré pour
coder mes propres fonctions) : http://www.arduino.cc/cgi-bin/yabb2...
[http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1191209057]

Copyright © PoBot                                                                                                    Page 5/5
Vous pouvez aussi lire