Hallo Besitzer der Zusatzplatine RP6 CCPRO M128,
die mitgelieferte Library DCF_Lib.cc hat gerade so die basalen Funktionen eines DCF-Decoders. Mit dieser Bibliothek RP6DCFCCLib.cc wird das besser. Viel Spaß damit.
Demo (DCF_RTC.cc):Bibliothek (RP6DCFCClib.cc), Teil 1:Code:/******************************************************************************* * RP6 C-Control PRO M128 Erweiterungsmodul * ---------------------------------------------------------------------------- * DCF_RTC Demoprogramm 2 * ---------------------------------------------------------------------------- * DCF_RTC: DCF Uhr * DCF Empfänger erforderlich * Mega128: DCF-Eingang PE5 (PortE.5, RP6: INT1) * Der DCF-Eingang kann in RP6DCFCClib.cc geändert werden. * erforderliche Library: IntFunc_Lib.cc und neue RP6DCFCClib.cc (v. 1.xx). * * Über den zusätzlich erforderlichen DCF Empfänger (Art-Nr. 641138) wird * das DCF Signal empfangen. * Auf dem LCD-Display werden die Zeit und das Datum angezeigt. * Die LED1 blinkt im Sekundentakt. * * Hinweis: * Für allgemeine Programmierhinweise zur CCPRO schauen Sie sich bitte die * CCPRO Dokumentation und die zugehörigen Beispielprogramme an! * Es sei auch nochmals darauf hingewiesen, dass die normalen Beispielprogramme * für die CCPRO nur zum Teil direkt auf dem RP6-CCPRO Modul laufen. * Die Anschlussbelegung ist natürlich komplett anders als auf dem * C-Control Application Board. Auch die LCD Ansteuerung ist leicht anders, * da hier noch zusätzliche LEDs mit an dem Schieberegister angeschlossen sind. * --> Die C-Control Beispielprogramme müssen ein klein wenig angepasst * werden bevor sie auf diesem Modul laufen können! * * ***************************************************************************** * Der Roboter bewegt sich in diesem Beispielprogramm NICHT und kann * am Rechner angeschlossen bleiben! ******************************************************************************/ // WICHTIG: Immer die RP6CCLib mit einbinden: #include "../../RP6CCLib/RP6CCLib.cc" // Die neue RP6DCFCCLib einbinden: #include "../../RP6CCLib/RP6DCFCClib.cc" int irqcnt; // globale Variablendeklaration byte cnt1, alte_sekunde; void main(void) { // WICHTIG! Immer als erstes aufrufen: RP6_CCPRO_Init(); // Auf Startsignal warten, LCD und andere Dinge initialisieren ! // ------------------------------------------------------ // Zwei Zeilen Text mit dem LCD anzeigen: showScreenLCD("RP6 CCPRO M128", "DCF RTC Demo 2!"); // Zweimal piepsen: beep(200, 300, 100); // Format: beep (<tonhöhe>, <dauer>, <pause>) beep(100, 100, 100); // Text über serielle Schnittstelle ausgeben: newline(); // Neue Zeile println(" ________________________"); println(" \\| RP6 ROBOT SYSTEM |/"); println(" \\_-_-_-_-_-_-_-_-_-_/ "); newline(); println(" Let's go! "); newline(); // 2 Sekunden Pause: AbsDelay(2000); // ------------------------------------------------------ // DCF-Hauptprogramm: Port_WriteBit(PORT_LED1, PORT_OFF); // LED1 aus clearLCD(); // Display löschen Time_Init(); // Funktionsaufruf zur Festlegung // von Startzeit und Startdatum. initDCF(); // Initialisierung des DCF Modus Irq_SetVect(INT_TIM2COMP, INT_10ms); // ISR definieren // Timer2: 10ms Interrupt while (1) // Endlosschleife { if (cnt1 == 50) Port_WriteBit(PORT_LED1, PORT_OFF); // LED1 aus if (cnt1 == 100) { // Sekundentakt Port_WriteBit(PORT_LED1, PORT_ON); // LED1 an cnt1 = 0; } if (alte_sekunde != Sekunde) { alte_sekunde = Sekunde; #ifndef DEBUG showCLOCK(); // showSTATUS(); #endif #ifdef DEBUG showDEBUGINFO(); #endif } } } //------------------------------------------------------------------------------ // Festlegung von Startzeit und Startdatum // void Time_Init(void) { Sekunde = 0; // Uhr Startzeit: 12:00:00 Minute = 0; Stunde = 12; Wochentag = 7; Tag = 31; // Uhr Startdatum: 31.05.2009 Monat = 5; Jahr = 9; } //------------------------------------------------------------------------------ // Interrupt Routine // void INT_10ms(void) { cnt1++; // Zähler für Blinken der LED1 decodeDCF(); // DCF77 Decoder irqcnt = Irq_GetCount(INT_TIM2COMP); // Interrupt Request Counter } //------------------------------------------------------------------------------Gruß DirkCode:/* **************************************************************************** * _______________________ * \| RP6 ROBOT SYSTEM |/ * \_-_-_-_-_-_-_-_-_-_/ >>> CCPRO M128 * ---------------------------------------------------------------------------- * ----------------------- [c]2009 - Dirk ------------------------------------- * **************************************************************************** * File: RP6DCFCClib.cc * Version: 1.0 - CompactC * Target: RP6 CCPRO M128 - C-Control PRO M128 @14.7456MHz * mit optionalem LC-Display 16x2 Zeichen (CONRAD 190911) * [oder OLED Textdisplay 16x2 Zeichen (CONRAD 197622)] * und einem DCF77 Empfänger Modul (z.B. CONRAD 641138) * Author(s): Dirk * **************************************************************************** * Beschreibung: * Dies ist meine DCF77 Bibliothek für die RP6 CCPRO M128. * Der DCF-Empfänger wird an PE5 (XBUS INT1, SPI_I/O: Pin 7) der CCPRO M128 * angeschlossen. * * ANMERKUNG: Ein 10 kOhm Pulldown-Widerstand (R34) ist auf dem RP6 Mainboard * mit E_INT1 verbunden und damit auch mit INT1 auf der CCPRO M128. * Normalerweise haben DCF Empfänger einen open-collector Ausgang * und benötigen einen PULLUP Widerstand zur korrekten Funktion. * Der interne Pullup-Widerstand des ATMEGA128 kann den Pulldown- * Widerstand auf dem RP6 Mainboard nicht kompensieren. * Deshalb muss man einen PULLUP-Widerstand zwischen +5V und den * DCF Empfängerausgang legen. Bei meinem DCF Empfänger klappt es * gut mit einem 2,2 kOhm Widerstand. * * **************************************************************************** * CHANGELOG FINDEN SIE AM ENDE DIESER DATEI! * **************************************************************************** */ // Alles nur EINMAL einbinden! #ifndef __RP6DCFCCLIB__ #define __RP6DCFCCLIB__ /******************************************************************************/ // Defines: // RP6 CCPRO M128 DCF Empfänger Anschluß: #define DCF_IN 37 // DCF Eingangs Signale an PortE.5 (RP6: INT1) // #define DCF_IN 13 // DCF Eingangs Signal an PortB.5 (SERVO_1 PB5) #define BIT_0 0x00 // 0b00000000 #define BIT_1 0x80 // 0b10000000 #define LETZTESBIT_0 0x40 // 0b01000000 #define LETZTESBIT_1 0xc0 // 0b11000000 #define BIT_FEHLER 0x01 // 0b00000001 /**************************************************************/ // AUFBAU DES DCF77 TELEGRAMMS: // Bit 0: DCF Bit 0 (immer 0) // Bits 1..14: Codierte Wetter Infos (Meteo Time GmbH) // Bits 15..20 (DCF Flags): // Flag R: Ruf Bit 15 für PTB Angestellte // Flag A1: Ankündigung eines Zeitzonenwechsels // Flag Z1: Zeitzone 1 [0 = MEZ, 1 = MESZ] (Z1 != Z2) // Flag Z2: Zeitzone 2 [1 = MEZ, 0 = MESZ] (Z2 != Z1) // Flag A2: Ankündigung einer Schaltsekunde // Flag S: Start Bit 20 (immer 1) // Bits 21..27: Minute (BCD) // Bit 28 [P1]: Minutenparität // Bits 29..34: Stunde (BCD) // Bit 35 [P2]: Stundenparität // Bits 36..41: Tag (BCD) // Bits 42..44: Wochentag // Bits 45..49: Monat (BCD) // Bits 50..57: Jahr (BCD) // Bit 58 [P3]: Datumsparität // [Bit 59: Schaltsekundenbit (immer 0)] /**************************************************************/ // #define DEBUG // Debug Modus // Der Debug Modus dient zum Abgleich der Pausenlängen (PAUSE_xxxMS). // Das LCD zeigt die vom Decoder erkannten Pausenlängen an. Wenn es // eine deutliche Abweichung gibt, können die Pausenlängen angepaßt // werden. // #define REPARATUR // Reparatur Modus // Im Reparatur Modus wird in dieser Programm Version nur eine Er- // kennung von Spikes ermöglicht. Damit sinkt die Störanfälligkeit. // In weiteren Programmversionen kann hier ggf. noch eine "echte" // Reparatur von fehlerhaften DCF Telegrammen erfolgen. // #define WETTER // Wetter Infos decodieren // Wenn man die in den DCF Bits 1..14 enthaltenen Wetter Informationen // einsehen möchte, muss man das Programm mit definiertem "WETTER" // kompilieren. Da die Infos verschlüsselt sind, wird man in der Regel // diese Bits nicht sinnvoll verwenden können. #define UHRABGLEICH 100 // Uhr Abgleich (100 x 10ms = 1s) // Mit "UHRABGLEICH" kann man die Ganggenauigkeit der Software-Uhr beein- // flussen. #define PAUSE_800MS 80 // Bit 1 Pausenlänge #define PAUSE_900MS 90 // Bit 0 Pausenlänge #define PAUSE_1800MS 180 // Letztes Bit 1 Pausenlänge #define PAUSE_1900MS 190 // Letztes Bit 0 Pausenlänge #define PAUSE_ABWEICHUNG 5 // Pausenlänge Abweichung // Das DCF77 Telegramm wird in einer ganzen Minute für die Folgeminute // übertragen. In jeder Sekunde wird ein DCF Bit codiert. Senderseitig // wird dazu die Sendeleistung 100ms lang für ein 0-Bit oder 200ms lang // für ein 1-Bit auf 25% abgesenkt. Danach ist für den Rest der Sekunde // (900ms bzw. 800ms) Pause, also 100% Sendeleistung. Für einen DCF De- // coder ist das Ende des Telegramms dadurch erkennbar, dass das letzte // Bit (DCF Bit 58) eine Pause von 1900ms bzw. 1800ms besitzt. Damit // können die o.g. 4 Pausendauern (PAUSE_XXXMS) unterschieden werden. // Da der DCF Decoder alle 10ms aufgerufen wird, wird er etwa 80-mal den // selben Pegel am Eingang feststellen, wenn die Pause nach einem 1-Bit // gesendet wird. // Durch "PAUSE_ABWEICHUNG" wird festgelegt, welche Abweichung vom Soll // zugelassen wird. Beim Wert 5 erkennt der Decoder ein 1-Bit, wenn er // zwischen 75- und 84-mal (= 750..840ms) den selben Pegel feststellt. #define VALIDITAETSSTANDARD 1 // Validitätszähler Grenze // (1: Jedes DCF Telegramm nutzen!) // Als INTAKT gilt ein Telegramm, wenn folgende Bedingungen erfüllt sind: // 1. DCF Bit 0 ist 0 // 2. DCF Bits 17 und 18 sind ungleich // 3. DCF Bit 20 ist 1 // 4. Die Paritätsbits 28, 35, 58 enthalten eine korrekte gerade Parität // 5. Es wurden genau 58 DCF Bits decodiert // 6. Fall Schaltsekunde: DCF Bit 59 ist 0 und DCF Bit 19 ist 1 // Nicht PLAUSIBEL ist ein Telegramm, wenn Werte außerhalb des möglichen // Bereichs liegen. Ein Wert von 9 für den Wochentag ist z.B. nicht // plausibel. Allgemeiner könnte man sagen, dass ein DCF Telegramm nicht // plausibel ist, wenn es nicht die Folgeminute der aktuellen Minute ab- // bildet. // Ein Telegramm ist VALIDE (= gültig), wenn es intakt UND plausibel ist. // Jedes valide DCF Telegramm wird gezählt. Ist VALIDITAETSSTANDARD 1, // dann wird jedes valide Telegramm zum Stellen der Uhr verwendet. Man // kann den Wert erhöhen, wenn man ein Stellen der Uhr nur bei sehr guten // Empfangsbedingungen erlauben will. Setzt man VALIDITAETSSTANDARD z.B. // auf 3, dann wird ein Telegramm nur dann zum Stellen der Uhr verwendet, // wenn es das dritte valide Telegramm in Folge ist. /******************************************************************************/ // Variablen: byte Jahr; // Jahr [0..99] byte Monat; // Monat [1..12] byte Wochentag; // Wochentag [1..7 = MO..SO] byte Tag; // Tag [1..31] byte Sommerzeit; // Zeitzone [0 / 1 = MEZ / MESZ] byte Stunde; // Stunde [0..23] byte Minute; // Minute [0..59] byte Sekunde; // Sekunde [0..59] #ifdef WETTER unsigned int Wetter; // Codierte Wetter Informationen #endif // (DCF Bits 1..14; Bit 0 immer 0) byte dcfflags; // DCF Flags (DCF Bits 15..20): #define FLAG_R 1 // R: Ruf Bit 15 für PTB Angestellte #define FLAG_A1 2 // A1: Ankündigung eines Zeitzonenwechsels #define FLAG_Z1 4 // Z1: Zeitzone 1 [0 = MEZ, 1 = MESZ] #define FLAG_Z2 8 // Z2: Zeitzone 2 [1 = MEZ, 0 = MESZ] #define FLAG_A2 16 // A2: Ankündigung einer Schaltsekunde #define FLAG_S 32 // S: Start Bit 20 (immer 1) byte dcfstatus; // Status Flags (Bits 0..5 nur lesen!): #define STATUS_FEHLER 1 // Telegramm Fehler #define STATUS_MINPARITAET 2 // Minutenparität ok #define STATUS_STDPARITAET 4 // Stundenparität ok #define STATUS_DATPARITAET 8 // Datumsparität ok #define STATUS_DCFBIT58 16 // 58 (oder 59) DCF Bits decodiert #define STATUS_TELEGRAMMINTAKT 32 // Telegramm intakt #define STATUS_UHRGESTELLT 64 // Uhr einmal gestellt #define STATUS_DCF_AN 128 // DCF77 Decoder AN byte validitaetszaehler; // Zähler für intakte und // plausible DCF Telegramme byte validitaetsgrenze; // Grenze Validitäts Zähler #ifdef DEBUG byte pause_1_laenge; byte pause_0_laenge; byte letztepause_1_laenge; byte letztepause_0_laenge; #endif /******************************************************************************/ // Funktionen: /** * INIT DCF * * Unbedingt einmal aufrufen, bevor die DCF77 Funktion benutzt wird! * */ void initDCF(void) { Port_DataDirBit(DCF_IN, 0); // Port = Eingang Port_WriteBit(DCF_IN, 1); // Pullup Widerstand ein validitaetszaehler = 0; // Validitätszähler zurücksetzen validitaetsgrenze = VALIDITAETSSTANDARD; // Grenze setzen dcfstatus = STATUS_DCF_AN; // DCF77 Decoder AN } /** * DCF DECODER AN * * Der DCF77 Decoder wird eingeschaltet. * Immer wenn ein intaktes DCF Telegramm decodiert wurde, kann die * Uhr mit den aktuellen DCF Informationen gestellt werden. * */ void DCFon(void) { dcfstatus = dcfstatus | STATUS_DCF_AN; // Status Bit 7 setzen } /** * DCF DECODER AUS * * Der DCF77 Decoder wird ausgeschaltet. * Die Uhr wird durch die interne Referenz (Timer) betrieben. * */ void DCFoff(void) { // Alle Status Bits löschen, nur Status Bit 6 bleibt unverändert: dcfstatus = dcfstatus & STATUS_UHRGESTELLT; } /** * BCD to DEC * * Diese Funktion wandelt einen BCD- in einen Dezimalwert um. * */ byte BCDtoDEC(byte bcd) { return ((bcd >> 4) * 10 + (bcd & 0x0f)); }
P.S.: Teil 2 der Bibliothek folgt!
Lesezeichen