Produktbilder dienen ausschließlich zu Informationszwecken und können je nach Charge und Lieferant geringfügige Unterschiede aufweisen. Produktspezifikationen und Preise können ohne vorherige Ankündigung geändert werden. Wir tun unser Bestes, um der Produktseite möglichst genaue und richtige Spezifikationen hinzuzufügen, es ist jedoch möglich, dass diese nicht ganz korrekt sind. Sollten Sie einen solchen Fall feststellen, melden Sie ihn uns bitte.
Das Produkt ist für Fachleute bestimmt und erfordert qualifiziertes und autorisiertes Personal. Dem Produkt liegt keine Montage-/Gebrauchsanleitung bei . Die Inbetriebnahme des Produktes durch nicht qualifizierte Personen führt zum Verlust der Garantie gemäß den AGB auf der Seite.
Die angegebenen technischen Spezifikationen (Strom, Leistung usw.) stellen maximale zulässige Werte unter idealen Betriebsbedingungen dar. Für einen sicheren Betrieb und eine optimale Lebensdauer wird empfohlen, das Produkt im Dauerbetrieb mit höchstens 50 % der angegebenen Maximalwerte zu verwenden.
RTC-Uhrenmodul PCF8563, I2C-Schnittstelle, 1.0-5.5V, Alarm und Timer, Knopfzellenhalter
Hält Uhrzeit und Datum bei geringem Stromverbrauch, ideal für Projekte mit Arduino, Raspberry Pi und Automatisierungen. Der PCF8563 bietet eine einfache I2C-Kommunikation, Versorgung mit 3.3V oder 5V mit Backup-Batterie, eine gute Stabilität im Vergleich zu klassischen DS1307-Modulen sowie kompakte Abmessungen für eine einfache Integration in Aufbauten.
Shipping by Mittwoch 11 November
Mit dem Kauf dieses Produkts erhalten Sie 0,29 RON an Treuepunkten.
International fast shipping within EU. Free Shipping for orders above 100 EUR in most EU countries.
We ship from our stock within 24H
Sie erhalten bei jeder Bestellung Punkte im Wert von 5 %.
Das RTC-Uhrenmodul mit dem Schaltkreis PCF8563 speichert Uhrzeit und Datum in Echtzeit und behält sie auch dann bei, wenn die Hauptversorgung fehlt, solange sich im Halter eine Knopfzelle befindet. Es liefert Sekunden, Minuten, Stunden, Tag, Wochentag, Monat und Jahr, und die Daten werden über die I2C-Schnittstelle ausgelesen. Es eignet sich für Datenlogger mit Zeitstempel, Alarme, Digitaluhren, zeitgesteuerte Automatisierungen und alle Projekte, die nach einem Neustart die genaue Uhrzeit kennen müssen.
Der PCF8563 ist ein stromsparender CMOS-Echtzeituhrbaustein, der einen Quarz mit 32.768 kHz und einen Frequenzteiler verwendet, um die Zeitbasis von 1 Hz zu erzeugen. Neben Uhr und Kalender verfügt der Baustein über einen Alarm, einen Timer, eine Unterspannungserkennung mit Anzeige VL und einen programmierbaren Taktausgang mit den Frequenzen 32.768 kHz, 1.024 kHz, 32 Hz oder 1 Hz. Die I2C-Schnittstelle unterstützt eine Frequenz von bis zu 400 kHz, und die 7-Bit-Adresse lautet 0x51.
Zu den wichtigsten Merkmalen gehören der PCF8563 im SO8-Gehäuse (U4), der Quarz mit 32.768 kHz (Y1), der Halter für Knopfzellen, zwei Dioden und Siebkondensatoren auf der Platine, zwei Befestigungslöcher sowie der Steckverbinder J1 mit 6 Pins, beschriftet INT, COT, SCL, SDA, GND und VCC. Die Versorgung erfolgt über den Pin VCC mit 1.0 - 5.5 V, und bei Ausfall der Versorgung läuft die Uhr mit der Batterie im Halter weiter.
Über die I2C-Schnittstelle ist das Modul kompatibel mit Arduino, ESP32, ESP8266, STM32, Raspberry Pi und anderen Plattformen mit I2C-Bus, wobei nur zwei Datenleitungen, die Versorgung und Masse benötigt werden.
Spezifikationen:
Versorgungsspannung: 1.0 - 5.5 VDC
Stromaufnahme im Reservebetrieb: 0.25 µA typisch (bei 3.0 V und 25 °C)
Uhrenschaltkreis: PCF8563 (SO8)
Schnittstelle: I2C
I2C-Adresse: 0x51 (7-Bit)
Maximale I2C-Frequenz: 400 kHz (bei Versorgung von mindestens 1.8 V)
Quarz: 32.768 kHz (Y1)
Gelieferte Daten: Sekunden, Minuten, Stunden, Tag, Wochentag, Monat, Jahr, Jahrhundertanzeige
Zusatzfunktionen: Alarm, Timer, Unterspannungserkennung (Anzeige VL)
Programmierbarer Uhrenausgang (COT): 32.768 kHz, 1.024 kHz, 32 Hz oder 1 Hz
Interrupt-Ausgang (INT): Open-Drain, aktiv auf Low-Pegel
Reserveversorgung: Halter für Knopfzelle
Steckverbinder: J1, 6 Pins (INT, COT, SCL, SDA, GND, VCC)
Aufbau:
| Element | Funktion |
|---|---|
| Steckverbinder J1 | Steckverbinder mit 6 Pins, von oben nach unten beschriftet INT, COT, SCL, SDA, GND und VCC, für Versorgung, I2C-Bus und die beiden Ausgänge des Schaltkreises. |
| Schaltkreis U4 (PCF8563) | Echtzeituhr mit Kalender, Alarm, Timer und I2C-Schnittstelle, im SO8-Gehäuse. |
| Quarz Y1 | Quarz mit 32.768 kHz, der die Zeitbasis der Uhr liefert. |
| Halter für Knopfzelle | Versorgt die Uhr, wenn die Versorgung des Moduls fehlt, damit Uhrzeit und Datum erhalten bleiben. |
| Dioden D7 und D8 | Dioden neben dem Batteriehalter, im Versorgungskreis der Uhr. |
| Kondensatoren | Die Kondensatoren C10, C16 und C22 sowie ein Elektrolytkondensator filtern die Versorgung des Schaltkreises. |
| Befestigungslöcher | Zwei Löcher am Ende der Platine neben dem Batteriehalter, zur Befestigung des Moduls. |
Pinbelegung:
| Steckverbinder | Pin | Funktion |
|---|---|---|
| J1 | INT | Interrupt-Ausgang vom Typ Open-Drain, aktiv auf Low-Pegel, für Alarm und Timer |
| J1 | COT | Programmierbarer Uhrenausgang (CLKOUT), Open-Drain, standardmäßig 32.768 kHz |
| J1 | SCL | I2C-Takt |
| J1 | SDA | I2C-Daten |
| J1 | GND | Masse |
| J1 | VCC | Versorgung 1.0 - 5.5 VDC |
| I2C-Parameter | Wert |
|---|---|
| 7-Bit-Adresse | 0x51 |
| 8-Bit-Schreibadresse | A2h |
| 8-Bit-Leseadresse | A3h |
Verwendung:
Das Modul hat keine Taster, Potentiometer, Jumper oder LEDs, daher werden Uhrzeit und Datum nur über den I2C-Bus eingestellt und ausgelesen.
Setzen Sie eine Knopfzelle mit der richtigen Polarität in den Halter ein und prüfen Sie dabei den auf dem Halter aufgedruckten Typ, damit die Uhr auch bei abgeschalteter Versorgung des Moduls läuft.
Verbinden Sie den Pin VCC mit der Versorgung des Entwicklungsboards, den Pin GND mit der Masse, den Pin SDA mit der I2C-Datenleitung und den Pin SCL mit der I2C-Taktleitung. Achtung: Am Steckverbinder J1 liegt der Pin SCL über dem Pin SDA, umgekehrt zu vielen anderen Modulen.
Versorgen Sie das Modul mit einer Spannung zwischen 1.0 und 5.5 V, passend zum Logikpegel des Entwicklungsboards. Legen Sie nicht mehr als 5.5 V an und achten Sie auf die richtige Polarität.
Lassen Sie die Pins INT und COT unbeschaltet, wenn Sie Alarm, Timer oder Taktausgang nicht verwenden. Falls Sie diese nutzen, schalten Sie an jeden einen Pull-up-Widerstand, da beide Ausgänge vom Typ Open-Drain sind.
Lesen Sie die Adresse 0x51 am I2C-Bus aus, um zu prüfen, ob das Modul antwortet, und stellen Sie danach Uhrzeit und Datum, indem Sie die Register der Uhr beschreiben. Die Werte werden im BCD-Format gelesen und geschrieben.
Prüfen Sie die Anzeige VL im Register der Sekunden. Ist sie 1, ist die Uhrzeit nicht mehr garantiert und muss erneut eingestellt werden, und das Schreiben der Sekunden mit Bit 7 gleich 0 löscht die Anzeige.
Für stabile Ergebnisse verwenden Sie kurze Leitungen für SDA und SCL und wechseln Sie die Batterie, wenn die Uhrzeit nach einem Ausfall der Versorgung verloren geht. Die Genauigkeit hängt vom Quarz ab, daher ist für Anwendungen, die Exaktheit verlangen, eine periodische Synchronisation der Uhr sinnvoll.
- Versorgungsspannung
- 1.0-5.5 V DC
- Anzahl der Pins
- 6 (INT, COT, SCL, SDA, GND, VCC)
- Schnittstelle
- I2C
- Arbeitsfrequenz
- 400 kHz
- Integrierter Schaltkreis
- PCF8563
- Standby-Verbrauch
- 0.25 µA
- I2C-Adresse
- 0x51
- Batterietyp
- Knopfzelle
Produs destinat utilizarii in proiecte electronice, automatizari, prototipare, educatie si cercetare.
Produsul trebuie utilizat numai conform specificatiilor tehnice mentionate in descriere si/sau in documentatia produsului.
Avertismente generale de siguranta:
Nu utilizati produsul la tensiuni, curenti sau temperaturi peste valorile specificate.
Montajul si conectarea trebuie realizate de persoane cu cunostinte tehnice minime in domeniul electric/electronic.
Evitati scurtcircuitele, inversarea polaritatii si conectarea gresita a alimentarii.
Nu lasati produsul alimentat nesupravegheat in timpul testelor.
Produsul nu este jucarie si nu este destinat copiilor.
Pentru modulele electronice, se recomanda utilizarea in carcase, panouri sau montaje protejate, dupa caz.
Identificare produs:
Denumirea produsului, codul/SKU-ul si caracteristicile tehnice sunt mentionate in pagina produsului si/sau pe eticheta ambalajului.
Producator / Importator / Distribuitor:
Sigmanortec S.R.L.
Calea Bucuresti nr. 9, Targu Jiu, Gorj, Romania
E-mail: [email protected]
Website: www.sigmanortec.ro
Persoana responsabila in UE:
Sigmanortec S.R.L.
Calea Bucuresti nr. 9, Targu Jiu, Gorj, Romania
E-mail: [email protected]
Documentatie si siguranta:
Pentru informatii suplimentare, fise tehnice, declaratii de conformitate sau instructiuni, ne puteti contacta la [email protected].
/*
PCF8563 RTC module test
Board: Arduino Uno (Tools > Board > Arduino AVR Boards > Arduino Uno)
Board package: Arduino AVR Boards (comes with the Arduino IDE)
Libraries: none to install, the Wire library comes with the Arduino IDE
Wiring:
RTC VCC -> Arduino 5V
RTC GND -> Arduino GND
RTC SDA -> Arduino A4
RTC SCL -> Arduino A5
RTC INT and COT are not connected
The program sets the clock from the compile time when the time was never
set or the backup battery was lost, then prints the date and time every second.
*/
#include <Wire.h>
const uint8_t RTC_ADDRESS = 0x51; // 7-bit I2C address of the PCF8563
const uint8_t REG_CONTROL_1 = 0x00; // first register, control and status 1
const uint8_t REG_SECONDS = 0x02; // seconds register, bit 7 is the VL flag
const bool FORCE_SET_TIME = false; // set to true to rewrite the time at every start
const char *dayNames[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
// Convert a decimal number (0 - 99) to BCD
uint8_t decToBcd(uint8_t value) {
return ((value / 10) << 4) | (value % 10);
}
// Convert a BCD number to decimal
uint8_t bcdToDec(uint8_t value) {
return ((value >> 4) * 10) + (value & 0x0F);
}
// Day of the week from the date, 0 = Sunday
uint8_t dayOfWeek(uint16_t year, uint8_t month, uint8_t day) {
static const uint8_t offsets[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
if (month < 3) {
year -= 1;
}
return (year + year / 4 - year / 100 + year / 400 + offsets[month - 1] + day) % 7;
}
// Check if the module answers on the I2C bus
bool rtcPresent() {
Wire.beginTransmission(RTC_ADDRESS);
return Wire.endTransmission() == 0;
}
// Read several consecutive registers starting at startReg
bool readRegisters(uint8_t startReg, uint8_t *buffer, uint8_t length) {
Wire.beginTransmission(RTC_ADDRESS);
Wire.write(startReg);
if (Wire.endTransmission() != 0) {
return false;
}
if (Wire.requestFrom(RTC_ADDRESS, length) != length) {
return false;
}
for (uint8_t i = 0; i < length; i++) {
buffer[i] = Wire.read();
}
return true;
}
// Write the compile date and time into the clock
void setTimeFromCompileTime() {
const char *dateText = __DATE__; // format: "Mmm dd yyyy"
const char *timeText = __TIME__; // format: "hh:mm:ss"
const char *months = "JanFebMarAprMayJunJulAugSepOctNovDec";
char monthName[4] = {dateText[0], dateText[1], dateText[2], 0};
uint8_t month = (strstr(months, monthName) - months) / 3 + 1;
uint8_t day = ((dateText[4] == ' ') ? 0 : (dateText[4] - '0')) * 10 + (dateText[5] - '0');
uint16_t year = atoi(dateText + 7);
uint8_t hour = (timeText[0] - '0') * 10 + (timeText[1] - '0');
uint8_t minute = (timeText[3] - '0') * 10 + (timeText[4] - '0');
uint8_t second = (timeText[6] - '0') * 10 + (timeText[7] - '0');
Wire.beginTransmission(RTC_ADDRESS);
Wire.write(REG_CONTROL_1); // start at control register 1
Wire.write((uint8_t)0x00); // control 1: clock running
Wire.write((uint8_t)0x00); // control 2: no alarm or timer flags
Wire.write(decToBcd(second)); // seconds, bit 7 = 0 clears the VL flag
Wire.write(decToBcd(minute)); // minutes
Wire.write(decToBcd(hour)); // hours
Wire.write(decToBcd(day)); // day of the month
Wire.write(dayOfWeek(year, month, day)); // day of the week
Wire.write(decToBcd(month)); // month, century bit 0 means 20xx
Wire.write(decToBcd(year % 100)); // year (00 - 99)
Wire.endTransmission();
}
void setup() {
Serial.begin(9600);
Wire.begin();
if (!rtcPresent()) {
Serial.println("PCF8563 not found, check the wiring");
while (true) {
delay(1000);
}
}
Serial.println("PCF8563 found at address 0x51");
uint8_t secondsRegister = 0;
readRegisters(REG_SECONDS, &secondsRegister, 1);
bool vlFlag = (secondsRegister & 0x80) != 0; // 1 = time is not guaranteed
if (vlFlag || FORCE_SET_TIME) {
Serial.println("Time lost or forced, setting it from compile time");
setTimeFromCompileTime();
}
}
void loop() {
uint8_t data[7];
if (!readRegisters(REG_SECONDS, data, 7)) {
Serial.println("Read error");
delay(1000);
return;
}
bool vlFlag = (data[0] & 0x80) != 0;
uint8_t second = bcdToDec(data[0] & 0x7F); // mask the VL bit
uint8_t minute = bcdToDec(data[1] & 0x7F);
uint8_t hour = bcdToDec(data[2] & 0x3F);
uint8_t day = bcdToDec(data[3] & 0x3F);
uint8_t weekday = data[4] & 0x07;
uint8_t month = bcdToDec(data[5] & 0x1F); // mask the century bit
uint16_t year = 2000 + bcdToDec(data[6]);
char buffer[40];
snprintf(buffer, sizeof(buffer), "%04u-%02u-%02u %02u:%02u:%02u ",
(unsigned int)year, (unsigned int)month, (unsigned int)day,
(unsigned int)hour, (unsigned int)minute, (unsigned int)second);
Serial.print(buffer);
Serial.print(dayNames[weekday]);
if (vlFlag) {
Serial.print(" WARNING: time is not guaranteed");
}
Serial.println();
delay(1000); // one reading per second
}
In diesem Tutorial verwenden wir das Arduino Uno R3 Board. Das Uhrenmodul PCF8563 ist eine Echtzeituhr (RTC) mit I2C-Schnittstelle. Sie speichert Uhrzeit und Datum auch dann, wenn das Entwicklungsboard ausgeschaltet ist, solange eine Pufferbatterie im Halter steckt. Sie verwenden es für Datenprotokolle mit Zeitstempel, Alarme, digitale Uhren, zeitgesteuerte Automatisierungen und jedes Projekt, das nach einem Neustart wissen muss, wie spät es ist.
Das Modul enthält den Schaltkreis PCF8563 im Gehäuse SO8, einen Quarz mit 32.768 kHz (Y1) und einen Halter für eine Knopfzelle. Am Rand der Platine befindet sich eine Steckerleiste J1 mit 6 Pins, beschriftet mit INT, COT, SCL, SDA, GND und VCC. Die Platine hat keine Taster, Potentiometer, Jumper oder LEDs, daher wird alles, was Sie einstellen, im Programm vorgenommen.

So funktioniert es:
Der Quarz mit 32.768 kHz schwingt 32.768 Mal pro Sekunde, also 2 hoch 15. Die Schaltung teilt diese Frequenz bis auf 1 Hz herunter und erhöht bei jedem Impuls den Sekundenzähler. Aus dem Sekundenzähler ergeben sich Minuten, Stunden, Tag, Wochentag, Monat und Jahr, die alle in internen Registern gespeichert werden.
Die Werte in den Registern liegen im BCD-Format vor. Jede Dezimalziffer belegt 4 Bit, daher wird die Sekunde 45 als 0x45 gelesen und nicht als 0x2D. Das Programm wandelt von BCD in Dezimal mit der Formel (v >> 4) * 10 + (v AND 0x0F) um und zurück mit ((v / 10) << 4) OR (v MOD 10).
Das Register 0x02 (Sekunden) hat im Bit 7 die Anzeige VL (voltage low). Ist sie 1, ist die Versorgungsspannung zu stark gesunken oder der Oszillator wurde angehalten, und die Uhrzeit ist nicht mehr gesichert. Beim Schreiben der Sekunden mit Bit 7 gleich 0 wird die Anzeige gelöscht. Das Register 0x07 (Monat) hat im Bit 7 das Jahrhundertbit, das die Schaltung beim Übergang des Jahres von 99 auf 00 umschaltet. Im Programm gehen wir davon aus, dass der Wert 0 die Jahre 20xx bedeutet.
Die Schaltung besitzt außerdem einen Alarm, einen Timer und einen programmierbaren Taktausgang am Pin COT (CLKOUT) mit den Frequenzen 32.768 kHz, 1.024 kHz, 32 Hz oder 1 Hz, eingestellt über das Register an der Adresse 0x0D. Der Pin INT ist ein Interrupt-Ausgang, Open-Drain, aktiv bei Low-Pegel. In diesem Tutorial lesen wir nur Uhrzeit und Datum, daher bleiben COT und INT unbeschaltet.
Die Genauigkeit hängt nur vom Quarz ab, da die Schaltung keine Temperaturkompensation durchführt. Ein Quarz mit einer Abweichung von 20 ppm (als Beispielwert) ergibt ungefähr 20 x 86400 / 1000000 = 1.7 Sekunden pro Tag, also etwa 50 Sekunden pro Monat. Für ein Datenprotokoll ist das mehr als ausreichend, für eine Präzisionsuhr sollte eine regelmäßige Synchronisation erfolgen.
Die I2C-Adresse mit 7 Bit lautet 0x51. In der Dokumentation der Schaltung erscheinen die 8-Bit-Adressen A2h zum Schreiben und A3h zum Lesen, die Bibliothek Wire von Arduino arbeitet jedoch mit der 7-Bit-Adresse, also 0x51.
Anschluss:
Versorgen Sie das Modul über den 5V-Pin des Arduino Uno. Der Schaltkreis PCF8563 arbeitet im Bereich von 1.0 bis 5.5 V, daher ist 5 V geeignet, und die Logikpegel des I2C-Busses sind mit denen des Uno kompatibel, sodass Sie keinen Pegelwandler benötigen. Wenn Sie ein Board mit 3.3 V verwenden, versorgen Sie das Modul über 3.3 V. Das Arduino Board wird über das USB-A-B-Kabel vom Computer mit Strom versorgt. Setzen Sie die Knopfzelle mit der richtigen Polarität in den Halter ein und prüfen Sie dabei den auf dem Halter aufgedruckten Typ.
| Pin am Produkt | Anschluss an | Funktion |
|---|---|---|
| VCC | 5V | Versorgung des Moduls |
| GND | GND | Gemeinsame Masse |
| SDA | A4 | I2C-Daten |
| SCL | A5 | I2C-Takt |
| INT | Nicht angeschlossen | Interrupt-Ausgang für Alarm und Timer, hier nicht genutzt |
| COT | Nicht angeschlossen | Programmierbarer Taktausgang CLKOUT, hier nicht genutzt |
Auf dem Arduino Uno R3 sind die Pins SDA und SCL neben AREF dieselben Signale wie A4 und A5, daher können Sie diese anstelle davon verwenden. Wenn Sie die Pins der Steckerleiste anschließen, beachten Sie, dass die Reihenfolge von oben nach unten auf der Platine INT, COT, SCL, SDA, GND, VCC lautet. Achten Sie auf SDA und SCL, sie sind gegenüber vielen anderen Modulen vertauscht. Für einen stabilen I2C-Bus verwenden Sie kurze Leitungen.
Board und Bibliotheken:
Wählen Sie in der Arduino IDE Tools > Board > Arduino AVR Boards > Arduino Uno. Das Paket Arduino AVR Boards ist im Lieferumfang der Arduino IDE enthalten, daher muss unter File > Preferences keine Adresse eingetragen werden. Wählen Sie anschließend den Port des Boards unter Tools > Port aus.
Das Programm verwendet nur die Bibliothek Wire, die mit der Arduino IDE geliefert wird, daher muss keine Bibliothek installiert werden. Wir sprechen direkt mit den Registern des Schaltkreises, damit Sie genau nachvollziehen können, was gelesen und was geschrieben wird.
Der Code:
Das Programm stellt die Uhr auf die Compilezeit, wenn die Zeit nie eingestellt wurde oder die Batterie entfernt wurde, und zeigt danach jede Sekunde Datum und Uhrzeit an.
/*
PCF8563 RTC module test
Board: Arduino Uno (Tools > Board > Arduino AVR Boards > Arduino Uno)
Board package: Arduino AVR Boards (comes with the Arduino IDE)
Libraries: none to install, the Wire library comes with the Arduino IDE
Wiring:
RTC VCC -> Arduino 5V
RTC GND -> Arduino GND
RTC SDA -> Arduino A4
RTC SCL -> Arduino A5
RTC INT and COT are not connected
The program sets the clock from the compile time when the time was never
set or the backup battery was lost, then prints the date and time every second.
*/
#include <Wire.h>
const uint8_t RTC_ADDRESS = 0x51; // 7-bit I2C address of the PCF8563
const uint8_t REG_CONTROL_1 = 0x00; // first register, control and status 1
const uint8_t REG_SECONDS = 0x02; // seconds register, bit 7 is the VL flag
const bool FORCE_SET_TIME = false; // set to true to rewrite the time at every start
const char *dayNames[] = {"Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"};
// Convert a decimal number (0 - 99) to BCD
uint8_t decToBcd(uint8_t value) {
return ((value / 10) << 4) | (value % 10);
}
// Convert a BCD number to decimal
uint8_t bcdToDec(uint8_t value) {
return ((value >> 4) * 10) + (value & 0x0F);
}
// Day of the week from the date, 0 = Sunday
uint8_t dayOfWeek(uint16_t year, uint8_t month, uint8_t day) {
static const uint8_t offsets[] = {0, 3, 2, 5, 0, 3, 5, 1, 4, 6, 2, 4};
if (month < 3) {
year -= 1;
}
return (year + year / 4 - year / 100 + year / 400 + offsets[month - 1] + day) % 7;
}
// Check if the module answers on the I2C bus
bool rtcPresent() {
Wire.beginTransmission(RTC_ADDRESS);
return Wire.endTransmission() == 0;
}
// Read several consecutive registers starting at startReg
bool readRegisters(uint8_t startReg, uint8_t *buffer, uint8_t length) {
Wire.beginTransmission(RTC_ADDRESS);
Wire.write(startReg);
if (Wire.endTransmission() != 0) {
return false;
}
if (Wire.requestFrom(RTC_ADDRESS, length) != length) {
return false;
}
for (uint8_t i = 0; i < length; i++) {
buffer[i] = Wire.read();
}
return true;
}
// Write the compile date and time into the clock
void setTimeFromCompileTime() {
const char *dateText = __DATE__; // format: "Mmm dd yyyy"
const char *timeText = __TIME__; // format: "hh:mm:ss"
const char *months = "JanFebMarAprMayJunJulAugSepOctNovDec";
char monthName[4] = {dateText[0], dateText[1], dateText[2], 0};
uint8_t month = (strstr(months, monthName) - months) / 3 + 1;
uint8_t day = ((dateText[4] == ' ') ? 0 : (dateText[4] - '0')) * 10 + (dateText[5] - '0');
uint16_t year = atoi(dateText + 7);
uint8_t hour = (timeText[0] - '0') * 10 + (timeText[1] - '0');
uint8_t minute = (timeText[3] - '0') * 10 + (timeText[4] - '0');
uint8_t second = (timeText[6] - '0') * 10 + (timeText[7] - '0');
Wire.beginTransmission(RTC_ADDRESS);
Wire.write(REG_CONTROL_1); // start at control register 1
Wire.write((uint8_t)0x00); // control 1: clock running
Wire.write((uint8_t)0x00); // control 2: no alarm or timer flags
Wire.write(decToBcd(second)); // seconds, bit 7 = 0 clears the VL flag
Wire.write(decToBcd(minute)); // minutes
Wire.write(decToBcd(hour)); // hours
Wire.write(decToBcd(day)); // day of the month
Wire.write(dayOfWeek(year, month, day)); // day of the week
Wire.write(decToBcd(month)); // month, century bit 0 means 20xx
Wire.write(decToBcd(year % 100)); // year (00 - 99)
Wire.endTransmission();
}
void setup() {
Serial.begin(9600);
Wire.begin();
if (!rtcPresent()) {
Serial.println("PCF8563 not found, check the wiring");
while (true) {
delay(1000);
}
}
Serial.println("PCF8563 found at address 0x51");
uint8_t secondsRegister = 0;
readRegisters(REG_SECONDS, &secondsRegister, 1);
bool vlFlag = (secondsRegister & 0x80) != 0; // 1 = time is not guaranteed
if (vlFlag || FORCE_SET_TIME) {
Serial.println("Time lost or forced, setting it from compile time");
setTimeFromCompileTime();
}
}
void loop() {
uint8_t data[7];
if (!readRegisters(REG_SECONDS, data, 7)) {
Serial.println("Read error");
delay(1000);
return;
}
bool vlFlag = (data[0] & 0x80) != 0;
uint8_t second = bcdToDec(data[0] & 0x7F); // mask the VL bit
uint8_t minute = bcdToDec(data[1] & 0x7F);
uint8_t hour = bcdToDec(data[2] & 0x3F);
uint8_t day = bcdToDec(data[3] & 0x3F);
uint8_t weekday = data[4] & 0x07;
uint8_t month = bcdToDec(data[5] & 0x1F); // mask the century bit
uint16_t year = 2000 + bcdToDec(data[6]);
char buffer[40];
snprintf(buffer, sizeof(buffer), "%04u-%02u-%02u %02u:%02u:%02u ",
(unsigned int)year, (unsigned int)month, (unsigned int)day,
(unsigned int)hour, (unsigned int)minute, (unsigned int)second);
Serial.print(buffer);
Serial.print(dayNames[weekday]);
if (vlFlag) {
Serial.print(" WARNING: time is not guaranteed");
}
Serial.println();
delay(1000); // one reading per second
}
So funktioniert der Code:
Am Anfang stehen die Definitionen. RTC_ADDRESS ist die 7-Bit-I2C-Adresse des Schaltkreises, also 0x51. REG_CONTROL_1 ist das erste Register (0x00), und REG_SECONDS ist das Register der Sekunden (0x02), dessen Bit 7 die Anzeige VL ist. Die Konstante FORCE_SET_TIME rescheibt die Uhrzeit bei jedem Start, wenn Sie sie auf true setzen. Das Feld dayNames enthält die Namen der Wochentage in der Reihenfolge, in der das Programm sie nummeriert, beginnend mit 0 für Sonntag.
Die Funktionen decToBcd und bcdToDec wandeln zwischen der Dezimalzahl und dem BCD-Format um, das die Register verwenden. Die Funktion dayOfWeek berechnet den Wochentag aus dem Datum, weil die Uhr ihn nicht selbst ableitet und wir ihn selbst schreiben müssen. Die Funktion rtcPresent sendet eine leere Übertragung an die Adresse 0x51 und liefert true zurück, wenn das Modul antwortet.
Die Funktion readRegisters sendet die Adresse des Startregisters, fordert danach length Bytes mit Wire.requestFrom an und legt sie im Puffer ab. Der Schaltkreis erhöht die Registeradresse selbst, daher liest eine einzige Anforderung alle Werte von den Sekunden bis zum Jahr.
Die Funktion setTimeFromCompileTime entnimmt Datum und Uhrzeit den Makros __DATE__ und __TIME__, berechnet den Monat anhand der Position des Namens im Feld months und schreibt die Register von 0x00 bis 0x08 in dieser Reihenfolge. Die Sekunden werden mit Bit 7 gleich 0 geschrieben, wodurch die Anzeige VL gelöscht wird, und das Jahrhundertbit im Monat bleibt 0.
Im setup starten wir die serielle Schnittstelle mit 9600 Baud und den I2C-Bus mit Wire.begin. Liefert rtcPresent false zurück, zeigt das Programm eine Fehlermeldung an und hält an. Andernfalls lesen wir das Register der Sekunden, und wenn vlFlag gleich 1 ist oder FORCE_SET_TIME true ist, rufen wir setTimeFromCompileTime auf.
Im loop lesen wir 7 Register ab 0x02 in das Feld data. Aus jedem Wert maskieren wir die Bits, die nicht zur Zahl gehören (0x7F für Sekunden und Minuten, 0x3F für Stunden und Tag, 0x1F für den Monat), und wandeln sie aus BCD um. Das Jahr ergibt sich als 2000 plus den Wert aus dem Register der Jahre. Die Zeile wird mit snprintf formatiert, zusammen mit dem Namen des Wochentags ausgegeben und, wenn vlFlag gleich 1 ist, mit einer Warnung versehen. Am Ende sorgt delay(1000) für eine Ablesung pro Sekunde.
Ergebnis:
Öffnen Sie den Serial Monitor über Tools und stellen Sie die Geschwindigkeit auf 9600 Baud ein. Beim ersten Start erscheinen die Meldungen über das gefundene Modul und die Einstellung der Uhrzeit, danach eine Zeile pro Sekunde mit Datum, Uhrzeit und Wochentag. Bei den nächsten Starts wird die Uhrzeit nicht mehr eingestellt, solange die Batterie im Halter steckt.
PCF8563 found at address 0x51
Time lost or forced, setting it from compile time
2025-03-14 10:22:31 Friday
2025-03-14 10:22:32 Friday
2025-03-14 10:22:33 Friday
2025-03-14 10:22:34 Friday
2025-03-14 10:22:35 Friday
2025-03-14 10:22:36 Friday
Häufige Probleme:
Im seriellen Monitor erscheint die Meldung PCF8563 not found. Die Ursache ist meist eine falsche Verdrahtung oder eine fehlende Versorgung. Prüfen Sie, ob SDA an A4 und SCL an A5 angeschlossen ist, und beachten Sie, dass auf der Steckerleiste SCL über SDA liegt, und ob VCC an 5V und GND an GND liegt.
Im seriellen Monitor erscheint nichts oder seltsame Zeichen. Die Ursache ist eine falsche Geschwindigkeit. Stellen Sie im Serial Monitor 9600 Baud ein und prüfen Sie, ob der gewählte Port der des Arduino Uno Boards ist.
Die Uhrzeit ist nach jedem Ausschalten der Versorgung falsch. Die Ursache ist eine fehlende oder entladene Batterie im Halter oder eine verkehrt herum eingesetzte Batterie. Setzen Sie eine passende Batterie ein, stellen Sie dann FORCE_SET_TIME auf true, laden Sie das Programm einmal hoch und setzen Sie es danach wieder auf false.
Die Warnung time is not guaranteed erscheint. Die Anzeige VL ist 1, also ist die Versorgungsspannung zu stark gesunken oder der Oszillator wurde angehalten. Stellen Sie die Uhrzeit erneut ein, und falls die Warnung wieder erscheint, tauschen Sie die Batterie aus.
Die Uhr stellt die Compilezeit ein, geht aber einige Sekunden nach. Die Ursache ist die Zeit zwischen dem Kompilieren und dem Hochladen des Programms auf das Board. Für eine genaue Uhrzeit stellen Sie die Uhr aus einer externen Quelle ein, zum Beispiel vom Computer oder von einem Zeitserver.
Die Uhr weicht um einige Sekunden pro Monat ab. Das ist normal, da die Genauigkeit vom Quarz abhängt und der Schaltkreis keine Temperaturkompensation hat. Synchronisieren Sie die Uhr regelmäßig, wenn Sie eine bessere Genauigkeit benötigen.
Einschränkungen und Tipps:
Die Uhr arbeitet im Bereich von 1.0 bis 5.5 V, doch für die I2C-Kommunikation mit 400 kHz muss die Versorgung mindestens 1.8 V betragen. Die Genauigkeit wird durch den Quarz mit 32.768 kHz bestimmt und ändert sich mit der Temperatur, daher ersetzt sie keine Uhr mit Temperaturkompensation, wenn es pro Monat auf Bruchteile einer Sekunde ankommt.
Das Modul hält die Uhrzeit nur, solange sich eine Batterie in gutem Zustand im Halter befindet, und der Verbrauch im Pufferbetrieb ist sehr gering, typisch 0.25 µA bei 3.0 V und 25 °C. Wenn Sie die Ausgänge INT und COT verwenden, fügen Sie Pull-up-Widerstände hinzu, da beide Open-Drain sind.
Außerdem können Sie den Alarm und den Timer des Schaltkreises nutzen, wobei der Ausgang INT mit einem Interrupt-Eingang verbunden wird, um das Board aus einem Energiesparmodus zu wecken. Sie können auch den Ausgang COT mit 1 Hz als Zeitbasis für andere Schaltungen verwenden oder ein Datenprotokoll mit Zeitstempel auf einer SD-Karte aufbauen.