Hallo Besitzer der Zusatzplatine RP6 CCPRO M128,

die mitgelieferte Library DCF_Lib.cc hat gerade so die basalen Funktionen eines DCF-Decoders. Mit dieser CCPRO BASIC Bibliothek RP6DCFCCLib.cbas wird das besser. Viel Spaß damit.

Demo (DCF_RTC.cbas):
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.cbas geändert werden.
 * erforderliche Library: IntFunc_Lib.cc und neue RP6DCFCClib.cbas (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.cbas"

' Die neue RP6DCFCCLib einbinden:
#include "../../RP6CCLib/RP6DCFCClib.cbas"

Dim irqcnt As Integer                      ' globale Variablendeklaration
Dim cnt1, alte_sekunde As Byte

Sub main()
    ' 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
    Do While True                           ' Endlosschleife
        If cnt1 = 50 Then
            Port_WriteBit(PORT_LED1, PORT_OFF) ' LED1 aus
        End If

        If cnt1 = 100 Then                     ' Sekundentakt
            Port_WriteBit(PORT_LED1, PORT_ON)  ' LED1 an
            cnt1 = 0
        End If
		If alte_sekunde <> Sekunde Then
			alte_sekunde = Sekunde
#ifndef DEBUG
            showCLOCK()
'            showSTATUS()
#endif
#ifdef DEBUG
            showDEBUGINFO()
#endif
        End If
    End While
End Sub

' -----------------------------------------------------------------------------
' Festlegung von Startzeit und Startdatum
'
Sub Time_Init()
    Sekunde = 0                             ' Uhr Startzeit:   12:00:00
    Minute = 0
    Stunde = 12
    Wochentag = 7
    Tag = 31                                ' Uhr Startdatum:  31.05.2009
    Monat = 5
    Jahr = 9
End Sub

' -----------------------------------------------------------------------------
' Interrupt Routine
'
Sub INT_10ms()
    cnt1 = cnt1 + 1                         ' Zähler für Blinken der LED1

    decodeDCF()                             ' DCF77 Decoder

    irqcnt = Irq_GetCount(INT_TIM2COMP)     ' Interrupt Request Counter
End Sub

' -----------------------------------------------------------------------------
Bibliothek (RP6DCFCClib.cbas), Teil 1:
Code:
/* ****************************************************************************
 *                           _______________________
 *                           \| RP6  ROBOT SYSTEM |/
 *                            \_-_-_-_-_-_-_-_-_-_/              >>> CCPRO M128
 * ----------------------------------------------------------------------------
 * ----------------------- [c]2009 - Dirk -------------------------------------
 * ****************************************************************************
 * File: RP6DCFCClib.cbas
 * Version: 1.0 - CCPRO BASIC
 * 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:

Dim Jahr As Byte                        ' Jahr      [0..99]
Dim Monat As Byte                       ' Monat     [1..12]
Dim Wochentag As Byte                   ' Wochentag [1..7 = MO..SO]
Dim Tag As Byte                         ' Tag       [1..31]
Dim Sommerzeit As Byte                  ' Zeitzone  [0 / 1 = MEZ / MESZ]
Dim Stunde As Byte                      ' Stunde    [0..23]
Dim Minute As Byte                      ' Minute    [0..59]
Dim Sekunde As Byte                     ' Sekunde   [0..59]

#ifdef WETTER
Dim Wetter As Word              		' Codierte Wetter Informationen
#endif                                  ' (DCF Bits 1..14; Bit 0 immer 0)

Dim dcfflags As Byte                ' 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)

Dim dcfstatus As Byte               ' 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

Dim validitaetszaehler As Byte			' Zähler für intakte und
										' plausible DCF Telegramme
Dim validitaetsgrenze As Byte			' Grenze Validitäts Zähler

#ifdef DEBUG
Dim pause_1_laenge As Byte
Dim pause_0_laenge As Byte
Dim letztepause_1_laenge As Byte
Dim letztepause_0_laenge As Byte
#endif

/******************************************************************************/
' Funktionen:

/**
 * INIT DCF
 *
 * Unbedingt einmal aufrufen, bevor die DCF77 Funktion benutzt wird!
 *
 */
Sub initDCF()
    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
End Sub

/**
 * 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.
 *
 */
Sub DCFon()
    dcfstatus = dcfstatus Or STATUS_DCF_AN        ' Status Bit 7 setzen
End Sub

/**
 * DCF DECODER AUS
 *
 * Der DCF77 Decoder wird ausgeschaltet.
 * Die Uhr wird durch die interne Referenz (Timer) betrieben.
 *
 */
Sub DCFoff()
    ' Alle Status Bits löschen, nur Status Bit 6 bleibt unverändert:
    dcfstatus = dcfstatus And STATUS_UHRGESTELLT
End Sub

/**
 * BCD to DEC
 *
 * Diese Funktion wandelt einen BCD- in einen Dezimalwert um.
 *
 */
Sub BCDtoDEC(bcd As Byte) As Byte
    Return (bcd >> 4) * 10 + (bcd And 0x0f)
End Sub
Gruß Dirk

P.S.: Teil 2 der Bibliothek folgt!