Hallo zusammen,
bezugnehmend auf diesen Thread ATMega 1284p - PinChange Interrupt,
habe ich gleich noch eine Frage hinterher. Wie ich ja beschrieben habe
möchte ich ein DCF77 Signal auswerten, allerdings verwende ich nicht den
externen Interrupt, sondern einen Pin Change Interrupt am PIN PCINT6
(PA6) meines ATMega1284p.
Hier nochmal die Configuration der Interrupts:
1 | //Interrupt PCINT6 einschalten
|
2 | PCICR |= (1<<PCIE0);
|
3 | PCMSK0 |= (1<<PCINT6);
|
4 |
|
5 | //Interrupt Overfolw enable
|
6 | TIMSK1 |= (1 << TOIE1);
|
7 | //Setzen des Prescaler auf 1024
|
8 | TCCR1B |= (1<<CS10 | 0<<CS11 | 1<<CS12);
|
9 |
|
10 | //F_CPU defined in config.h
|
11 | TCNT1 = 65535 - (F_CPU / 1024);
|
F_CPU ist definiert in einer Datei /config.h/:
1 | #define F_CPU 16000000UL
|
Das sollte für mein AVR Net-IO von Pollin, auf dem das Ganze läuft
hinhauen - zumindest passt die serielle Ausgabe. Ich sehe das mal als
Indikator für die Korrektheit der Einstellung an :)
Grundsätzlich verwende ich den DCF77 Code von Ulrich Radig, und habe
daher - nach Anpassung an meinen Chip folgende ISRs:
1 | //############################################################################
|
2 | //Overflow Interrupt wird ausgelöst bei 59Sekunde oder fehlenden DCF77 Signal
|
3 | //############################################################################
|
4 | ISR (TIMER1_OVF_vect)
|
5 | {
|
6 | struct DCF77_Bits *rx_buffer;
|
7 | rx_buffer = (struct DCF77_Bits*)(char*)&dcf_rx_buffer;
|
8 |
|
9 | //Zur¸cksetzen des Timers
|
10 | TCNT1 = 65535 - (F_CPU / 1024);
|
11 |
|
12 | //wurden alle 59 Bits empfangen und sind die Paritys richtig?
|
13 | if (rx_bit_counter == 59 &&
|
14 | flags.parity_P1 == rx_buffer->P1 &&
|
15 | flags.parity_P2 == rx_buffer->P2 &&
|
16 | flags.parity_P3 == rx_buffer->P3)
|
17 | //Alle 59Bits empfangen stellen der Uhr nach DCF77 Buffer
|
18 | {
|
19 | //Berechnung der Minuten BCD to HEX
|
20 | mm = rx_buffer->Min-((rx_buffer->Min/16)*6);
|
21 | if (mm != 0){mm--;}else{mm = 59; h_hh = 1;};
|
22 |
|
23 | //Berechnung der Stunden BCD to HEX
|
24 | hh = rx_buffer->Hour-((rx_buffer->Hour/16)*6);
|
25 | if (h_hh) {hh--;h_hh = 0;};
|
26 |
|
27 | //Berechnung des Tages BCD to HEX
|
28 | day= rx_buffer->Day-((rx_buffer->Day/16)*6);
|
29 |
|
30 | //Berechnung des Monats BCD to HEX
|
31 | mon= rx_buffer->Month-((rx_buffer->Month/16)*6);
|
32 |
|
33 | //Berechnung des Jahres BCD to HEX
|
34 | year= 2000 + rx_buffer->Year-((rx_buffer->Year/16)*6);
|
35 |
|
36 | //Sekunden werden auf 0 zur¸ckgesetzt
|
37 | ss = 59;
|
38 | flags.dcf_sync = 1;
|
39 | }
|
40 | else
|
41 | //nicht alle 59Bits empfangen bzw kein DCF77 Signal Uhr l‰uft
|
42 | //manuell weiter
|
43 | {
|
44 | Add_one_Second();
|
45 | flags.dcf_sync = 0;
|
46 | }
|
47 | //zur¸cksetzen des RX Bit Counters
|
48 | rx_bit_counter = 0;
|
49 | //Lˆschen des Rx Buffers
|
50 | dcf_rx_buffer = 0;
|
51 | };
|
1 | //############################################################################
|
2 | //DCF77 Modul empfängt Träger
|
3 | //############################################################################
|
4 | ISR (PCINT0_vect) {
|
5 | if ((PINA & (1<<PINA6)) && (oldPinLevel == 0)) {
|
6 | //check for high level
|
7 | INT0_CONTROL = INT0_RISING_EDGE;
|
8 | oldPinLevel = 1;
|
9 | PORTC ^= _BV(PC6);
|
10 |
|
11 | } else if ((!(PINA & (1<<PINA6))) && (oldPinLevel == 1)) {
|
12 | //check for low level
|
13 | INT0_CONTROL = INT0_FALLING_EDGE;
|
14 | oldPinLevel = 0;
|
15 | PORTC ^= _BV(PC6);
|
16 | }
|
17 |
|
18 |
|
19 | //Auswertung der Pulseweite
|
20 | if (INT0_CONTROL == INT0_RISING_EDGE) {
|
21 | flags.dcf_rx ^= 1;
|
22 |
|
23 | //Secunden Hilfs Counter berechnen // F_CPU defined in USART.H
|
24 | h_ss = h_ss + TCNT1 - (65535 - (F_CPU / 1024));
|
25 | //Zur¸cksetzen des Timers
|
26 | TCNT1 = 65535 - (F_CPU / 1024);
|
27 |
|
28 | //ist eine Secunde verstrichen // F_CPU defined in USART.H
|
29 | if (h_ss > (F_CPU / 1024 / 100 * 90)) {
|
30 | //Addiere +1 zu Sekunden
|
31 | Add_one_Second();
|
32 | //Zur¸cksetzen des Hilfs Counters
|
33 | h_ss = 0;
|
34 | };
|
35 | } else {
|
36 | //Auslesen der Pulsweite von ansteigender Flanke zu abfallender Flanke
|
37 | unsigned int pulse_wide = TCNT1;
|
38 |
|
39 | //Zur¸cksetzen des Timers
|
40 | TCNT1 = 65535 - (F_CPU / 1024);
|
41 |
|
42 | //Secunden Hilfs Counter berechnen
|
43 | h_ss = h_ss + pulse_wide - (65535 - (F_CPU / 1024));
|
44 |
|
45 | //Parity speichern
|
46 | //beginn von Bereich P1/P2/P3
|
47 | if (rx_bit_counter == 21 || rx_bit_counter == 29 || rx_bit_counter == 36) {
|
48 | flags.parity_err = 0;
|
49 | };
|
50 |
|
51 | //Speichern von P1
|
52 | if (rx_bit_counter == 28) {flags.parity_P1 = flags.parity_err;};
|
53 |
|
54 | //Speichern von P2
|
55 | if (rx_bit_counter == 35) {flags.parity_P2 = flags.parity_err;};
|
56 |
|
57 | //Speichern von P3
|
58 | if (rx_bit_counter == 58) {flags.parity_P3 = flags.parity_err;};
|
59 |
|
60 | //‹berpr¸fen ob eine 0 oder eine 1 empfangen wurde
|
61 | //0 = 100ms
|
62 | //1 = 200ms
|
63 | //Abfrage grˆfler als 150ms (15% von 1Sekund also 150ms)
|
64 | if (pulse_wide > (65535 - (F_CPU / 1024)/100*85))
|
65 | {
|
66 | //Schreiben einer 1 im dcf_rx_buffer an der Bitstelle rx_bit_counter
|
67 | dcf_rx_buffer = dcf_rx_buffer | ((unsigned long long) 1 << rx_bit_counter);
|
68 | //Toggel Hilfs Parity
|
69 | flags.parity_err = flags.parity_err ^ 1;
|
70 | }
|
71 |
|
72 | //RX Bit Counter wird um 1 incrementiert
|
73 | rx_bit_counter++;
|
74 | }
|
75 |
|
76 | }
|
Dem Blinken der LED nach, sieht die Erkennung der BITs soweit auch ganz
gut aus - ich hab leider kein OSZI um das genauer nachzumessen. Ich sehe
aber mindestens einen Unterschied zwischen den 100ms und 200ms
High-Pegeln und BIT59.
Leider bekomm ich trotzdem keinen Sync hin.
Könnt ihr mir ein paar Tipps geben, wie ich bei der Fehlersuche evtl.
noch auf Hinweise zur Ursache kommen kann, oder seht ihr vielleicht
sogar einen Fehler im obigen Code?
Danke und Grüße
Galdo