/* Das Programm dekodiert die DCF77 Zeit, macht die Paritätsprüfung und schickt die vier benötigten Ziffern für die Zeitanzeige als serielle Daten über den TX Pin 1 an den Anzeigecontroller. Datengeschwindigkeit: 9600 Baud Wenn ein gültiges Signal gesendet wurde, gibt es eine Pause von 30 Minuten, in dieser Zeit wird der DCF Empfänger an Pin 6 abgeschaltet. mit Hilfe von: https://wolles-elektronikkiste.de/dcf77-funkuhr 30.04.2025 */ #include //comment out if you don't use an AVR MCU #define dcfOnOut 6 int interruptPin = 2; volatile unsigned long lastInt = 0; volatile unsigned long long currentBuf = 0; volatile byte bufCounter; volatile bool parityStat = 0; volatile byte dcf77MinuteEiner = 0; volatile byte dcf77MinuteZehner = 0; volatile byte dcf77HourEiner = 0; volatile byte dcf77HourZehner = 0; void setup() { Serial.begin(9600); pinMode(dcfOnOut, OUTPUT); digitalWrite(dcfOnOut, HIGH); pinMode(interruptPin, INPUT); attachInterrupt(digitalPinToInterrupt(interruptPin), DCF77_ISR, CHANGE); } void loop() { if (parityStat == 1) { delay(100); Serial.print(dcf77HourZehner); Serial.print(","); Serial.print(dcf77HourEiner); Serial.print(","); Serial.print(dcf77MinuteZehner); Serial.print(","); Serial.print(dcf77MinuteEiner); delay(100); digitalWrite(dcfOnOut, LOW); parityStat = 0; delay(1800000); // 30 Minuten, 15 Minuten Wartezeit: 900000 digitalWrite(dcfOnOut, HIGH); } } /************************************************************************* lesen des dcf Signals am Pin 2 **************************************************************************/ void DCF77_ISR() { // unsigned int dur = 0; dur = millis() - lastInt; if (digitalRead(interruptPin)) { if (dur > 1500) { unsigned long highBuf = (currentBuf >> 32) & 0x7FFFFFF; unsigned long lowBuf = (currentBuf & 0xFFFFFFFF); bufCounter = 0; evaluateSequence(); currentBuf = 0; } } else { if (dur > 150) { currentBuf |= ((unsigned long long)1 << bufCounter); } bufCounter++; } lastInt = millis(); } /************************************************************************** Umwandlung Binärcode in Ziffern *************************************************************************/ void evaluateSequence() { parityStat = 1; byte dcf77Year = (currentBuf >> 50) & 0xFF; // year = bit 50-57 byte dcf77Month = (currentBuf >> 45) & 0x1F; // month = bit 45-49 byte dcf77DayOfWeek = (currentBuf >> 42) & 0x07; // day of the week = bit 42-44 byte dcf77DayOfMonth = (currentBuf >> 36) & 0x3F; // day of the month = bit 36-41 byte dcf77Hour = (currentBuf >> 29) & 0x3F; dcf77HourEiner = (currentBuf >> 29) & 0xF; // hour = bit 29-34, 6 bit dcf77HourZehner = (currentBuf >> 33) & 0x3; // hour = bit 29-34, 6 bit byte dcf77Minute = (currentBuf >> 21) & 0x7F; dcf77MinuteEiner = (currentBuf >> 21) & 0xF; // minute = 21-27, 7 bit dcf77MinuteZehner = (currentBuf >> 25) & 0x7; // minute = 21-27, 7 bit bool parityBitMinute = (currentBuf >> 28) & 1; bool parityBitHour = (currentBuf >> 35) & 1; bool parityBitDate = (currentBuf >> 58) & 1; /*************************************************************************** Paritätsprüfung ***************************************************************************/ if ((parity_even_bit(dcf77Minute)) != parityBitMinute) { parityStat = 0; } if ((parity_even_bit(dcf77Hour)) != parityBitHour) { parityStat = 0; } if (((parity_even_bit(dcf77DayOfMonth) + parity_even_bit(dcf77DayOfWeek) + parity_even_bit(dcf77Month) + parity_even_bit(dcf77Year)) % 2) != parityBitDate) { parityStat = 0; } if (dcf77MinuteEiner > 9) { parityStat = 0; } if (dcf77MinuteZehner > 5) { parityStat = 0; } if (dcf77HourEiner > 9) { parityStat = 0; } if (dcf77HourZehner > 2) { parityStat = 0; } if (dcf77Hour == 0 && dcf77Minute == 0) { parityStat = 0; } } unsigned int rawByteToInt(byte raw) { return ((raw >> 4) * 10 + (raw & 0x0F)); }