Hallo liebe Community,
wie der Name schon sagt möchte ich ein DCF77 Signal auswerten. Das ganze mache ich mit einem Atmega 16 bei 2.048 MHz. (2.048MHz/1024 =2000 Hz)
DCF77:
-ein Zeitsignal
-in einer Sekunde ist entweder 0,1 (0) oder 0,2 (1) s ein Low-Pegel
-je nach dem ist das Bit der Sekunde High oder Low (0 oder 1)
Was der Code eigentlich machen soll:
-er soll messen ob ein High-Pegel länger als eine Sekunde ist und so den Beginn einer neuen Minute anzeigt und eine 2 schreiben
-er soll die Low-Pegel messen und bei 0,1s eine 0 schreiben und bei 0,2s eine 1 schreiben
Was der Code macht:
-den Beginn einer neuen Minute erkennt er und schreibt eine 2
-das Low-Pegel messen geht nicht, es sind alle länger als 0,2 Sekunden und er schreibt immer eine 1
Code:
/*
* main.c
*
* Created on: 21.09.2010
*
#include <avr/io.h>
#include <avr/interrupt.h>
#define F_CPU 2048000UL
#define BAUD 9600UL
#define UBRR_BAUD ((F_CPU/(16UL*BAUD))-1)
#define LED_DDR DDRD
#define LED_PORT PORTD
#define LED_PORTPIN PD7
char InterruptFlag; // =0 -> nächster Interrupt bei fallender Flanke / =1 -> nächster Interrupt bei steigender Flanke
unsigned int Zaehlerstand; //nimmt den Zählerstand aus IRC1 auf
unsigned char Sekundenzaehler; //zählt die Sekunden / wird resetet bei der 59 S
char Feld [60]; //das Feld enthält die binären Werte der jeweiligen Sekunden
void uart_init(void)
{
// Baudrate einstellen (Normaler Modus)
UBRRH = (uint8_t) (UBRR_BAUD>>8);
UBRRL = (uint8_t) (UBRR_BAUD & 0x0ff);
// Aktivieren von receiver und transmitter
UCSRB = (1<<RXEN)|(1<<TXEN);
// Einstellen des Datenformats: 8 Datenbits, 1 Stoppbit
UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);
}
ISR(TIMER1_CAPT_vect)
{
Zaehlerstand = ICR1; //Zählerstand wird aus IRC1 ausgelsen
TCNT1 = 0; //16-Bit-Timer Zählerstand wird zurückgesetzt
switch(InterruptFlag)
{
case 0: //der Interrupt hat bei fallender Flanke ausgelöst -> Pausenzeit wird gemessen
InterruptFlag = 1; //zeigt an: nächster Interrupt bei steigender Flanke
TCCR1B |= (1<<ICES1); //Capture Interrupt nun bei steigender Flanke
if (Zaehlerstand >= 3600) //Pause von 1,8s -> Zeigt an der nächste Low-Pegel gehört zur neuen Minute
{
Sekundenzaehler = 0; //der Sekundenzaehler wird resetet
// Warten bis der Sendepuffer frei ist
while ( !( UCSRA & (1<<UDRE)) );
// Daten in den Puffer schreiben und damit senden
UDR = '2';
}
break;
case 1: //der Interrupt hat bei steigender Flanke ausgelöst -> Low-Pegel-Zeit wird gemessen
InterruptFlag = 0; //zeigt an; nächster Interrupt bei fallender Flanke
TCCR1B |= (0<<ICES1); //Capture Interrupt nun bei fallender Flanke
if (Zaehlerstand < 300) //Low-Pegel-Zeit unter 100ms -> 0
{
Feld [Sekundenzaehler] = 0; //schreibt eine null an die aktuelle Stelle des Feldes
Sekundenzaehler = Sekundenzaehler+1; //der Sekundenzähler wird um 1 erhöht für die nächste Sekunde
// Warten bis der Sendepuffer frei ist
while ( !( UCSRA & (1<<UDRE)) );
// Daten in den Puffer schreiben und damit senden
UDR = '0';
}
if (Zaehlerstand > 300) //Low-Pegel-Zeit über 100ms -> 1
{
Feld [Sekundenzaehler] = 1; //schreibt eine eins an die aktuelle Stelle des Feldes
Sekundenzaehler = Sekundenzaehler+1; //der Sekundenzähler wird um 1 erhöht für die nächste Sekunde
// Warten bis der Sendepuffer frei ist
while ( !( UCSRA & (1<<UDRE)) );
// Daten in den Puffer schreiben und damit senden
UDR = '1';
}
break;
}
}
void main(void)
{
TIMSK |= (1<<TICIE1); //gibt den Capture Interrupt frei
TCCR1B |= (0<<ICES1) | (1<<CS12) | (1<<CS10); //erster Interrupt bei einer fallenden Flanke | Prescaler auf 1024 -> 2.048MHz/1024 -> 2000Hz
InterruptFlag = 0; //zeigt an erster Interrupt bei fallender Flanke
DDRD &=~ (1<<PD6); //PD6 als Eingang
PORTD |= (1<<PD6); //...
sei();
uart_init();
LED_DDR |= (1<<LED_PORTPIN); //LED Port als Ausgang
LED_PORT |= (1<<LED_PORTPIN); //LED Port auf High -> LED leuchtet
while(1);
{
if (Sekundenzaehler == 59) //Ende einer Minute steht an -> Auswertung kann erfolgen
{
//Auswertungsfunktion
}
}
}
Ich weiß nicht was ich noch machen soll. Das Signal von dem DCF77-Empfänger kommt auch an. Hab mal mein analoges Voltmeter an den PIN gehalten und man erkennt anhand der unterschiedlichen Tiefe der Ausschläge die 0 und 1... bloß der mC macht das nicht.
Vielleicht fällt ja irgendwem etwas an meinem Code auf. Danke schonmal.
Lesezeichen