/* 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 19.05.2025 www.buschke.net info@buschke.net */ #include //comment out if you don't use an AVR MCU #define dcfOnOff 6 int interruptPin = 2; volatile unsigned long lastInt = 0; volatile unsigned long long currentBuf = 0; volatile byte bufCounter; volatile byte parityStat = 0; volatile byte dcf77MinuteEiner = 0; volatile byte dcf77MinuteZehner = 0; volatile byte dcf77HourEiner = 0; volatile byte dcf77HourZehner = 0; volatile int testVar = 0; unsigned long startMillis = 0; const long waitingTime = 1800000; // 30 Minuten byte dcfState = 0; void setup() { Serial.begin(9600); pinMode(dcfOnOff, OUTPUT); digitalWrite(dcfOnOff, 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); dcfState = LOW; digitalWrite(dcfOnOff, dcfState); parityStat = 0; } unsigned long currentMillis = millis(); if (currentMillis - startMillis >= waitingTime) { startMillis = currentMillis; if (dcfState == HIGH) { dcfState = LOW; } else { dcfState = HIGH; } digitalWrite(dcfOnOff, dcfState); } } /************************************************************************* 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); testVar = bufCounter; 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; 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 (testVar != 59) { parityStat = 0; } }