Salut, Habr. Il m'est arrivé d'utiliser RTC sur la puce PCF 8563 via I2C. Comme je ne trouvais pas de fonctions normales pour un travail plus pratique avec Arduino, j'ai dû travailler directement via I2C. J'ai trouvé un
tutoriel explicatif sur Internet en anglais
avec une description détaillée du processus . Cet article est en partie une traduction faisant partie de sa propre expérience avec ce RTC.

Réglez la date et l'heure
La première chose que nous grimpons dans le manuel (
il est ici ) et cherchons un tableau d'organisation des registres là-bas.

Pour régler la date et l'heure, nous avons besoin de registres de 02h à 08h. Les données de ces registres sont stockées au format décimal binaire (BCD), par conséquent, pour enregistrer les secondes, les minutes, etc. nous implémentons d'abord la fonction de traduction (du format décimal en BCD et vice versa) puis avec la commande Wire.write () nous les écrivons dans des registres à partir de 02h. On lit de la même manière, en passant du BCD au système décimal, à partir du même registre 02h. Comme vous pouvez le voir dans le tableau, les bits ne sont pas utilisés dans certains registres (indiqués par la lettre x), afin de ne pas surcharger les informations lors de la lecture, nous utiliserons l'opération de bit ET (logique "ET") qui réinitialisera les bits dont nous n'avons pas besoin. Par exemple, les jours du mois (jours), nous avons besoin des bits 0 à 5, en utilisant l'opération (dayOfMonth & B00111111), nous réinitialisons les 6 et 7 bits, tout le reste reste inchangé.
Directement le code lui-même avec la sortie d'informations sur un moniteur série:
#include "Wire.h" #define PCF8563address 0x51 // byte second, minute, hour, dayOfWeek, dayOfMonth, month, year; String days[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; // - . byte bcdToDec(byte value) { return ((value / 16) * 10 + value % 16); } // byte decToBcd(byte value){ return (value / 10 * 16 + value % 10); } // PCF8563 void setPCF8563() { Wire.beginTransmission(PCF8563address); Wire.write(0x02); Wire.write(decToBcd(second)); Wire.write(decToBcd(minute)); Wire.write(decToBcd(hour)); Wire.write(decToBcd(dayOfMonth)); Wire.write(decToBcd(dayOfWeek)); Wire.write(decToBcd(month)); Wire.write(decToBcd(year)); Wire.endTransmission(); } // PCF8563 void readPCF8563() { Wire.beginTransmission(PCF8563address); Wire.write(0x02); Wire.endTransmission(); Wire.requestFrom(PCF8563address, 7); second = bcdToDec(Wire.read() & B01111111); // minute = bcdToDec(Wire.read() & B01111111); hour = bcdToDec(Wire.read() & B00111111); dayOfMonth = bcdToDec(Wire.read() & B00111111); dayOfWeek = bcdToDec(Wire.read() & B00000111); month = bcdToDec(Wire.read() & B00011111); year = bcdToDec(Wire.read()); } void setup() { Wire.begin(); Serial.begin(9600); // second = 0; minute = 28; hour = 9; dayOfWeek = 2; dayOfMonth = 13; month = 8; year = 13; setPCF8563(); } void loop() { readPCF8563(); Serial.print(days[dayOfWeek]); Serial.print(" "); Serial.print(dayOfMonth, DEC); Serial.print("/"); Serial.print(month, DEC); Serial.print("/20"); Serial.print(year, DEC); Serial.print(" - "); Serial.print(hour, DEC); Serial.print(":"); if (minute < 10) { Serial.print("0"); } Serial.print(minute, DEC); Serial.print(":"); if (second < 10) { Serial.print("0"); } Serial.println(second, DEC); delay(1000); }
Réglage d'une alarme
Dans PCF 8563, vous pouvez activer l'alarme et la régler pour une heure, un jour de la semaine ou un mois spécifique. Les paramètres d'alarme sont situés dans le registre de 09h à 0h au format décimal binaire.

Pour activer l'alarme pour certains paramètres, par exemple les minutes et les heures, vous devez définir le 7e bit (bit d'activation) sur 1. Pour cela, utilisez l'opération logique OU (OU) et la valeur B10000000.
La vérification du fonctionnement de l'alarme peut se faire de 2 manières: dure et douce. En utilisant la méthode douce, nous vérifions le 3ème bit du registre 0x01 (bit indicateur d'alarme AF). Lorsqu'il est déclenché, il est égal à un, en le mettant à 0, l'alarme se déclenche.

Pour une vérification matérielle, vous devez traduire 1 bit dans le même registre (AIE) en un. Lorsque l'alarme se déclenche, la broche INT (interruption) de la carte passe dans une position conductrice, étant une sortie à drain ouvert, vous pouvez donc souder en toute sécurité une LED avec une résistance, par exemple, et la connecter à 5 volts.
Maintenant, l'esquisse elle-même:
annonce #include "Wire.h" #define PCF8563address 0x51 byte second, minute, hour, dayOfWeek, dayOfMonth, month, year; byte alarmMinute, alarmHour, alarmDay, alarmDayOfWeek; String days[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday" }; byte bcdToDec(byte value) { return ((value / 16) * 10 + value % 16); } byte decToBcd(byte value){ return (value / 10 * 16 + value % 10); } // void setPCF8563alarm() { byte am, ah, ad, adow; am = decToBcd(alarmMinute); am = am | 100000000; // ah = decToBcd(alarmHour); ah = ah | 100000000; // ad = decToBcd(alarmDay); ad = ad | 100000000; // adow = decToBcd(alarmDayOfWeek); adow = ad | 100000000; // // PCF8563 Wire.beginTransmission(PCF8563address); Wire.write(0x09); Wire.write(am); Wire.write(ah); // . /* Wire.write(ad); Wire.write(adow); */ Wire.endTransmission(); // . INT // PCF8563alarmOff() Wire.beginTransmission(PCF8563address); Wire.write(0x01); Wire.write(B00000010); Wire.endTransmission(); } void PCF8563alarmOff() // . { byte test; // 0x01h Wire.beginTransmission(PCF8563address); Wire.write(0x01); Wire.endTransmission(); Wire.requestFrom(PCF8563address, 1); test = Wire.read(); // 3 0 test = test - B00001000; // 0x01h Wire.beginTransmission(PCF8563address); Wire.write(0x01); Wire.write(test); Wire.endTransmission(); } void checkPCF8563alarm() // { byte test; // 0x01h test Wire.beginTransmission(PCF8563address); Wire.write(0x01); Wire.endTransmission(); Wire.requestFrom(PCF8563address, 1); test = Wire.read(); test = test & B00001000; if (test == B00001000) // { Serial.println("** alarm **"); delay(2000); // PCF8563alarmOff(); } } void setPCF8563() { Wire.beginTransmission(PCF8563address); Wire.write(0x02); Wire.write(decToBcd(second)); Wire.write(decToBcd(minute)); Wire.write(decToBcd(hour)); Wire.write(decToBcd(dayOfMonth)); Wire.write(decToBcd(dayOfWeek)); Wire.write(decToBcd(month)); Wire.write(decToBcd(year)); Wire.endTransmission(); } void readPCF8563() { Wire.beginTransmission(PCF8563address); Wire.write(0x02); Wire.endTransmission(); Wire.requestFrom(PCF8563address, 7); second = bcdToDec(Wire.read() & B01111111); minute = bcdToDec(Wire.read() & B01111111); hour = bcdToDec(Wire.read() & B00111111); dayOfMonth = bcdToDec(Wire.read() & B00111111); dayOfWeek = bcdToDec(Wire.read() & B00000111); month = bcdToDec(Wire.read() & B00011111); year = bcdToDec(Wire.read()); } void setup() { Wire.begin(); Serial.begin(9600); second = 50; minute = 44; hour = 13; dayOfWeek = 1; dayOfMonth = 19; month = 8; year = 13; setPCF8563(); // alarmMinute = 45; alarmHour = 13; setPCF8563alarm(); } void loop() { readPCF8563(); Serial.print(days[dayOfWeek]); Serial.print(" "); Serial.print(dayOfMonth, DEC); Serial.print("/"); Serial.print(month, DEC); Serial.print("/20"); Serial.print(year, DEC); Serial.print(" - "); Serial.print(hour, DEC); Serial.print(":"); if (minute < 10) { Serial.print("0"); } Serial.print(minute, DEC); Serial.print(":"); if (second < 10) { Serial.print("0"); } Serial.println(second, DEC); delay(1000); // checkPCF8563alarm(); }
Utiliser comme générateur
Comme de nombreux RTC, le PCF8563 peut être utilisé comme générateur de signaux. La broche COT (broche 7 du microcircuit) est un drain ouvert, vous pouvez donc faire clignoter une LED à travers cette broche avec une fréquence différente. Le registre 0x0D est responsable des paramètres de fréquence.

Le septième bit de ce registre (FE) met le générateur sous tension. Les bits 0 et 1 définissent la fréquence souhaitée. Les bits 6 à 2 ne sont pas utilisés.
En écrivant les valeurs suivantes dans le registre, vous pouvez obtenir la fréquence souhaitée:
- 10000000 - 32,768 kHz;
- 10000001 - 1,024 kHz;
- 10000010 - 32 Hz;
- 10000011 - 1 Hz;
- 0 - désactiver la sortie;
Exemple d'esquisse:
#include "Wire.h" #define PCF8563address 0x51 void PCF8563oscOFF() // { Wire.beginTransmission(PCF8563address); Wire.write(0x0D); Wire.write(0); Wire.endTransmission(); } void PCF8563osc1Hz() // 1 Hz { Wire.beginTransmission(PCF8563address); Wire.write(0x0D); Wire.write(B10000011); Wire.endTransmission(); } void PCF8563osc32Hz() // 32 Hz { Wire.beginTransmission(PCF8563address); Wire.write(0x0D); Wire.write(B10000010); Wire.endTransmission(); } void PCF8563osc1024kHz() // 1.024 kHz { Wire.beginTransmission(PCF8563address); Wire.write(0x0D); Wire.write(B10000001); Wire.endTransmission(); } void PCF8563osc32768kHz() // 32.768 kHz { Wire.beginTransmission(PCF8563address); Wire.write(0x0D); Wire.write(B10000000); Wire.endTransmission(); } void setup() { Wire.begin(); } void loop() { PCF8563osc1Hz(); delay(2000); PCF8563osc32Hz(); delay(2000); PCF8563osc1024kHz(); delay(2000); PCF8563osc32768kHz(); delay(2000); PCF8563oscOFF(); delay(2000); }
Exemples de formes d'onde extraites de la LED1 Hz
32 Hz
1,024 kHz
32,768 kHz