Hier noch der 2. Teil:
Bibliothek (RP6DCFClockCClib.cc), Teil 2:
Gruß DirkCode:/** * DCF DECODER * * Dies ist der DCF77 Decoder. * * Der (abschaltbare) DCF Decoder in dieser Funktion decodiert die * DCF Informationen und stellt die Uhr mit den empfangenen Daten. * * Die Funktion decodeDCF() muss alle 10ms aufgerufen werden. * */ void decodeDCF(void) {byte temp, dcfbit; static byte impulsdauer, alterpegel, paritaet; static byte dcfbitzaehler, dcfbitpuffer; #ifdef WETTER static unsigned int wetterpuffer; #endif static byte jahrpuffer, monatpuffer, wochentagpuffer, tagpuffer; static byte sommerzeitpuffer, stundepuffer, minutepuffer, dcfflagspuffer; if (!(dcfstatus & STATUS_DCF_AN)) { return; // DCF Decoder AUS! } // DCF77 Decoder: temp = Port_ReadBit(DCF_IN); // DCF Eingang lesen if (temp == alterpegel) { // Keine Pegeländerung impulsdauer++; if (impulsdauer >= (PAUSE_1900MS + (PAUSE_ABWEICHUNG * 3))) { impulsdauer = 0; dcfstatus = dcfstatus | STATUS_FEHLER; } return; // Ende DCF Decoder! } else { // Pegeländerung am Eingang #ifdef REPARATUR // Nach 1ms Port neu lesen zum Erkennen von "Spikes": // (Spikes sind kurze Störsignale von elektr. Geräten) AbsDelay(1); // 1ms Verzögerung if (temp != Port_ReadBit(DCF_IN)) { // Keine Pegeländerung impulsdauer++; return; } #endif alterpegel = temp; dcfbit = BIT_FEHLER; if ((impulsdauer >= (PAUSE_900MS - PAUSE_ABWEICHUNG)) && (impulsdauer < (PAUSE_900MS + PAUSE_ABWEICHUNG))) { dcfbit = BIT_0; // Bit 0 decodiert #ifdef DEBUG pause_0_laenge = impulsdauer; #endif } if ((impulsdauer >= (PAUSE_800MS - PAUSE_ABWEICHUNG)) && (impulsdauer < (PAUSE_800MS + PAUSE_ABWEICHUNG))) { dcfbit = BIT_1; // Bit 1 decodiert paritaet++; #ifdef DEBUG pause_1_laenge = impulsdauer; #endif } if ((impulsdauer >= (PAUSE_1900MS - PAUSE_ABWEICHUNG)) && (impulsdauer < (PAUSE_1900MS + PAUSE_ABWEICHUNG))) { dcfbit = LETZTESBIT_0; // Letztes Bit 0 decodiert #ifdef DEBUG letztepause_0_laenge = impulsdauer; #endif } if ((impulsdauer >= (PAUSE_1800MS - PAUSE_ABWEICHUNG)) && (impulsdauer < (PAUSE_1800MS + PAUSE_ABWEICHUNG))) { dcfbit = LETZTESBIT_1; // Letztes Bit 1 decodiert paritaet++; #ifdef DEBUG letztepause_1_laenge = impulsdauer; #endif } impulsdauer = 0; // Impulsdauer zurücksetzen if (dcfbit != BIT_FEHLER) { // Kein DCF Bitfehler dcfbitpuffer = dcfbitpuffer >> 1; // Puffer nach rechts schieben dcfbitpuffer = dcfbitpuffer | (dcfbit & 0x80); // DCF Bit einfügen switch (dcfbitzaehler) { #ifdef WETTER case 7 : wetterpuffer = dcfbitpuffer; // Wetter Infos (Bits 0..7) if (wetterpuffer & 0x0001) { // DCF Bit 0 == 1 ? dcfstatus = dcfstatus | STATUS_FEHLER; // -> Fehler! } dcfbitpuffer = 0; break; #endif case 14 : #ifdef WETTER // Wetter Infos (Bits 8..14) wetterpuffer = wetterpuffer | (dcfbitpuffer << 7); #endif dcfstatus = dcfstatus & (~STATUS_TELEGRAMMINTAKT); dcfbitpuffer = 0; break; case 20 : dcfflagspuffer = dcfbitpuffer >> 2; // DCF Flags if (dcfflagspuffer & FLAG_Z1) { // Z1: Zeitzone sommerzeitpuffer = 1; // [1 = MESZ] if (dcfflagspuffer & FLAG_Z2) { // Z1 == Z2 ? dcfstatus = dcfstatus | STATUS_FEHLER; // -> Fehler! } } else { sommerzeitpuffer = 0; // [0 = MEZ] if (!(dcfflagspuffer & FLAG_Z2)) { // Z1 == Z2 ? dcfstatus = dcfstatus | STATUS_FEHLER; // -> Fehler! } } if (!(dcfflagspuffer & FLAG_S)) { // Start Bit == 0 ? dcfstatus = dcfstatus | STATUS_FEHLER; // -> Fehler! } dcfbitpuffer = 0; paritaet = 0; break; case 27 : minutepuffer = BCDtoDEC(dcfbitpuffer >> 1); // Minute if (minutepuffer > 59) { // Minute > 59 ? dcfstatus = dcfstatus | STATUS_FEHLER; // -> Fehler! } break; case 28 : if (!(paritaet & 1)) { // P1: Parität ok ? dcfstatus = dcfstatus | STATUS_MINPARITAET; } dcfbitpuffer = 0; paritaet = 0; break; case 34 : stundepuffer = BCDtoDEC(dcfbitpuffer >> 2); // Stunde if (stundepuffer > 23) { // Stunde > 23 ? dcfstatus = dcfstatus | STATUS_FEHLER; // -> Fehler! } break; case 35 : if (!(paritaet & 1)) { // P2: Parität ok ? dcfstatus = dcfstatus | STATUS_STDPARITAET; } dcfbitpuffer = 0; paritaet = 0; break; case 41 : tagpuffer = BCDtoDEC(dcfbitpuffer >> 2); // Tag if ((tagpuffer == 0) || (tagpuffer > 31)) { dcfstatus = dcfstatus | STATUS_FEHLER; // -> Fehler! } dcfbitpuffer = 0; break; case 44 : wochentagpuffer = dcfbitpuffer >> 5; // Wochentag if ((wochentagpuffer == 0) || (wochentagpuffer > 7)) { dcfstatus = dcfstatus | STATUS_FEHLER; // -> Fehler! } dcfbitpuffer = 0; break; case 49 : monatpuffer = BCDtoDEC(dcfbitpuffer >> 3); // Monat if ((monatpuffer == 0) || (monatpuffer > 12)) { dcfstatus = dcfstatus | STATUS_FEHLER; // -> Fehler! } dcfbitpuffer = 0; break; case 57 : jahrpuffer = BCDtoDEC(dcfbitpuffer); // Jahr if (jahrpuffer > 99) { dcfstatus = dcfstatus | STATUS_FEHLER; // -> Fehler! } break; case 58 : dcfstatus = dcfstatus | STATUS_DCFBIT58; if (!(paritaet & 1)) { // P3: Parität ok ? dcfstatus = dcfstatus | STATUS_DATPARITAET; } break; case 59 : // Schaltsekundenbit if ((dcfbitpuffer & 0x80) || (!(dcfflagspuffer & FLAG_A2))) { dcfstatus = dcfstatus | STATUS_FEHLER; // -> Fehler! } break; case 60 : // Mehr als 59 Bits? dcfstatus = dcfstatus & (~STATUS_DCFBIT58); // -> Fehler! } if (dcfbit & LETZTESBIT_0) { // Ein letztes Bit (Telegrammende): if ((!(dcfstatus & STATUS_FEHLER)) && (dcfstatus & STATUS_MINPARITAET) && (dcfstatus & STATUS_STDPARITAET) && (dcfstatus & STATUS_DATPARITAET) && (dcfstatus & STATUS_DCFBIT58)) { // Telegramm fehlerfrei? dcfstatus = dcfstatus | STATUS_TELEGRAMMINTAKT; // Ja! validitaetszaehler++; if (validitaetszaehler >= validitaetsgrenze) { validitaetszaehler = validitaetsgrenze; #ifdef WETTER DCF_WEATHER = wetterpuffer; #endif dcfflags = dcfflagspuffer; Clock_SetTime(stundepuffer, minutepuffer, 0, CLOCK_CORR); // Uhr stellen! DCF_DST = sommerzeitpuffer; DCF_DOW = wochentagpuffer; tagpuffer--; // Tag und Monat monatpuffer--; // ... nullbasiert! Clock_SetDate(tagpuffer, monatpuffer, jahrpuffer); dcfstatus = dcfstatus | STATUS_UHRGESTELLT; } } else { // Telegramm NICHT intakt oder plausibel: validitaetszaehler = 0; // Validitätszähler zurücksetzen } // Vorbereitung auf nächstes DCF Telegramm: dcfstatus = dcfstatus & (~(STATUS_FEHLER | STATUS_MINPARITAET | STATUS_STDPARITAET | STATUS_DATPARITAET | STATUS_DCFBIT58)); // 5 Status Bits löschen dcfbitpuffer = 0; dcfbitzaehler = 0; } else { // Kein Telegramm Ende: dcfbitzaehler++; // Nächstes DCF Bit decodieren } } // Kein DCF Bitfehler } // Pegeländerung am Eingang } /******************************************************************************/ // Nützliche LCD Funktionen: /** * SHOW CLOCK * * Format: Uhrzeit * Datum * */ void showCLOCK(void) {byte temp; setCursorPosLCD(0, 1); // Zeile 1 temp = Clock_GetVal(CLOCK_HOUR); if (temp < 10) { writeCharLCD('0'); } printIntegerLCD(temp); writeCharLCD(':'); temp = Clock_GetVal(CLOCK_MIN); if (temp < 10) { writeCharLCD('0'); } printIntegerLCD(temp); writeCharLCD(':'); temp = Clock_GetVal(CLOCK_SEC); if (temp < 10) { writeCharLCD('0'); } printIntegerLCD(temp); if (dcfstatus & STATUS_UHRGESTELLT) { if (DCF_DST) { // MESZ? printLCD(" MESZ"); } else { printLCD(" MEZ"); } } setCursorPosLCD(1, 1); // Zeile 2 switch (DCF_DOW) { // Wochentag case 1 : printLCD("Mo"); break; case 2 : printLCD("Di"); break; case 3 : printLCD("Mi"); break; case 4 : printLCD("Do"); break; case 5 : printLCD("Fr"); break; case 6 : printLCD("Sa"); break; case 7 : printLCD("So"); break; default : printLCD("--"); } printLCD(", "); temp = Clock_GetVal(CLOCK_DAY) + 1; // Tag nullbasiert! if (temp < 10) { writeCharLCD('0'); } printIntegerLCD(temp); writeCharLCD('.'); temp = Clock_GetVal(CLOCK_MON) + 1; // Monat nullbasiert! if (temp < 10) { writeCharLCD('0'); } printIntegerLCD(temp); printLCD(".20"); temp = Clock_GetVal(CLOCK_YEAR); if (temp < 10) { writeCharLCD('0'); } printIntegerLCD(temp); } /** * SHOW STATUS * * Format: Status * Uhrzeit * */ void showSTATUS(void) {byte i, temp; setCursorPosLCD(0, 1); // Zeile 1 printLCD("Stat: "); temp = dcfstatus; for(i = 0; i < 8; i++) { if (temp & 0x80) { writeCharLCD('1'); } else { writeCharLCD('0'); } temp = temp << 1; } setCursorPosLCD(1, 1); // Zeile 2 temp = Clock_GetVal(CLOCK_HOUR); if (temp < 10) { writeCharLCD('0'); } printIntegerLCD(temp); writeCharLCD(':'); temp = Clock_GetVal(CLOCK_MIN); if (temp < 10) { writeCharLCD('0'); } printIntegerLCD(temp); writeCharLCD(':'); temp = Clock_GetVal(CLOCK_SEC); if (temp < 10) { writeCharLCD('0'); } printIntegerLCD(temp); if (dcfstatus & STATUS_UHRGESTELLT) { if (DCF_DST) { // MESZ? printLCD(" MESZ"); } else { printLCD(" MEZ"); } } } #ifdef DEBUG /** * SHOW DEBUG INFO * */ void showDEBUGINFO(void) { setCursorPosLCD(0, 1); // Zeile 1 printLCD("P1/0: "); printIntegerLCD(pause_1_laenge); printLCD(" / "); printIntegerLCD(pause_0_laenge); printLCD(" "); setCursorPosLCD(1, 1); // Zeile 2 printLCD("L1/0: "); printIntegerLCD(letztepause_1_laenge); printLCD(" / "); printIntegerLCD(letztepause_0_laenge); printLCD(" "); } #endif /****************************************************************************** * Info * **************************************************************************** * Changelog: * - v. 1.0 (initial release) 13.06.2009 by Dirk * * **************************************************************************** */ /*****************************************************************************/ // EOF







Zitieren

Lesezeichen