Hallo, ich habe versucht mir einen DCF77-Empfänger zu programmieren. sobald das L-Signal vom Empfänger kommt wird ein interrupt an PD2 ausgelöst, das programm zählt ca 100ms und prüft ob das Signal immer noch L ist, um eine 1 oder eine 0 im Signal festzustellen, dies wird dann im T-Bit gespeichert und je nach sekundenzahl ins passende Register geschoben. Die Pause in der 59. sekunde soll von einem Compare interrupt am Timer1 erkannt werden und den sekundenzähler wieder auf 0 setzen, dass Problem liegt allerdings darin, dass das ganze Programm nicht mehr funktioniert, sobald ich den Timer im Programm einschalte, er scheint viel zu schnell zu Zählen, kann mir jemand sagen was ich falsch mache? Im Programm habe ich einige Ausgabebefehle integriert, in der hoffnung, dass ich den Fehler finde, allerdings vergebens... Quelltext: .include "m16def.inc" .org 0000 rjmp init .org int0addr rjmp int0routine .org OC1Aaddr rjmp secpause .equ xtal = 8000000 .def minute = r24 .def stunde = r23 init: ldi r16, low(ramend) out spl, r16 ldi r16, high(RAMEND) out sph, r16 ldi r16, 0xff ;Portb->Ausgang out ddrb, r16 out ddrc, r16 ;auch out ddra, r16 ;nochmal ldi r16, 0x00 ;Portd->Eingang out ddrd, r16 ldi r16, 0b00000010 ;INT0 konfigurieren out MCUCR, r16 ldi r16, 0b01000000 ;INT0 aktivieren out GICR, r16 ldi r16, 0b00000101 ;Timer1 aktivieren, teiler 1024 out tccr1b, r16 ldi r16, 0b00010000 ;Interrupt bei Compare A Match out timsk, r16 ldi r16, 0xff ;Compare A Match wert festlegen out ocr1al, r16 ldi r16, 0x20 out ocr1ah, r16 ldi r25, 0xff ldi r16, 0b01010101 out porta, r16 sei loop: ;bld r16, 5 ;com r16 in r20, porta mov r16, r25 com r16 out portb, r16 mov r16, minute com r16 out portc, r16 rjmp loop ;***************************Entscheidung über 1 oder 0******************* ;100ms 0V = Logisch 0 200ms 0V = Logisch 1 int0routine: cli ;push r16 ldi r16, 0x00 out tcnt1h, r16 out tcnt1l, r16 rcall count ;pop r16 inc r25 ;sekundenzähler erhöhen clt ;T-Flag wird gelöscht sbis portd, 2 set ;T-Flag wird gesetzt rjmp savedcf ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; ;Hier wird anhand des Sekundenzählers der richtige speicherort ;für jedes bit bestimmt. savedcf: cpi r25, 0 breq ausgabe cpi r25, 21 brlo end breq min1 cpi r25, 22 breq min2 cpi r25, 23 breq min4 cpi r25, 24 breq min8 cpi r25, 25 breq min10 cpi r25, 26 breq min20 cpi r25, 27 breq min40 cpi r25, 28 breq end cpi r25, 29 breq std1 cpi r25, 30 breq std2 cpi r25, 31 breq std4 cpi r25, 32 breq std8 cpi r25, 33 breq std10 cpi r25, 34 breq std20 rjmp end ;35 aufwärts un 1-20 wird ausgeblendet min1: bld minute, 0 rjmp end min2: bld minute, 1 rjmp end min4: bld minute, 2 rjmp end min8: bld minute, 3 rjmp end min10: bld minute, 4 rjmp end min20: bld minute, 5 rjmp end min40: bld minute, 6 rjmp end std1: bld stunde, 0 rjmp end std2: bld stunde, 1 rjmp end std4: bld stunde, 2 rjmp end std8: bld stunde, 3 rjmp end std10: bld stunde, 4 rjmp end std20: bld stunde, 5 rjmp end end: sei reti ausgabe: ;out portb, stunde ldi stunde, 0x00 ldi minute, 0x00 sei reti ;Verzögerung count: ldi r16, 0x00 ldi r17, 0x00 count_1: inc r16 cpi r16, 0xff brne count_1 inc r17 cpi r17, 90 brne count_1 ret ;*********************secPause****************************** secpause: ;push r16 ldi r16, 0x00 out tcnt1h, r16 out tcnt1l, r16 ldi r25, 0xff ;pop r16 com r20 out porta, r20 reti Gruß Jochen
Hi > ldi r16, 0xff ;Compare A Match wert festlegen > out ocr1al, r16 > ldi r16, 0x20 > out ocr1ah, r16 Datenblatt: To do a 16-bit write, the high byte must be written before the low byte. For a 16-bit read, the low byte must be read before the high byte. In fast allen Datenblättern gibt es einen Punkt:'Accessing 16-bit Registers' MfG Spess
Danke, das hat mir schon um einiges weitergeholfen, allerdings zählt mein sekundenzähler relativ warlos, an was kann das liegen, evtl. an empfangsstörungen? Gruß Jochen
Hi Ich nehme an, das deine 100ms Abfrage kritisch ist. Also evtl. zu knapp. Ich habe das damals anders gelöst: Bei der Startflanke wird der Zähler auf Null gesetzt. Dann wird das Ende des Impulses abgewartet und danach der Zählerstand abgefragt. Zwischen 50 und 150 ms eine Null, bei >150 und <250 eine Eins. >250 Schaltsekunde. Nur so vom Prinzip her. MfG Spess
Ich mach es auch so ähnlich wie Spess, allerdings pin-change interrupt da int0/1 schon belegt sind. damit ist auch die zustands/flanken sache egal und es ist auch egal ob der high- oder low-aktive ausgang des dcf-modules verwendet wird. dann einen timer der alle 10ms um 1 hochzählt und im pinchange-int den zähler wert testen. hat den vorteil das ich auch einfach empfangsstörungen ausbügeln kann, z.b. alles kleiner als 80ms kann nur eine störung sein, alles über etwa 240ms bis 780ms kann auhc nur eine störung sein. erreicht der timer 255 ist es ein time-out und somit kein signalempfang. den timer resete ich nicht am ende des 100/200ms puls sondern beim beginn der des nächsten 100/200ms puls, damit lässt sich der minuten-puls über 1800 bzw. 1900ms auch detektieren. die bits shifte ich einfach aus dem carry in den sram und beim minuten-puls dann von dort wieder per shift um x stellen bis zur gewünschten info, konvertieren, weitershiften bis zur nächsten. parity lässt sich damit auch recht einfach prüfen. funktioniert in wien mit schlechtem empfang nicht mal so schlecht, einzig in den abendstunden wenn rundherum die tv-geräte laufen klappt es öfter mal nicht. aja und das ganze in asm auf einem mega168 mit 20mhz. wobei die hohe taktfrequenz freilich nicht notwendig ist für dcf, klar.
Hi Viele Wege führen nach Rom. Mein Verfahren ist auch nicht unbedingt das Nonplusultra. Ich hatte nur im Rahmen dieser 'DCF... Wetter...'-Diskussion mal eigene Aufzeichnungen gemacht und dafür schnell was 'zusammengeschossen'. Hat aber erstaunlich gut funktioniert. MfG Spess
Guten Morgen, Ist im Prinzip eh sehr einfach... außer man hat schlechten empfang und immer wieder störungen im signal. Und da find ich das verfahren das du ja auch anwendest (timer und vergangene Zeit auswerten) am einfachsten, auswertung im hintergrund via isr-routinen ist möglich und es lässt sich einfach erweitern um eben die störsignale mithilfe von zeitfenstern zu ignorieren. kommt natürlich ein störsignal innerhalb eines "gültigen" zeitfensters und das 2x dann kanns mit der parity auch schon schwierig werden. -> plausibilitätstests wie 0<=sek/min=<59 usw. helfen dann auch noch. aber bei gutem empfang ist die sache ja eigentlich sehr einfach, bzw. in der praxis welche der theorie noch am ehesten entspricht ;) schönen tag, mfg, Martin.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.