Das Zeitsignal der physikalisch-technischen Bundesanstalt in Braunschweig wird gerne für das Stellen des RTC verwendet. Die Funktionsweise der Amplitudenmodulation und den Aufbau der DCF77-Kodierung finden sie im Kapitel 12 [2].
Um das DCF77-Signal auswerten zu können, muss das Verhältnis ti/T ermittelt werden. Ist das Verhältnis 1/10, ist eine „0“ kodiert, bei 2/10 eine „1“. Abbildung 47 enthält einen Ausschnitt des DCF77-Signals. Mit dem Beginn jeder Sekunde mit Ausnahme der 59sten, wird eine „0“, bzw. eine „1“ gesendet. Somit ist zu erkennen, wann die nächste Minute anfängt.
|
|
Abbildung 47 Ausschnitt aus dem DCF77-Signal
Je nach verwendetem DCF77-Empfänger weicht das Verhältnis von ti/T um einige % ab (siehe Abbildung 48 und Abbildung 49).
|
|
Abbildung 48 Empfang des Wertes „0“
|
|
Abbildung 49 Empfang des Wertes „1“
Erstellen sie ein Programm, das die Breite des LOW-Pulses auswertet. Wird eine „0“ erkannt, wird die LED an P2.0, bei einer „1“ die LED an P2.1 eingeschaltet. Liegt die Zeit außerhalb des erlaubten Bereiches von +- 10 %, so sollen die LEDs P2.4–P2.7 eingeschaltet werden. Um die Zeit messen zu können, wird der Timer 0 mit einem Reloadwert von 10 ms geladen (siehe Listing 53, ) und bei fallender Flanke gestartet (siehe ‚). Alle 10 ms (siehe ƒ) wird die Variable „ucTime“ inkrementiert und der Zustand des Portpins P2.3 gewechselt (siehe „). Wechselt der Zustand des DCF77-Signals von „0“ -> „1“, wird der Timer 0 gestoppt (siehe …) und „ucTime“ wird ausgewertet (siehe †). Danach wird der Reloadwert gesetzt (siehe ‡) und auf die nächste fallende Flanke gewartet (siehe ˆ).
|
Projektname |
Verzeichnis |
Verwendete Sourcemodule |
|
DCF77_Tick |
Test_DCF77_Tick |
TestDCF77.c, PortConfig.c |
Tabelle 57 Projekt DCF77_Tick
|
‚
…
†
‡
ˆ
ƒ „ |
#include <REG932.H> #include <PortConfig.h>
sbit sbDCF77 = P0^0; sbit sb10msec = P2^3; unsigned char ucTime;
void main(void) { v_PortConfig(Port2, AllPins, BiDir); P2 = 0xFF;
TMOD = 0x01; // Timer 0, Betriebsart 1 TL0 = 0xDD; // fuer 10 msec initialisieren TH0 = 0x6F; TF0 = 0; // Timer 0 Flag zuruecksetzen
ET0 = 1; // Interrupt fuer Timer 1 freigeben EA = 1;
// Warten bis fallende Flanke gefunden while (sbDCF77 == 0); while (sbDCF77 == 1);
while (1) { TR0 = 1; // Timer 1 starten ucTime = 0; while (sbDCF77 == 0); TR0 = 0; // Timer 1 stoppen
if (ucTime >= 10 & ucTime <= 11) P2 = 0x01; else if (ucTime > 20 & ucTime <= 21) P2 = 0x02; else P2 = 0xF0;
// Timerwert auf Reloadwert setzen TL0 = 0xDD; TH0 = 0x6F;
while (sbDCF77 == 1); // Warten auf fallende Flanke } }
void v_Timer0Int(void) interrupt 1 using 1 { TL0 = 0xDD; TH0 = 0x6F; ucTime++; sb10msec = !sb10msec; } |
Listing 53 Inhalt von TestDCF77.c
Um eine volle Minute aufzeichnen und auswerten zu können, muss zuerst die 59ste Sekunde gefunden werden. Erstellen sie ein Programm, das diese Sekunde findet und bei der fallenden Flanke von der nächsten Sekunde stoppt.
Die Initialisierung des Timers ist zur besseren Lesbarkeit in eine eigene Unterfunktion ausgelagert worden (siehe Listing 54, ). Für die Konfiguration von Port 2 wurde die Libraryfunktion „v_PortConfig()„ aus Kapitel 0 verwendet (siehe ‚). Im Gegensatz zum vorangegangenen Beispiel wird auf die steigende Flanke des DCF77-Signals gewartet (siehe ƒ). Ist sie gefunden, wird die Zeitmessung gestartet (siehe „). Es wird jetzt so lange gewartet, bis eine fallende Flanke erkannt wird (siehe …). Ist die gemessene Zeit größer 1,8 s (siehe †), ist die 59ste gefunden worden.
|
Projektname |
Verzeichnis |
Verwendete Sourcemodule |
|
DCF77_59sec |
Test_DCF77_59sec |
FindDCF77_59sec.c |
Tabelle 58 Projekt DCF77_59sec
|
‚
ƒ „
…
† |
#include <REG932.H> #include <PortConfig.H>
sbit sbDCF77 = P0^0; sbit sb10msec = P2^3; unsigned char ucTime;
void v_InitTimer10msec(void) { // Timer 0 für 10 msec initialisieren TMOD = 0x01; TL0 = 0xDD; TH0 = 0x6F; TF0 = 0; ET0 = 1; EA = 1; }
void main(void) { unsigned char Low, High; v_PortConfig(Port2, AllPins, BiDir); // P2 als Quasi-bidir. v_InitTimer10msec();
while (sbDCF77 == 1); // Warten bis fallende Flanke gefunden while (sbDCF77 == 0); // Warten bis steigende Flanke gefunden TR0 = 1; // Timer 0 starten
while (1) { ucTime = 0; while (sbDCF77 == 1);
if (ucTime >= 180) { TR0 = 0; // Timer 0 stoppen } while (sbDCF77 == 0); TL0 = 0xDD; TH0 = 0x6F; } }
void v_Timer0Int(void) interrupt 1 using 1 { TL0 = 0xDD; TH0 = 0x6F; ucTime++; sb10msec = !sb10msec; } |
Listing 54 Inhalt von FindDCF77_59sec.c
|
|
Abbildung 50 DCF77-Lücke bei der 59sec
Meist sehen die DCF77-Signale aber nicht so sauber aus, wie bisher dargestellt. Leichte Änderungen des Ferritkerns zur Senderichtung oder ein störendes Umfeld, z. B. durch Radiosender ergeben folgendes DCF77-Signalbild für die Auswertung:
|
|
Abbildung 51 DCF77 gestörter Empfang
Um eine Spikeunterdrückung durchzuführen, startet der Flankenwechsel des DCF77-Signals den zweiten Timer. Ist diese Zeit abgelaufen und kein erneuter Flankenwechsel aufgetreten, wird der Flankenwechsel an Portpin 2.3 ausgegeben. Abbildung 52 enthält eine Filterfunktion mit einem Timer1 Intervall von 5 ms.
|
|
Abbildung 52 DCF77 gestörter Empfang (P0.0), Filter 5ms (P2.3)
Um den Softwareaufbau und die Funktionsweise der Spikeunterdrückung nachvollziehen zu können, erstellen sie das Projekt aus Tabelle 59. Mit Hilfe des Makros „#define FILTER“ (siehe Listing 55, ) wird die Zeit für den Timer 1 definiert.
F !! Aufbau und Funktionsweise des Makros #define können sie im Kapitel 5 [1], in der Rubrik Makro Definitionen nachlesen. !!
Am Anfang des Programms wird der Timer 1 initialisiert (siehe ‚). Die Initialisierung selbst ist in Funktionen ausgelagert worden (siehe ƒ). Das Programm wartet so lange, bis eine fallende Flanke gefunden wurde (siehe „). Es wird nun die Spikeunterdrückung gestartet (siehe …). Ist die Zeit des Timer 1 abgelaufen und es hat kein weiterer Flankenwechsel am DCF77-Signal stattgefunden, wird der aktuelle Zustand des DCF77-Signals an P2.3 ausgegeben (siehe †). Der Timer 1 wird zudem gestoppt. Erfolgt ein Flankenwechsel während der Timer 1 läuft, wird der Timer 1 erneut aufgesetzt. Somit wird erreicht, das kurzzeitige Spikes kleiner der Timer 1 Zeit unterdrückt werden.
|
Projektname |
Verzeichnis |
Verwendete Sourcemodule |
|
DCF77_DetectSpike |
Test_DCF77_DetectSpike |
DetectSpike.c |
|
|
..\Library |
PortConfig.c |
Tabelle 59 Projekt DCF77_ DetectSpike
|
ƒ
‚
„ …
‡
‡
† |
#include <REG932.H> #include <PortConfig.H>
sbit sbDCF77 = P0^0; sbit sbCleanDCF77 = P2^3;
unsigned char ucTime; // Reload value 1ms (RC-Oscillator) = 0xE6A #define FILTER 0x10000 - (5 * 0xE6A)
void v_InitTimer1(void) { // Timer 1 für initialisieren TMOD = TMOD | 0x10; TL1 = (unsigned char) FILTER; TH1 = FILTER / 256; TF1 = 0; ET1 = 1; EA = 1; }
void v_StartFilter(void) { TH1 = FILTER / 256; TL1 = (unsigned char) FILTER; TR1 = 1; // Timer 1 starten }
void main(void) { // unsigned char Low, High; v_PortConfig(Port2, AllPins, BiDir); // P2 als Quasi-bidir. v_InitTimer1();
while (sbDCF77 == 1); // Warten bis fallende Flanke gefunden v_StartFilter();
while (1) { while (sbDCF77 == 1); v_StartFilter();
while (sbDCF77 == 0); v_StartFilter(); } }
void v_Timer1Int(void) interrupt 3 using 1 { sbCleanDCF77 = sbDCF77; TR1 = 0; // Timer 1 stoppen } |
Listing 55 Inhalt DetectSpike.c
Dieser Filtermechanismus erkennt allerdings nicht, wenn die Spikes > 5 ms sind. In diesem Fall entsteht ein Signalwechsel mit einer Zeitbreite >= 5 ms (siehe Abbildung 53). Um diese kurzzeitigen Wechsel unterdrücken zu können, muss die Startzeit des letzten Flankenwechsels abgespeichert werden.
|
|
Abbildung 53 DCF77 gestörter Empfang (P0.0), Filter 5ms (P2.3)