DCF77 Auswertung in C

Aus PIC-Projekte
Wechseln zu: Navigation, Suche

Inhaltsverzeichnis

Vorwort

Ich möchte hier meine DCF77 Routinen zur Verfügung stellen bzw. anhand des Codes erklären wie Ihr das DCF77 Signal empfangen und auswerten könnt. Der Code ist eigentlich eine erste Version und sicherlich nicht perfekt aber er funktioniert bei mir seid langem ohne Probleme. Die Routine hat bisher nicht einmal einen Fehler gemacht, sprich ist der Empfang mit Störung behaftet hat meine Routine das auch gemerkt und quittiert.


Allgemein zum DC77 Signal

Das DCF77 ist ein Zeitsignal, welches auf einer Trägerfrequenz von 77,5 kHz von Frankfurt/Main bzw. Mainflingen aus übertragen wird. Das Signal ermöglicht eine hochpräzise Synchronisation. Somit steht immer die aktuelle Uhrzeit, sowie das Datum inklusive Wochentag zur Verfügung. Für nicht einmal 5€ kann man sich beim Online-Versandhändler Pollin ein Empfangsmodul kaufen, welches direkt das DCF77 Signal ausgibt.


Ambox notice.png DCF1 Modul von Pollin
Der Hier zur Verfügung gestellte Code arbeitet bei mir mit dem DCF1 Modul (siehe Link oben) von Pollin zusammen. Die Routinen sollten aber theoretisch auch mit den Modulen von Conrad und/oder Reichelt arbeiten können. Eventuell muss ein negiertes Ausgangssignal berücksichtigt werden.


Anschluss des Moduls

Das DCF Modul von Pollin kann man ohne weiteres direkt an einen IO des PIC anschließen. In meiner Beschaltung habe ich ein Spannungsstabilisator mit einer Ausgangsspannung von 3,3 Volt als Spannungsversorgung gewählt, da das Modul aber recht empfindlich gegen Störungen auf der Versorgungsspannung ist, wäre es wohl optimal die Spannung durch eine Knopfzelle mit entsprechender Halterung bereit zu stellen.


Anschlussprinzip

     1,2V - 3,3V
          o
          |
VCC  o----+
DATA o--------> Interrupt-on-change(!) Pin
GND  o----+
PON  o----+
          |
         ===

Wahlweise kann PON noch auf einen I/O des PIC geführt werden um das Modul abzuschalten, somit lässt sich, bei Versorgung durch eine Knopfzelle, die Lebensdauer der Batterie verlängern.


Das Signal

DCF77 Signalfolgen
Das Signal sendet eine komplette Zeitinformation, dieser Vorgang dauert genau 60 Sekunden bzw. 1 Minute. Dabei unterscheidet man zwischen zwei Signalzuständen, welche sich in der Impulslänge wieder spiegeln. Das DCF Modul sendet über 1 Minute lang 59 (Bit 0-58) Impulse aus.

Wie man unschwer feststellen kann, sind die Impulse von Unterschiedlicher Länge somit lässt sich identifizieren ob es sich gerade um eine logische 1 oder um eine 0 Information handelt. Eine 1 hat eine Impulslänge von 200ms hingegen eine 0 eine Länge von 100ms. Wie ich oben schon erwähnt habe überträgt das Modul pro Zeitinformation (Dauer der Übertragung genau 60 Sekunden) 59 Impulse (Bit 0 bis Bit 58) bzw. Bits - pro Sekunde wird ein Bit/Impuls gesendet. Dann müssten es doch aber eigentlich 60 Bits sein oder? --> Eigentlich ja aber das würde nicht funktionieren, da man bei 60 Bits nicht erkennen könnte wann eine neue Zeitinformation beginnt. Daher werden 59 Bits gesendet. Das fehlende 60. Bit signalisiert a) den Beginn einer neuen Zeitinformation und b) den Start der nächsten Minute zur nächsten Flanke und somit die Gültigkeit der zuvor erhaltenden Zeitinformation.


Ambox notice.png Gültigkeit immer für die Folgeminute
Eine übertragende Zeitinformation ist immer die gültige Zeit für die darauf folgende Minute. Also die Zeit die im Augenblick übertragen wird ist 1. Minute voraus. So kann man die empfange Information empfangen, verarbeiten und zum Beginn der nächsten Minute z.B. auf einem Display ausgeben.


Die einzelnen Bits

Nachfolgend eine Tabelle mit der aufgeschlüsselten Zeitinformation:

Sekunde Bedeutung
0 Minutenbeginn --> immer '0'
1-14 Wetterdaten(verschlüsselt)
15 Reserveantenne aktiv
16 Umstellung zwischen Sommer- bzw. Winterzeit
17 Sommerzeit
18 Winterzeit
19 Schaltsekunde
20 Zeitbeginn
21-27 Minute 1, 2, 4, 8, 10, 20, 40
28 Prüfbit Minute
29-34 Stunde 1, 2, 4, 8, 10, 20
35 Prüfbit Stunde
36-41 Tag 1, 2, 4, 8, 10, 20
42-44 Wochentag 1, 2, 4
45-49 Monat 1, 2, 4, 8, 10
50-57 Jahr 1, 2, 4, 8, 10, 20, 40, 80
58 Prüfbit Datum (36. - 57.)
59 wird nicht gesendet (siehe oben)


Prüfbits

Die Prüfbits müssen immer dann "1" sein, wenn die Anzahl der gesetzten Bits ungerade war! Wenn z.B. Bit 29, 30 und 33 gesetzt sind (3 Stück), dann muss Bit 35 eine "1" enthalten. Wenn das nicht der Fall ist gab es einen Übertragungsfehler und die Daten sind unbrauchbar.

Programm

Jetzt kommen wir zum Programm bzw. zum Vorgehen um das Signal zu empfangen und auszuwerten. Hier ein Programmablaufplan:

DCF77 PAP 2.png


Programmcode in C

Achtung PP.gif Decodierung Verwendung des Timer1
Meine DCF77 Routinen arbeiten mit dem Timer1. Der Timer1 muss mit einem 32,768 kHz Uhrenquarz betrieben werden, damit die Routinen vernünftig arbeiten. Eine Möglichkeit ohne Uhrenquarz gibt es auch bedarf aber einiger Anpassung, da der Uhrenquarz das Erfassen/Messen der Impulse enorm vereinfacht!


Anschlussschema

Link zum Quarz • Link zu den Kondensatoren

                 C
T1OSI o----+-----||--+
           |         |
        [Quarz]      |  
           |     C   |
T1OSO o----+-----||--+
                     |
                    ===


DCF77 Routine

Nachfolgend die Routine, welche das DCF77 Signal empfängt, prüft und auswertet. Das Programm ist ziemlich stark/gut kommentiert und bedarf eigentlich keiner weiteren Erklärung:


Datei: DCF.c

/***********************************************************************************************
Autor:				Nicolas Meyertöns 
Version:			1.0
Zugehörige Dateien:		DCF.c , DCF.h , ISR.c , ISR.h , main.c
 
Datei Beschreibung:		DCF.c - Diese Datei enthällt die Funktion zum Empfang des DCF77 
				Signals sowie die Auswertung des selbigen. Das Ergebnis steht in
				den Variablen: Sekunde, Minute, Stunde, Tag, Monat, Jahr, Wochentag
/**********************************************************************************************/
//Includedateien einbinden
 
#include 	<p18cxxx.h>					
#include 	"delays.h"
#include	"DCF.h"
#include 	"ISR.h"				
 
/**********************************************************************************************/
 
unsigned char DCF77 (void)
{
	//Die Variablen, welche lediglich innerhalb dieser Funktion verwendet werden
	unsigned char Startbit=0;	
	unsigned char Fertig=0;
	unsigned char i=0;
	unsigned char Paritaet=0;
	unsigned char Einer;
	unsigned char Zehner;
 
	//Hier wird die Variable DCF_Versuche imkrementiert
	DCF_Versuche++;
 
	//Wenn dies bereits der 30. Versuch ist das DCF77 Signal zu empfangen, dann wird
	//die Syncronisation abgebrochen und die "2" als Rückgabewert gesetzt!
	if(DCF_Versuche>=30)return(2);
 
/**********************************************************************************************/
	//Alle* Interrupts werden verboten, damit die DCF Routine nicht gestört wird
 
 
 
 
	//* Ihr müsst hier alle Interrupts verbieten, welche Ihr in eurem Prog verwendet!
/**********************************************************************************************/	
 
	//WICHTIG: DER TIMER MUSS MIT EINEM UHRENQUARZ BETRIEBEN WERDEN!!	
 
	T1CONbits.TMR1ON=0;			//Timer1 abschalten
	TMR1H=TMR1L=0;				//TMR1 Zählregister löschen
	T1CON=0x1E;				//Timer1 Einstellungen
	IPR1bits.TMR1IP=1;			//Timer1 Interrupt ist "high priotity"
	INTCONbits.RBIE=0;			//
 
 
/*	Je nach DCF Empfang muss eine gewisse Zeit gewartet werden, bevor sich das DCF Modul von 
	Pollin eingeschwungen hat.*/
 
	Delay10KTCYx(255); Delay10KTCYx(255);
	Delay10KTCYx(255); Delay10KTCYx(255);
 
/***********************************************************************************************
Das fehlende Bit erkennen (Start)								
***********************************************************************************************/
 
/* 	Erläuterung des Abshnittes:
 
	In diesem Abschnitt wird gewartet bis eine neue Zeitinformation beginnt und das geschieht
	folgendermaßen: Durch das fehlende 60. Bit (bzw. 59. Bit wenn man von 0 an zählt) entshet
	zum Beginn einer neuen Zeitinformation eine Phase in der das DCF-Signal lange den Zustand
	low einnimt. Hier wird also die Länge der LOW Zustände gemessen. Wird ein gewisser Wert
	überschritten, weiß der PIC, dass der nächste Impuls bereits die erste Information ist. */
 
	while(Startbit==0)
	{
		if (DCF==0)
		{	
			T1CONbits.TMR1ON=1;
			while(DCF==0);
			T1CONbits.TMR1ON=0;
		}	
 
		if (TMR1H>0x70) 
		{
			Startbit=1;
		}
 
		else
		{
			TMR1H=TMR1L=0;
		}
	}
 
	T1CON=0x0E;	// Timer1 Einstellungen
 
//Erkennung abgeschlossen	
/**********************************************************************************************/
 
//Jetzt kommen die Einstellungen für Interrupt on change - Priorität=low
	INTCON2bits.RBIP=0;
 
 
/***********************************************************************************************
Der Interrupt on change wird nun aktiviert und der Empfang des DCF77 Signals beginnt							
***********************************************************************************************/
 
/* 	Erläuterung des Abshnittes:
 
	Durch eine ansteigende Flanke auf dem DCF Signal wird ein Interrupt ausgelöst, welcher den
	Timer1 solange zählen lässt, bis das DCF-Signal wieder auf low zurück geht. Anschließend
	wird das Erkennungs-Flag DCF_F gesetzt und wieder zurück gesprungen (hier her). Jetzt sieht
	diese Funktion, dass ein Impuls gemessen wurde (durch das laufen des Timer1) und wertet aus
	ob es eine 1 oder 0 war (je nach Impulslänge). Wenn es weder 1 noch 0 war, war es ein Fehler
	und die Routine wird abgebrochen. Nach 59 empfangenen Bits (i) wird das Flag "Fertig" 
	gesetzt und der PIC springt aus der while(Fertig==0) Schleife heraus. */
 
	while(Fertig==0)
	{
		INTCONbits.RBIE=1;			//Interrupt erlauben
 
		if(DCF_F==1)				//DCF_F==1==Flanke am DCF Data Signal erkannt
		{
			if(TMR1H>0x16) 			//Wenn der Impuls länger war als ~190ms
			{
				DCF_Data[i]=1;		//Dann: War es eine 1 (High)
				i++;			//i inkrementieren (1 Speicherplatz vorwärts im Array)
				DCF_F=0;		//muss wieder gelöscht werden (warten auf nächste Flanke)
			}	
 
			else
			{
				if(TMR1H>0x0A)		//Sonst: Wenn der Impuls länger war als ~90ms
				{
					DCF_Data[i]=0;	//Sonst: Dann war es eine 0 (Low)
					i++;		//i inkrementieren (1 Speicherplatz vorwärts im Array)
					DCF_F=0;	//muss wieder gelöscht werden (warten auf nächste Flanke)
				}
			}
 
			if(TMR1H<0x0A)			//Wenn der Impuls kürzer war als ~90ms
			{
				INTCONbits.RBIE=0;	//Interrupt verbieten
				i=DCF_F=0;
				return(0);		//Dann war es ein Fehler und wird mit "0" quittiert
			}	
		}
 
		if(i==59)				//Wenn i=59 bzw. wenn 59 Bits empfangen wurden
		{
			Fertig=1;			//Dann wurden alle Daten empfangen
		}
	}
 
/***********************************************************************************************
Der Interrupt on change wird jetzt wieder verboten, da alle Daten empfangen wurden
***********************************************************************************************/
 
INTCONbits.RBIE=0;			//Interrupt verbieten
 
/***********************************************************************************************
Die Parität der Minuten wird geprüft
***********************************************************************************************/
 
	Paritaet=(DCF_Data[21]+DCF_Data[22]+DCF_Data[23]+DCF_Data[24]+DCF_Data[25]+DCF_Data[26]+DCF_Data[27]);	
 
	i=Paritaet%2;	//Durch 2 Teilen -> Rest in i
 
	//Wenn in "i" eine Zahl steht war die Summe ungerade und das Prüfbit muss auch "1" sein, 
	//wenn nicht, dann wird beendet und mit "0" quitiert. Oder: Wenn in "i" null steht, dann 
	//muss das Prüfbit 0 sein, wenn nicht, dann wird ebenfalls beendet und mit 0 quitiert!
 
	if( ((i==1) && (DCF_Data[28]==0)) || ((i==0) && (DCF_Data[28]==1)) )return(0);
 
 
/***********************************************************************************************
Die Parität der Stunden wird geprüft
***********************************************************************************************/
 
	Paritaet=(DCF_Data[29]+DCF_Data[30]+DCF_Data[31]+DCF_Data[32]+DCF_Data[33]+DCF_Data[34]);
 
	i=Paritaet%2;	//Durch 2 Teilen -> Rest in i
 
	//Wenn in "i" eine Zahl steht war die Summe ungerade und das Prüfbit muss auch "1" sein, 
	//wenn nicht, dann wird beendet und mit "0" quitiert. Oder: Wenn in "i" null steht, dann 
	//muss das Prüfbit 0 sein, wenn nicht, dann wird ebenfalls beendet und mit 0 quitiert!
 
	if( ((i==1) && (DCF_Data[35]==0)) || ((i==0) && (DCF_Data[35]==1)) )return(0);
 
/***********************************************************************************************
Die Parität des Datums wird geprüft
***********************************************************************************************/
 
	Paritaet=	(DCF_Data[36]+DCF_Data[37]+DCF_Data[38]+DCF_Data[39]+DCF_Data[40]+DCF_Data[41]+
			 DCF_Data[42]+DCF_Data[43]+DCF_Data[44]+DCF_Data[45]+DCF_Data[46]+DCF_Data[47]+
			 DCF_Data[48]+DCF_Data[49]+DCF_Data[50]+DCF_Data[51]+DCF_Data[52]+DCF_Data[53]+
			 DCF_Data[54]+DCF_Data[55]+DCF_Data[56]+DCF_Data[57]);
 
	i=Paritaet%2;			//Durch 2 Teilen -> Rest in i
 
	//Wenn in "i" eine Zahl steht war die Summe ungerade und das Prüfbit muss auch "1" sein, 
	//wenn nicht, dann wird beendet und mit "0" quitiert. Oder: Wenn in "i" null steht, dann 
	//muss das Prüfbit 0 sein, wenn nicht, dann wird ebenfalls beendet und mit 0 quitiert!
 
	if( ((i==1) && (DCF_Data[58]==0)) || ((i==0) && (DCF_Data[58]==1)) )return(0);
 
/***********************************************************************************************
Auswertung der Minuten
***********************************************************************************************/
 
	Minute=0;					//Minuten nullen
	Minute=Minute+DCF_Data[21];			//1er hinzuaddieren
	Minute=Minute+(DCF_Data[22]*2);			//2er hinzuaddieren
	Minute=Minute+(DCF_Data[23]*4);			//4er hinzuaddieren
	Minute=Minute+(DCF_Data[24]*8);			//8er hinzuaddieren
	Minute=Minute+(DCF_Data[25]*10);		//10er hinzuaddieren
	Minute=Minute+(DCF_Data[26]*20);		//20er hinzuaddieren
	Minute=Minute+(DCF_Data[27]*40);		//40er hinzuaddieren
 
/***********************************************************************************************
Auswertung der Stunden
***********************************************************************************************/
 
	Stunde=0;					//Stunden nullen
	Stunde=Stunde+DCF_Data[29];			//1er hinzuaddieren
	Stunde=Stunde+(DCF_Data[30]*2);			//2er hinzuaddieren
	Stunde=Stunde+(DCF_Data[31]*4);			//4er hinzuaddieren
	Stunde=Stunde+(DCF_Data[32]*8);			//8er hinzuaddieren
	Stunde=Stunde+(DCF_Data[33]*10);		//10er hinzuaddieren
	Stunde=Stunde+(DCF_Data[34]*20);		//20er hinzuaddieren
 
//Sekunden zurück setzten
	Sekunde=0;	
 
/***********************************************************************************************
Auswertung des Datums
***********************************************************************************************/
 
	Tag=0;						//Tag nullen
	Tag=Tag+ DCF_Data[36];				//1er hinzuaddieren
	Tag=Tag+(DCF_Data[37]*2);			//2er hinzuaddieren
	Tag=Tag+(DCF_Data[38]*4);			//4er hinzuaddieren
	Tag=Tag+(DCF_Data[39]*8);			//8er hinzuaddieren
	Tag=Tag+(DCF_Data[40]*10);			//10er hinzuaddieren
	Tag=Tag+(DCF_Data[41]*20);			//20er hinzuaddieren
 
	Wochentag=0;					//Wochentag nullen
	Wochentag=Wochentag+ DCF_Data[42];		//1er hinzuaddieren
	Wochentag=Wochentag+(DCF_Data[43]*2);		//2er hinzuaddieren
	Wochentag=Wochentag+(DCF_Data[44]*4);		//4er hinzuaddieren	
 
	Monat=0;					//Monat nullen
	Monat=Monat+ DCF_Data[45];			//1er hinzuaddieren
	Monat=Monat+(DCF_Data[46]*2);			//2er hinzuaddieren
	Monat=Monat+(DCF_Data[47]*4);			//4er hinzuaddieren
	Monat=Monat+(DCF_Data[48]*8);			//8er hinzuaddieren
	Monat=Monat+(DCF_Data[49]*10);			//10er hinzuaddieren
 
	Jahr=2000;					//Jahr Offset*
	//*da beim Jahr nur Einer und Zehner übertragen werden!
 
	Jahr=Jahr+ DCF_Data[50];			//1er hinzuaddieren
	Jahr=Jahr+(DCF_Data[51]*2);			//2er hinzuaddieren
	Jahr=Jahr+(DCF_Data[52]*4);			//4er hinzuaddieren
	Jahr=Jahr+(DCF_Data[53]*8);			//8er hinzuaddieren
	Jahr=Jahr+(DCF_Data[54]*10);			//10er hinzuaddieren
	Jahr=Jahr+(DCF_Data[55]*20);			//20er hinzuaddieren
	Jahr=Jahr+(DCF_Data[56]*40);			//40er hinzuaddieren
	Jahr=Jahr+(DCF_Data[57]*80);			//80er hinzuaddieren
 
/***********************************************************************************************
Die Auswertung bzw. Decodierung des DCF77 Signals ist jetzt abgeschlossen. Die Informationen
stehen jetzt zur Anzeige bereit, da die Information aber erst für die darauf folgende Minute
gültig ist, wird nun auf den Start der nächsten Minute gewartet:
***********************************************************************************************/
 
	//Solange ausharren bis wieder das 1.Bit High wird,
	//dass signalisiert den Start der nächsten Minute!
	while(PORTBbits.RB5==0);
 
/**********************************************************************************************/
	return(1);					// Rückgabewert ist "1" für erfolgreicher Empfang
}


Datei: DCF.h

/***********************************************************************************************
Autor:				Nicolas Meyertöns 
Version:			1.0
Zugehörige Dateien:		DCF.c , DCF.h , ISR.c , ISR.h , main.c
 
Datei Beschreibung:		DCF.h - In dieser Datei werden Funktionen, welche in der Datei 
				DCF.c verwendet werden angemeldet, dadurch können die enthaltenen
				Funktionen von externen *.c Dateien aufgerufen werden.
/**********************************************************************************************/
 
// Durch diese Angaben wird die Datei com Compiler nur 1 mal durchlaufen
#ifndef DCF_H
#define	DCF_H
 
/************************************************************************************************
Definitionen, welche den Programmcode besser lesbar machen	
*************************************************************************************************
 
*/
#define	DCF	PORTBbits.RB5		//HIER DEN PORTPIN* EINTRAGEN AN DEM EUER DCF-DATA HÄNGT!
/*
 
************************************************************************************************
*Hinweis: Dieser I/O muss ein Interrupt on change Pin des PORTB sein! Nicht vergessen in der 
main.c das zugehörige TRIS Bit als Ausgang zu definieren!
************************************************************************************************/
 
 
 
 
/**********************************************************************************************/
//	Hier kommen die Funktionen (Unterprogramme) hinein:
/**********************************************************************************************/
 
unsigned char DCF77 (void);
 
/**********************************************************************************************/
//	Globale Variablen deklaieren(!)
/**********************************************************************************************/
 
/*Hinweis:	Das "extern" vor der Variable bedeutet, dass diese Variable bereits in einer 
		anderen *.c Datei deklariert worden ist. Dadurch weiß der Compiler diese
		Variable gibt es schon und somit kann diese in der *.c Datei, welche DIESE
		*.h Datei includiert hat, verwendet werden.*/
 
extern unsigned char DCF_F;
extern unsigned char DCF_Status;
extern unsigned char DCF_Data[60];
extern unsigned char DCF_Versuche;
extern unsigned char Sekunde;
extern unsigned char Minute;
extern unsigned char Stunde;		
extern unsigned char Tag;
extern unsigned char Monat;
extern unsigned int  Jahr;
extern unsigned char Wochentag;
 
/**********************************************************************************************/
// Und wenn sie dann deklariert sind, wird diese nicht erneut durchgeführt
 
#endif	DCF_H


Datei: ISR.c

/***********************************************************************************************
Autor:				Nicolas Meyertöns 
Version:			1.0
Zugehörige Dateien:		DCF.c , DCF.h , ISR.c , ISR.h , main.c
 
Datei Beschreibung:		ISR.c - Zeigt den Code, welche in der ISR ausgeführt werden muss,
				damit die DCF77 Routine richtig arbeitet.
/**********************************************************************************************/
 
#include 	<p18cxxx.h>		// Für die Funktionen des PIC 							
#include 	"delays.h"       	// Für Warteschleifen
#include	"main.h"		
#include	"DCF.h"  		// Für die DCF Routine	
#include 	"ISR.h"	
 
/**********************************************************************************************/
 
#pragma code _LOW_INTERRUPT_VECTOR=0x18
void interrupt_at_low_vector( void )
{
  _asm GOTO low_isr _endasm
}
 
/**********************************************************************************************/
 
#pragma code
 
#pragma interruptlow low_isr
void low_isr( void )
{
		TMR1L=TMR1H=0;		//Zählstand löschen
 
		T1CONbits.TMR1ON=1;	//Timer1 an		
		Delay10KTCYx(20);
 
		while(PORTBbits.RB5);	//Solange zählen wie DCF High Pegel hat
 
		T1CONbits.TMR1ON=0;	//Timer1 aus
		DCF_F=1;		//Erkennungsbit
		INTCONbits.RBIF=0;	//Interrupt Flag löschen
}
 
/**********************************************************************************************/


Datei: ISR.h

/***********************************************************************************************
Autor:				Nicolas Meyertöns 
Version:			1.0
Zugehörige Dateien:		DCF.c , DCF.h , ISR.c , ISR.h , main.c
 
Datei Beschreibung:		ISR.h - keine
/**********************************************************************************************/
 
// Durch diese Angaben werden die Unterprogramme nur 1mal deklariert
#ifndef ISR_H
#define	ISR_H
 
/**********************************************************************************************/
//	Hier kommen die Funktionen (Unterprogramme) hinein:
/**********************************************************************************************/
 
void low_isr( void );			// Hier steht die niedrig priorisierte ISR
 
/**********************************************************************************************/
 
// Und wenn sie dann deklariert sind, wird diese nicht erneut durchgeführt
#endif	ISR_H


Datei: main.c

/***********************************************************************************************
Autor:				Nicolas Meyertöns 
Version:			1.0
Zugehörige Dateien:		DCF.c , DCF.h , ISR.c , ISR.h , main.c
 
Datei Beschreibung:		main.c - Diese Datei ist lediglich vorhanden um zu zeigen wie man
				die DCF77 Routinen verwenden kann.
/**********************************************************************************************/
 
 
/**********************************************************************************************/
//	Einbinden von benötigten Include Dateien
/**********************************************************************************************/
 
#include 	<p18cxxx.h>		// Für die Funktionen des PIC 							
#include 	"delays.h"       	// Für Warteschleifen
#include	"main.h"		
#include	"DCF.h"  		// Für die DCF Routine	
#include	"ISR.h"		
 
/**********************************************************************************************/
//	Konfiguration für den PIC
/**********************************************************************************************/
 
//Selber einfügen
 
/**********************************************************************************************/
//	Globale Variablen definieren
/**********************************************************************************************/
 
unsigned char DCF_Versuche=0;
unsigned char DCF_F=0;
unsigned char DCF_Status=0;	//0=Fehler 1=Erfolgreich 2=Erfolglos
unsigned char DCF_Data[60];
unsigned char Sekunde=0; 
unsigned char Minute=31; 
unsigned char Stunde=19;
unsigned char Tag=0; 
unsigned char Wochentag=0; 
unsigned char Monat=0;
unsigned int  Jahr=0;
 
/**********************************************************************************************/
//	Hauptprogramm
/**********************************************************************************************/
 
#pragma code
 
void main (void)	
{
	unsigned char i;
	unsigned char k;
 
//Alle Ein/Ausgänge löschen
    LATA = LATB = LATC = LATD = LATE = 0x00;                   	
 
//Konfigurieren von Ein/Ausgängen
	TRISB = 0x32;                   // RB7=O RB6=O RB5=I RB4=I RB3=O RB2=O RB1=I RB0=O
 
//Erweiterte Einstellungen
	ADCON1=0x0F;			// Alle Port Pins auf digital gesetzt
	CMCON=0x07;			// Komparatoreinänge deaktivieren 
	INTCON2bits.RBPU=1;		// PORTB Pullups deaktivieren
	PORTEbits.RDPU=0;		// PORTD Pullups deaktivieren	
 
//Notwendige Funktionen zum Booten
	INT_Einstellungen();
	EXINT1_Einstellungen();
 
//Solange beim Booten DCF77 empfangen bis es geklappt hat oder 30 Versuche überschritten wurden
	while(DCF_Status==0)
	{
		DCF_Status=DCF77();
	}	
 
//Endlosschleife	
	while(1)
	{
	}
}
 
/**********************************************************************************************/
//	Unterprogramme / Funktionen
/**********************************************************************************************/
 
/**********************************************************************************************/
// Diese Funktion konfiguriert die Interrupts
/**********************************************************************************************/
 
void INT_Einstellungen (void)
{
	INTCONbits.GIEH=1;		// Hoch Priorisierte INTs erlaubt
	INTCONbits.GIEL=1;		// Niedrig Priorisierte INTs erlaubt
	RCONbits.IPEN=1;		// Erlaubt verschiedene Priority Interrupts
}
 
/**********************************************************************************************/
 
/**********************************************************************************************/
// Diese Funktion konfiguriert die Externen Interrupts
/**********************************************************************************************/
 
void EXINT1_Einstellungen(void)	
{
	INTCON3bits.INT1IP=0; 			// Priorität niedrig
	INTCON2bits.INTEDG1=1;			// INT auf fallende Flanke
	INTCON3bits.INT1IE=1;			// INT erlaubt
}


Datei: main.h

/***********************************************************************************************
Autor:				Nicolas Meyertöns 
Version:			1.0
Zugehörige Dateien:		DCF.c , DCF.h , ISR.c , ISR.h , main.c
 
Datei Beschreibung:		main.h - keine
/**********************************************************************************************/
 
// Durch diese Angaben werden die Unterprogramme nur 1mal deklariert
#ifndef main_H
#define	main_H
 
/**********************************************************************************************/
//	Funktionen anmelden
/**********************************************************************************************/
 
void INT_Einstellungen (void);
void EXINT1_Einstellungen(void);
 
/**********************************************************************************************/
 
// Und wenn sie dann deklariert sind, wird diese nicht erneut durchgeführt
#endif	main_H

Hinweis

Achtung PP.gif Es gibt durchaus Optimierungspotential
Dies ist eine relativ simple Lösung um das DCF77 Signal auszuwerten. Eine weitere effektivere Lösung, da Rechenzeit gespart wird ist die Auswertung mittels Timer Interrupt. Damals habe ich mich aber eben nun für diese Lösung entschieden, da ich es unter anderem auch einfach noch nicht besser wusste.

Download

Die Routinen zum Download als ZIP-Archiv Download.gif Download

Siehe auch


Autoren

Nico 14:51, 29. Aug. 2011 (CEST)

Meine Werkzeuge
Namensräume

Varianten
Aktionen
Navigation
Mikrocontroller
Elektrotechnik
Projekte
Displays
Bauteile
Werkzeuge