La RAM du DS1307

Le DS1307 dispose de 56 octets de RAM. Comme toute mémoire vive, celle du DS1307 est accessible en lecture et en écriture.

DS1307_-_RAM_registers.png

Les registres de RAM sont localisés de l'adresse 0x08 à l'adresse 0x3F.

DS1307_-_Timekeeper_Registers_color.png

Bibliothèque RTClib

La bibliothèque RTClib de JeeLabs - ou ses différents forks tel que celui d'Adafruit - est probablement la bibliothèque Arduino la plus utilisée pour piloter l'horloge temps réel DS1307.

Toutefois cette bibliothèque se concentre sur la gestion du temps de l'horloge. On ajoutera des méthodes pour accomplir les tâches suivantes :

  • lecture d'un octet ;
  • lecture de plusieurs octets ;
  • écriture d'un octet ;
  • écriture de plusieurs octets.

API

Les prototypes de quatre nouvelles méthodes font leur apparition dans l'API de la bibliothèque :

  • readByteInRam (ligne 36) ;
  • readBytesInRam (ligne 37) ;
  • writeByteInRam (ligne 38) ;
  • writeBytesInRam (ligne 39).
// RTC based on the DS1307 chip connected via I2C and the Wire library
class RTC_DS1307 {
public:
    static void begin() {}
    static void adjust(const DateTime& dt);
    static DateTime now();
    
    // RAM registers read/write functions. Address locations 08h to 3Fh.
    // Max length = 56 bytes.
    static uint8_t readByteInRam(uint8_t address);
    static void readBytesInRam(uint8_t address, uint8_t length, uint8_t* p_data);
    static void writeByteInRam(uint8_t address, uint8_t data);
    static void writeBytesInRam(uint8_t address, uint8_t length, uint8_t* p_data);

    // utility functions
    static uint8_t bcd2bin (uint8_t val) { return val - 6 * (val >> 4); }
    static uint8_t bin2bcd (uint8_t val) { return val + 6 * (val / 10); }
};

Contraintes des arguments :

  • L'adresse (address) doit être comprise entre 0x08 et 0x3F.
  • Le nombre d'octets (length) ne doit pas excéder 56.
  • Pour les méthodes readBytesinRam et writeBytesInRam, le pointeur p_data pointant sur un tableau d'octets doit être non nul, alloué et libéré par la méthode appelante.

Implémentation

L'implémentation des méthodes de lecture et d'écriture des registres de RAM du DS1307 ne présente pas de particularité. Il serait judicieux de vérifier les arguments passés aux méthodes à l'aide d'assertions. Cependant leur gestion dépend très fortement du projet dans sa globalité. Par conséquent le soin est laissé au développeur d'implémenter ces vérifications.

uint8_t RTC_DS1307::readByteInRam(uint8_t address) {
    Wire.beginTransmission(DS1307_ADDRESS);
  	Wire.write(address);	
    Wire.endTransmission();

    Wire.requestFrom(DS1307_ADDRESS, 1);
    uint8_t data = Wire.read();
    Wire.endTransmission();
    
    return data;
}

void RTC_DS1307::readBytesInRam(uint8_t address, uint8_t length, uint8_t* p_data) {
    Wire.beginTransmission(DS1307_ADDRESS);
  	Wire.write(address);	
    Wire.endTransmission();

    Wire.requestFrom(DS1307_ADDRESS, (int)length);
    for (uint8_t i = 0; i < length; i++) {
        p_data[i] = Wire.read();
    }
    Wire.endTransmission();
}

void RTC_DS1307::writeByteInRam(uint8_t address, uint8_t data) {
    Wire.beginTransmission(DS1307_ADDRESS);
  	Wire.write(address);	
  	Wire.write(data);
    Wire.endTransmission();
}

void RTC_DS1307::writeBytesInRam(uint8_t address, uint8_t length, uint8_t* p_data) {
    Wire.beginTransmission(DS1307_ADDRESS);
  	Wire.write(address);	
  	for (uint8_t i = 0; i < length; i++) {
  	  	Wire.write(p_data[i]);
  	}
    Wire.endTransmission();
}

Mise en œuvre

Le sketch d'exemple ds1307_ram.ino écrit quelques octets dans la RAM du DS1307 lors de l'initialisation (fonction setup, ligne 18). Ces octets sont lus périodiquement dans la fonction loop (ligne 24) puis sont transmis via la liaison série (ligne 27).

// RAM read and write functions using a DS1307 RTC connected via I2C and Wire lib.
// 2012-11-06 www.idreammicro.com http://opensource.org/licenses/mit-license.php

#include <Wire.h>
#include <RTClib.h>

RTC_DS1307 RTC;

void setup () {
    Serial.begin(57600);
    Wire.begin();
    RTC.begin();
    
    // Write bytes in RAM.
    uint8_t data[13] = {
        'H', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd', '!', '\n', 
    };
    RTC.writeBytesInRam(0x08, 13, data);
}

void loop () {
    // Read bytes in RAM.
    uint8_t data[13] = { 0 };
    RTC.readBytesInRam(0x08, 13, data);
    
    // Print bytes on Serial.
    Serial.write(data, 13);
    delay(5000);
}

À l'aide de l'environnement de développement Arduino, on télécharge le programme dans la carte de développement. Puis on ouvre le moniteur série. Si tout se passe bien, on doit voir le message "Hello world!" s'afficher toutes les 5 secondes.

DS1307_RAM_SerialMonitor.png

Conclusion

Bien que restreinte, la RAM du DS1307 peut s'avérer très utile pour sauvegarder quelques données à l'abri d'une coupure d'alimentation. Ces données peuvent par exemple être l'état d'un système à un instant donné, la dernière clé d'un système de verrouillage à code tournant, etc...

Comme de coutume lorsqu'iDreamMicro utilise un logiciel libre comme base de travail, une pull request a été soumise à JeeLabs pour réintégrer les nouvelles méthodes de lecture et d'écriture de la RAM du DS1307 dans le projet original.

[Télécharger la bibliothèque]

Articles relatifs