PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : DCF77 Lib Download - wie und wo?



dl1akp
23.12.2013, 10:06
Hallo Fachleute!

Möglicherweise ist das ja eine dumme Frage, oder auch im falschen Forum...
Aber wie zum Geier kann ich denn hier aus dem Wiki was runterladen???

Genau handelt es sich um diese Seite:
http://www.rn-wissen.de/index.php/DCF77-Decoder_als_Bascom-Library

Über eine kurze Hilfestellung würde ich mich echt freuen.

Vielen Dank und ein ein Frohes Fest an alle Robo-Netz User!
Andreas

Dirk
23.12.2013, 11:00
Hi,

das geht nur mit Copy&Paste.

Einfach ist das ja mit der Demo (http://www.rn-wissen.de/index.php/DCF77-Decoder_als_Bascom-Library#Bascom_Hauptprogramm) und der Include-Datei (http://www.rn-wissen.de/index.php/DCF77-Decoder_als_Bascom-Library#Bascom_Include-File):
Einfach markieren, kopieren, in den Windows-Editor einfügen und Datei so benennen, wie im RN-Wissen angegeben.

Die Lib selbst ist in einzelne Teile gestückelt, die man aneinanderfügen müßte. Da das etwas umständlich ist, habe ich die Lib (V4.11) hier mal komplett eingefügt.
Datei dcf77.lib:

copyright = Dirk
comment = DCF77-Decoder und Softclock
libversion = 4.11
date = 15.01.2010
statement = ----------------------------------
statement = Version 4.11:
statement = !
statement = Version 4.10:
statement = Jahr: BCD->DEZ-Fehler korrigiert!
statement = Version 4.00:
statement = Komplette Paritätsprüfung
statement = Auswertung der DCF77-Bits 15..20
statement = NEU: DCF77-Bit 20 - Prüfung!
statement = NEU: Schaltsekunde decodiert!
statement = NEU: DCF77-Bits 0..14 erfasst!
statement = NEU: Plausibilitäts-Check!
statement = NEU: Validitäts-Zähler!
statement = ----------------------------------

[Dcf77_soft]
;Eingang für DCF77-Empfänger-Anschluss:
.equ PIND = &H10 ;Pind
.equ PIND3 = 3 ;3 = Pin 3

;Timer-Interruptfrequenz:
.equ ISR_freq = 40 ;40 Hz

;Grenzwerte für Pausenzeit-Zähler (/ ISR_freq [s]):
.equ LastBit0Max = 79 ;LastBit 0 obere Zeitgrenze + 1
.equ LastBit_Mid = 75 ;LastBit-Grenze
.equ LastBit1Min = 71 ;LastBit 1 untere Zeitgrenze
.equ DataBit0Max = 39 ;Datenbit 0 obere Zeitgrenze + 1
.equ DataBit_Mid = 35 ;Datenbit-Grenze
.equ DataBit1Min = 31 ;Datenbit 1 untere Zeitgrenze
.equ Spike_Limit = 3 ;Störimpulsgrenze

;Validitäts-Zähler Limit:
.equ Val_Limit = 1 ;Jedes Telegramm ist gültig

.def Status = r16
;Bit0 = 15. Impuls erreicht
;Bit1 = Minutenparität OK
;Bit2 = Stundenparität OK
;Bit3 = Parität OK
;Bit4 = 58 Impulse empfangen
;Bit5 = Gültiges DCF77-Telegramm
;Bit6 = Softclock nach DCF gestellt
;Bit7 = DCF-Decoder EIN
.def Counter = r17
.def Parity = r18
.def Impulse = r19
.def Shifter = r20

Dcf77_soft:
*lds Status,{Dcfstatus} ;Status laden
rcall Softclock ;Softclock bearbeiten
rjmp dcf77_start
;-------------------------------------------------------------------------------
[Dcf77]
$EXTERNAL Dcf77_soft

Dcf77:
*lds Status,{Dcfstatus} ;Status laden
dcf77_start:
*lds Counter,{DCF77Counter} ;Pausenzeit-Zähler laden
*lds Parity,{DCF77Parity} ;Fehler-Flag + 1-Zähler laden
sbis PIND,PIND3 ;Input-Pin für DCF-Empfänger
rjmp dcf77_5 ;low: Bit auswerten!
inc Counter ;high: Pausenzeit zählen!
brne dcf77_3
dcf77_1:
sbr Parity,&B10000000 ;Fehler-Flag setzen
*sts {DCF77Parity},Parity
andi Status,&B11000000 ;Statusbits 0..5 löschen
dcf77_2:
clr Counter ;Pausenzeit-Zähler zurücksetzen
dcf77_3:
*sts {DCF77Counter},Counter
*sts {Dcfstatus},Status
dcf77_4:
ret

dcf77_5:
tst Counter ;Auswertung fertig?
breq dcf77_4 ;ja: Ende!
*lds Impulse,{DCF77Impulse} ;nein: Auswerten!
*lds Shifter,{DCF77Shifter}
*lds ZL,{DCF77TAL}
*lds ZH,{DCF77TAH}
cpi Counter,LastBit0Max ;LastBit 0 obere Zeitgrenze + 1
brsh dcf77_1 ;überschritten: Fehler
cpi Counter,LastBit_Mid ;LastBit-Grenze
brlo dcf77_6
rjmp dcf77_20 ;75..78 = LastBit0
dcf77_6:
cpi Counter,LastBit1Min ;LastBit 1 untere Zeitgrenze
brlo dcf77_7
rjmp dcf77_19 ;71..74 = LastBit1
dcf77_7:
sbrc Parity,7 ;wenn Fehler aufgetreten, ...
rjmp dcf77_2 ;... dann Abbruch!

cpi Counter,Spike_Limit ;Störimpulsgrenze
brlo dcf77_2 ;Störimpuls wird ignoriert
cpi Counter,DataBit0Max ;Datenbit 0 obere Zeitgrenze + 1
brsh dcf77_1 ;überschritten: Fehler
cpi Counter,DataBit1Min ;Datenbit 1 untere Zeitgrenze
brlo dcf77_1 ;unterschritten: Fehler
*sts {DCF77Databit},Counter ;DataBit0/1-Pausenlänge für Debug
cpi Counter,DataBit_Mid ;Datenbit-Grenze
brlo dcf77_8 ;Bit1!

cpi Impulse,20 ;DataBit = 0 (35..38):
breq dcf77_2 ;Bit 20 = 0: Abbruch!
cpi Impulse,58 ;P3 (= 0) bei Schaltsekunde?
breq dcf77_2 ;Abbruch: LastBit 59 (= 0) folgt!
rjmp dcf77_10 ;andere 0-Bits: weiter

dcf77_8: ;DataBit = 1 (31..34):
cpi Impulse,21 ;DCF77-Bits 0..20 (= 1)?
brlo dcf77_9 ;keine Parität!
inc Parity ;sonst alle 1-Bits zählen
*sts {DCF77Parity},Parity
cpi Impulse,28
breq dcf77_10 ;Minutenparitätsbit nicht addieren!
cpi Impulse,35
breq dcf77_10 ;Stundenparitätsbit nicht addieren!
cpi Impulse,58 ;P3 (= 1) bei Schaltsekunde?
breq dcf77_2 ;Abbruch: LastBit 59 (= 0) folgt!
dcf77_9:
ld Counter,Z ;Counter = aktuelle DCF77Buffer Zelle
add Counter,Shifter ;addiere 1 an der aktuellen Bitposition
st Z,Counter ;zurückspeichern

dcf77_10:
lsl Shifter ;Shifter auf nächste Bitposition
*sts {DCF77Shifter},Shifter
cpi Impulse,7
brlo dcf77_16 ;DCF77-Bits 0..7 Zyklus
breq dcf77_15 ;letztes Bit 0..7 Zyklus
cpi Impulse,14
brlo dcf77_16 ;DCF77-Bits 8..14 Zyklus
brne dcf77_11
andi Status,&B11000111 ;Statusbits 3..5 löschen
sbr Status,&B00000001 ;Status 15. Impuls erreicht setzen
rjmp dcf77_15 ;letztes Bit 8..14 Zyklus
dcf77_11:
cpi Impulse,20
brlo dcf77_16 ;DCF77-Bits 15..20 Zyklus
breq dcf77_15 ;letztes Bit (DCF77-Bit 20)
cpi Impulse,28
brlo dcf77_16 ;Minuten-Zyklus
breq dcf77_17 ;Minutenparität
cpi Impulse,35
brlo dcf77_16 ;Stunden-Zyklus
breq dcf77_17 ;Stundenparität
cpi Impulse,41
brlo dcf77_16
breq dcf77_12 ;letztes Bit TAG
cpi Impulse,44
brlo dcf77_16
breq dcf77_12 ;letztes Bit WOCHENTAG
cpi Impulse,49
brlo dcf77_16
breq dcf77_12 ;letztes Bit MONAT
cpi Impulse,57
brne dcf77_16 ;nicht letztes Bit JAHR
dcf77_12: ;DCF77Buffer Zelle in DEZ wandeln:
ld Counter,Z ;Counter = aktuelle DCF77Buffer Zelle
mov Shifter,Counter ;Counter (BCD)
andi Shifter,&H0F
dcf77_13:
subi Counter,&H10
brcs dcf77_14
subi Shifter,&HF6
rjmp dcf77_13
dcf77_14: ;-> Shifter (DEZ)
st Z,Shifter ;DEZ in Zelle zurückspeichern
cpi Impulse,57
breq dcf77_16 ;letztes Bit JAHR
dcf77_15: ;aktuelle DCF77Buffer Zelle fertig:
ldi Shifter,1 ;Bitposition zurücksetzen
adiw ZL,1 ;nächste DCF77Buffer Zelle
*sts {DCF77Shifter},Shifter
*sts {DCF77TAL},ZL ;Adresse der nächsten Zelle speichern
*sts {DCF77TAH},ZH
dcf77_16:
inc Impulse ;nächstes DCF77-Bit
*sts {DCF77Impulse},Impulse
rjmp dcf77_2

dcf77_17: ;Parität Min./Std. Auswertung:
sbrc Parity,0
rjmp dcf77_2 ;Parität Fehler: Abbruch!
cpi Impulse,28 ;Minutenparität?
brne dcf77_18 ;nein: Stundenparität (35)
sbr Status,&B00000010 ;Status Minutenparität OK setzen
rjmp dcf77_12
dcf77_18:
sbr Status,&B00000100 ;Status Stundenparität OK setzen
rjmp dcf77_12 ;Parität Min./Std. OK

dcf77_19: ;Telegramm Ende:
inc Parity ;LastBit = 1
dcf77_20: ;LastBit = 0
*sts {DCF77Lastbit},Counter ;LastBit0/1-Pausenlänge für Debug
cpi Impulse,58 ;58 DCF77-Bits erfasst?
brne dcf77_21 ;unvollständig: weiter
sbr Status,&B00010000 ;ja: Status 58 Impulse empfangen setzen
dcf77_21:
andi Parity,&B10000001
brne dcf77_22 ;Paritäts- oder sonst. Fehler aufgetreten?
sbr Status,&B00001000 ;nein: Status Parität OK setzen
dcf77_22:
mov Counter,Status
andi Counter,&B00011111 ;Status Bits 0..4?
cpi Counter,&B00011111 ;alle 5 Bits = 1?
breq dcf77_24
dcf77_23:
clr Shifter ;Validitäts-Zähler zurücksetzen
rjmp dcf77_25 ;Fehler: Softclock NICHT stellen!

dcf77_24: ;Plausibilitäts-Check:
ld Counter,Z ;Jahr (0..99)
cpi Counter,100
brsh dcf77_23 ;> 99: Nicht plausibel!
ld Counter,-Z ;Monat (1..12)
tst Counter
breq dcf77_23
cpi Counter,13
brsh dcf77_23
ld Counter,-Z ;Wochentag (1..7)
tst Counter
breq dcf77_23
cpi Counter,8
brsh dcf77_23
ld Counter,-Z ;Tag (1..31)
tst Counter
breq dcf77_23
cpi Counter,32
brsh dcf77_23
ld Counter,-Z ;Stunde (0..23)
cpi Counter,24
brsh dcf77_23
ld Counter,-Z ;Minute (0..59)
cpi Counter,60
brsh dcf77_23
adiw ZL,5 ;Pufferzeiger auf Jahr zurücksetzen
sbr Status,&B00100000 ;Status Gültiges DCF77-Telegramm setzen

*lds Shifter,{DCF77Val_cnt} ;Validitäts-Zähler laden
inc Shifter ;Zähler erhöhen
cpi Shifter,Val_Limit ;Stand Validitäts-Zähler?
brlo dcf77_25 ;< Val_Limit: Softclock NICHT stellen!
ldi Shifter,Val_Limit ;Zähler wird nicht > Val_Limit!

sbrs Status,7 ;Status DCF-Decoder EIN/AUS?
rjmp dcf77_25 ;AUS: Softclock NICHT stellen!

;Softclock nach DCF stellen:
loadadr _year,X ;Zeiger auf Softclock-Variablen
ld Counter,Z ;Jahr = DCF77Buffer(9)
st X,Counter ;in _year sichern
ld Counter,-Z ;Monat = DCF77Buffer(8)
st -X,Counter ;in _month sichern
ld Counter,-Z ;Wochentag = DCF77Buffer(7)
*sts {_dayofweek},Counter ;in _dayofweek sichern
ld Counter,-Z ;Tag = DCF77Buffer(6)
st -X,Counter ;in _day sichern
ld Counter,-Z ;Stunde = DCF77Buffer(5)
st -X,Counter ;in _hour sichern
ld Counter,-Z ;Minute = DCF77Buffer(4)
st -X,Counter ;in _min sichern
clr Counter
st -X,Counter ;_sec zurücksetzen
*sts {Dcf77hsec},Counter ;Sek.-Bruchteile zurücksetzen
ld Counter,-Z ;DCF77-Bits 15..20 = DCF77Buffer(3)
*sts {Dcfflags},Counter ;in Dcfflags sichern
ld Counter,-Z ;DCF77-Bits 8..14 = DCF77Buffer(2)
*sts {Dcf77bits8_14},Counter ;in Dcf77bits8_14 sichern
ld Counter,-Z ;DCF77-Bits 0..7 = DCF77Buffer(1)
*sts {Dcf77bits0_7},Counter ;in Dcf77bits0_7 sichern
sbr Status,&B01000000 ;Status Softclock nach DCF gestellt setzen

dcf77_25:
andi Status,&B11111000 ;Statusbits 0..2 löschen
rjmp dcf77_26

;-------------------------------------------------------------------------------
[Dcf77_init]
$EXTERNAL Dcf77_soft

Dcf77_init: ;DCF77-Variablen Reset
clr Shifter ;Validitätszähler zurücksetzen
andi Status,&B11000000 ;Statusbits 0..5 löschen
dcf77_26:
*sts {Dcfstatus},Status ;Status speichern
*sts {DCF77Val_cnt},Shifter ;Validitäts-Zähler speichern
loadadr DCF77Buffer(1),Z ;Adresse DCF77Buffer
mov Parity,ZL
mov Impulse,ZH
loadadr DCF77Counter,Z ;Adresse DCF77Counter
ldi Counter,12
clr Shifter
dcf77_27: ;DCF77Counter..DCF77Buffer = 0
st Z+,Shifter
dec Counter
brne dcf77_27
inc Counter
st Z+,Counter ;DCF77Shifter = 1
st Z+,Parity ;Adresse DCF77Buffer -> DCF77TAL/AH
st Z,Impulse
ret

;BASCOM-Variablen für die Dcf77.lib:
;DCF77counter: Pausenzeit-Zähler
;DCF77parity: Fehler-Flag (Bit 7) + 1-Bit-Zähler
;DCF77impulse: Aktuelle DCF77-Bitnummer
;DCF77buffer(9): Zeit-Zwischenspeicher
;(Inhalt: DCF77-Bits 0..7, DCF77-Bits 8..14, DCF-Flags (= DCF77-Bits 15..20),
; Minute, Stunde, Tag, Wochentag, Monat, Jahr)
;DCF77shifter: Bitposition in der aktuellen DCF77Buffer Zelle
;DCF77tal: Zeiger (low) auf die aktuelle DCF77Buffer Zelle
;DCF77tah: Zeiger (high) auf die aktuelle DCF77Buffer Zelle
;Dcf77hsec: Sekunden-Bruchteile
;Dcf77bits0_7: DCF77-Bits 0..7
;Dcf77bits8_14: DCF77-Bits 8..14
;Dcf77val_cnt: Validitäts-Zähler
;Dcf77lastbit: LastBit-Pausenlänge für Debug
;Dcf77databit: DataBit-Pausenlänge für Debug

;-------------------------------------------------------------------------------
Softclock:
*lds Counter,{Dcf77hsec}
inc Counter ;Sek.-Bruchteile erhöhen
cpi Counter,ISR_freq ;1000ms = 1s erreicht?
breq Soft_10 ;ja: weiter
*sts {Dcf77hsec},Counter
ret ;sonst Ende
Soft_10:
clr Counter ;Sek.-Bruchteile löschen
*sts {Dcf77hsec},Counter
*lds Counter,{_sec}
inc Counter ;Sekunde erhöhen
cpi Counter,60 ;60 Sekunden erreicht?
breq Soft_20 ;ja: weiter
*sts {_sec},Counter
ret
Soft_20:
clr Counter ;Sekunde löschen
*sts {_sec},Counter
*lds Counter,{_min}
inc Counter ;Minute erhöhen
cpi Counter,60 ;60 Minuten erreicht?
breq Soft_30 ;ja: weiter
*sts {_min},Counter
ret
Soft_30:
clr Counter ;Minute löschen
*sts {_min},Counter
*lds Counter,{_hour}
inc Counter ;Stunde erhöhen
cpi Counter,24 ;24 Stunden erreicht?
breq Soft_40 ;ja: weiter
*sts {_hour},Counter
ret
Soft_40:
clr Counter ;Stunde löschen
*sts {_hour},Counter
*lds Counter,{_dayofweek}
inc Counter ;Wochentag erhöhen
cpi Counter,8 ;letzter Wochentag erreicht?
brne Soft_50 ;nein: weiter
ldi Counter,1 ;Wochentag auf "1" (Montag)
Soft_50:
*sts {_dayofweek},Counter
*lds Counter,{_day} ;Tag holen
*lds Shifter,{_month} ;Monat holen
ldi zl,low(Daysofmonth*2)
ldi zh,high(Daysofmonth*2) ;Anzahl Tage pro Monat holen
add zl,Shifter ;Zeiger auf aktuellen Monat
lpm ;Anzahl Tage holen
cp Counter,r0 ;Monatsende erreicht?
brne Soft_90 ;nein: weiter
cpi Shifter,2 ;Monatsende Februar (wg. Schaltjahr)?
brne Soft_60 ;nein: weiter
cbr Status,&B01000000 ;Status Softclock nach DCF gestellt löschen
Soft_60:
cpi Shifter,6 ;Monatsende Juni (wg. Schaltsekunde)?
brne Soft_70 ;nein: weiter
cbr Status,&B01000000 ;Status Softclock nach DCF gestellt löschen
Soft_70:
ldi Counter,1 ;Tag auf 1
cpi Shifter,12 ;Jahresende (+ wg. Schaltsekunde)?
brne Soft_100 ;nein: weiter
cbr Status,&B01000000 ;Status Softclock nach DCF gestellt löschen
*lds Shifter,{_year} ;Jahr holen
inc Shifter ;Jahr erhöhen
cpi Shifter,100 ;Jahr 100 erreicht?
brne Soft_80 ;nein: Ende
clr Shifter ;Jahr 00 setzen
Soft_80:
*sts {_year},Shifter ;speichern
ldi Shifter,1 ;Monat auf 1
rjmp Soft_110
Soft_90:
inc Counter ;Tag erhöhen
rjmp Soft_110
Soft_100:
inc Shifter ;Monat erhöhen
Soft_110:
*sts {_day},Counter ;Datum speichern
*sts {_month},Shifter
ret

Daysofmonth:
.db 00, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
[end]


Die Demo (Hauptprogramm) und Include-Datei kommen in das Programme-Verzeichnis, die Lib ins LIB-Verzeichnis (ACHTUNG: Wenn da schon eine dcf77.lib enthalten ist, müßte man die Lib aus diesem Post unter anderem Namen speichern!).

Noch ein Hinweis:
Die DCF77-Decoder-Funktion ist in den aktuellen Bascom-Versionen schon enthalten, so dass du diese Lib eigentlich nicht mehr brauchst.

dl1akp
23.12.2013, 14:29
Hallo Dirk,

vielen Dank für die Hilfe.
Ich habe schon mehrere DCF77-Uhren programmiert, mit der Lib von AlBundy.
Aber da ist keine Fehlerkorrektur, oder Plausi-Kontrolle drin (oder ich verstehe sie nicht...)

Nachdem ich eine Uhr nun mit in ein Häuschen mitten im Wald genommen habe, ist dort öfter falsche Uhrzeit :-))
Manchmal springt sie einfach 2 oder drei Minuten vor, dann wieder zurück. Manchmal zeigt sie auch eine Zeit, wie: "34:75:02" als Uhrzeit.
Beides nicht sehr praktikabel...

Grüße, Andreas

PICture
23.12.2013, 14:44
Hallo!

Das scheint nicht software Problem (ausser eventuell Paritätsbits), eher zu schwaches Empfang zu sein. Ausserdem die DCF ist nur für Synchronisieren von Quarzuhren gedacht.

dl1akp
28.12.2013, 12:47
Hallo,

ja, das tut sie ja auch. Sie synchronisiert die mit Quarztakt laufende Uhr.
Hier zu Hause laufen zwei Stück, absolut fehlerfrei seit 6 Jahren.

Dann habe ich noch eine im Waldhäuschen (Stimmt, dort ist der Empfang sehr schlecht!!).
Sie synchronisiert aber jede Minute. Wenn ich nun eine Plausi-Kontrolle (oder sowas in der Art) hätte, könnte ich vlcht. nur einmal pro 12 STd. sync. machen...

MfG.

Peter(TOO)
28.12.2013, 13:08
Hallo PICture

Das scheint nicht software Problem (ausser eventuell Paritätsbits), eher zu schwaches Empfang zu sein. Ausserdem die DCF ist nur für Synchronisieren von Quarzuhren gedacht.

Ist schon ein Softwareproblem, wenn der Decoder den schlechten Empfang nicht erkennt!
Es gibt mehrere Parity-Bits im DCF-Signal.
Zudem kann man Störungen recht einfach ausfiltern, indem man immer nur das Signal in einem Zeitfenster, jede Sekunde abtastet, zumindest wen man auf das Signal synchronisiert hat. Zudem ist der Impuls immer 100 oder 200ms lang, ein Impuls von 150ms ist auch schon ein gestörtes Signal.

Allerdings sollte man keine anderen Interrupts haben, welche das Timing vom DCF-Decoder blockieren können.

MfG Peter(TOO)