Atmega8: DCF77 an ICP1-Pin hängen

OP #4794951
Lesenswert?
• ▲
▼
Hi,

ich versuche gerade das DCF77-Modul von Conrad mit meinen ATmega8 zum 
Laufen zu bekommen. Um das empfangene Signal vom DCF77-Modul zu 
dekodieren, wollte ich mit Hilfe vom ICP1-Pin und einen Timer die 
Biterekennung(100ms low = '0'; 200ms low = '1') realisieren.

Um jetzt erstmal "einzusteigen" habe ich mir unten stehende Funktion 
geschrieben. Wenn ich die Decodierung vom DCF77 richtig verstanden habe, 
sollte jetzt die Ausgabe 'TIMER1_CAPT_vect' 59Mal pro Minute ausgegeben 
werden, oder?. Aber die Ausgabe kommt wesentlich öfters(Zeitmessung alle 
8Sekunden: Da kommt die Ausgabe zwischen 0x - 40x; Eigentlich erwartet: 
8x). Habe ich einen Fehler im Programm, in der Denkweiße oder bekomme 
ich so viele Störsignale, dass ich das Programm so nicht realisieren 
kann?

Bin für jede Hilfe dankbar.

clock.c
1
ISR(TIMER1_CAPT_vect)
2
{
3
  usart_write("TIMER1_CAPT_vect\n");
4

5
}
6

7
void startClock(void) {
8
  TCNT1 |= (1 << ICES1); //0 = 'falling edge', '1'=rising edge
9

10
  //timer
11
  TIMSK |= (1 << TOIE1); //enable interrupt timer
12
  TIMSK |= (1 << TICIE1); //enable interupt capter Register(ICP)
13
  TCCR1B |= (1 << CS10 | 0 << CS11 | 1 << CS12); //prescaler 1024
14
  TCCR1B |= (1 << ICNC1); //noise filter enable
15

16
  TCNT1 = 65535 - (SYSCLK / 1024); //sysclk = 8000000, define in uart.h
17
}

main.c
1
int main(void) {
2

3
  //using usart for debugging
4
  usart_init(9600);
5

6
  DDRC = _BV(LED);   //LED as Output
7
  PORTC = _BV(LED);
8

9
  PORTB = (1 << PD0); //pullup widerstand ICP
10

11

12
  //Enable global interrupt
13
  sei();
14

15
  //start clock
16
  startClock();
17

18
  usart_write("\nDCF 77 Debugger123\n\n");
19

20
  while (1)
21
  {
22
    LED_ON
23
    _delay_ms(1000);
24
    LED_OFF
25
    _delay_ms(1000);
26
  }
27
}
Gast #4794969
Lesenswert?
• ▲
▼
Tobi F. schrieb:
> TCNT1 |= (1 << ICES1); //0 = 'falling edge', '1'=rising edge

TCNT1 ist doch der 16-Bit-Zähler des Counters. ICES1 sollte m.E. im 
TCCR1B-Register gesetzt werden.
Abgesehen davon ist die Methode, das DCF-Signal mittels Interrupt 
aufzunehmen, nicht so ganz optimal. Häufig hat man Störungen, die sich 
wie Prellen geben, und dann werden einzelne Flanken mehrfach erfasst.
#4794970
Lesenswert?
• ▲
▼
Tobi F. schrieb:
> bekomme
> ich so viele Störsignale, dass ich das Programm so nicht realisieren
> kann?

So wirds sein.
Gibt doch mal den Pin auf ne LED aus.

Die bevorzugte Methode ist z.B. alle 10ms per Timerinterrupt das Signal 
einzulesen. Die 100/200ms Pulsdauer und die 2s Pause kann man dann 
bequem mit je einem Byte abzählen.
Die 10ms kann man gleichzeitig auch für die interne Zeitzählung bei 
Empfangsstörungen benutzen.
Gast #4794971
Lesenswert?
• ▲
▼
Hallo,
Es kann schon sein, dass du Störsignale empfängst. Ich hatte auch ein 
ähnliches Problem. Versuch alle Netzteile fernzuhalten, Kabel möglichst 
kurz oder mal andere Orte ausprobieren. Und richte die Antenne grob 
Richtung Frankfut aus (sodass Antenne und die gedachte Linie Richtung 
Frankfurt einen rechten Winkel bilden). Du kannst die Signalqualität 
natürlich auch mit einem Oszilloskop überprüfen. Oder, falls nicht 
vorhanden, eine LED anschließen, oder per µC eine LED ansteuern (erstmal 
ohne Timer oä.) Da das Signal doch recht langsam ist, kann man schon was 
erkennen.
OP #4795020
Lesenswert?
• ▲
▼
Vielen Dank für eure Antworten!

HildeK schrieb:
> TCNT1 ist doch der 16-Bit-Zähler des Counters. ICES1 sollte m.E. im
> TCCR1B-Register gesetzt werden.

Da hast du natürlich recht. Habe es im Code geändert. Danke.

Peter D. schrieb:
> Gibt doch mal den Pin auf ne LED aus.

Ich habe jetzt den Pin vom DCF77 direkt mit einer LED verbunden. Die LED 
sollte jetzt doch eigentlich (ungefähr) im Sekundentakt blinken, oder? 
Aber die 'flakert' ab und zu. D.h. ich habe erhalte zu viel Störsignale.

Peter D. schrieb:
> Die bevorzugte Methode ist z.B. alle 10ms per Timerinterrupt das Signal
> einzulesen. Die 100/200ms Pulsdauer und die 2s Pause kann man dann
> bequem mit je einem Byte abzählen.
> Die 10ms kann man gleichzeitig auch für die interne Zeitzählung bei
> Empfangsstörungen benutzen.

Danke. Ich denke ich werde es dann mal so probieren, wenn ich einen 
Position hier gefunden habe, wo nicht so viel Störungen sind.
OP #4795826
Lesenswert?
• ▲
▼
Soo, der erste Schritt, die Binärzahlen aus dem DCF77-Modul zu 
decodieren und über die UART-Schnittstelle auszugeben, funktioniert 
schonmal. Ich bekomme zwar immer noch oft falsche Werte, aber es kommen 
auch ab und zu die richtige Bitfolge.

Für alle die es interessiert, hier mein Code:
1
ISR(TIMER1_COMPA_vect) {
2
  pulse_sync++;
3

4
  //If DCF77-Pin is "high" count pulse_wide
5
  if (PINB & (1 << PB0)) {
6
    pulse_wide++;
7
    dcf77_pin_low = 1;
8
    pulse_sync = 0;
9
  } else {
10

11
    if (dcf77_pin_low) {
12
      // pulse_wide >= 150ms => '1'
13
       if (pulse_wide >= 15) {
14
        usart_write("1");
15
        pulse_wide = 0;
16
        pulse_sync = 0;
17
      }
18
       // pulse_wide < 150ms => '0'
19
       else {
20
        usart_write("0");
21
        pulse_wide = 0;
22
        pulse_sync = 0;
23
      }
24
      dcf77_pin_low = 0;
25
      pulse_sync = 0;
26
    }
27
  }
28

29
  //linebreak at 59.bit/syncbit, pulse_sync => 180ms
30
  if(pulse_sync >= 180)
31
  {
32
    usart_write("\n %i\n", pulse_sync);
33
  }
34
}
35

36
void startClock(void) {
37

38
  // stop interrupts
39
  cli();
40
  
41
  TCCR1A = 0; // set entire TCCR1A register to 0
42
  TCCR1B = 0; // same for TCCR1B
43
  TCNT1 = 0; // initialize counter value to 0
44

45
  // set compare match register for 100 Hz increments
46
  OCR1A = 1249; // = (8000000 / (64* 100))-1
47

48
  // turn on CTC mode
49
  TCCR1B |= (1 << WGM12);
50

51
  // Set CS12, CS11 and CS10 bits for 64 prescaler
52
  TCCR1B |= (1 << CS11);
53
  TCCR1B |= (1 << CS10);
54

55
  // enable timer compare interrupt
56
  TIMSK |= (1 << OCIE1A);
57
  
58
  // allow interrupts
59
  sei();
60
}
61

62

63
int main(void) {
64

65
  //using usart for debugging
66
  usart_init(9600);
67

68
  DDRC = _BV(LED);   //LED as Output
69
  PORTC = _BV(LED); //Pull-up resistor LED
70

71
  PORTB = (1 << PD0); //Pull-up resistor DCF77
72

73
  //start clock
74
  startClock();
75

76
  usart_write("\nDCF 77 Debugger123\n\n");
77

78
  while (1)
79
  {
80
    LED_ON;
81
    _delay_ms(1000);
82
    LED_OFF;
83
    _delay_ms(1000);
84
  }
85
}

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren