Horloge RTC et calendrier I2C
←
→
Transcription du contenu de la page
Si votre navigateur ne rend pas la page correctement, lisez s'il vous plaît le contenu de la page ci-dessous
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