Knipser-14
22.09.2010, 11:34
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
/*
* 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.
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
/*
* 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.