Archiv verlassen und diese Seite im Standarddesign anzeigen : Library für DCF77 Dekodierung
Da ich jetzt schon öfter in meine Projekte eine Funkuhr eingesetzt habe und nicht jedes mal ellenlange Codes einfügen wollte,
habe ich mich entschlossen, das ganze mit einer Library zu vereinfachen.
Das wichtigste dabei war, jeden beliebigen Pin benutzen zu können und auch jeden beliebigen Timer.
Falls es jemand gebrauchen kann, die Library liegt zusammen mit einem Beispielprogramm im Download.
Hallo,
da der Downloadbereich sicher weniger frequentiert wird, als dieses Forum auch an dieser Stelle meinen herzlichen Dank für die Library. Funktioniert bestens. Ein paar Anregungen/Anmerkungen habe ich in einem PDF zusammengefasst. Auch eine kleine Modifikation mit Beispielprogrammen ist enthalten (als ZIP). Siehe auch Kommentar im Downloadbereich.
Download der Anmerkungen:
Edit von radbruch (24.01.2018): Link führt zu agressiver Werbung:
www.henrik-reimers.de/control/Downloads/dcf77_anmerkungen.zip
Viele Grüße
Henrik
bertl100
25.03.2006, 22:09
Hallo,
Was muss ich ändern um die Lib mit dem Mega128 zu verwenden?
MFG
Bertl
bertl100
25.03.2006, 22:12
Habs im Datenblatt gerade gefunden.
Die entsprechenden I/O Adressen sind im Datenblatt immer ganz hinten.
MFG
Bertl
Habs im Datenblatt gerade gefunden.
Die entsprechenden I/O Adressen sind im Datenblatt immer ganz hinten.
Bingo! :-). Ich habe in meine Tabelle nur bereits selbst getestete Controller aufgenommen, den Mega128 habe ich zwar da, aber noch nicht mit der Lib getestet.
BTW: Beim Tiny45 geht natürlich nur SW-Uart bzw. I2C - es muss also auf der Emfangsseite auf Plausibilität geprüft werden.
Grüße
Henrik
Hallo Henrik,
schön, dass dir meine Lib gefällt. :D
Sie war in meinem speziellem Fall dafür gedacht, vorhandene Projekte mit einer Funkuhr nachzurüsten. (z.B. Jallousiesteuerung)
Wobei es natürlich nicht nötig ist, die Softuhr permanent mit der Funkuhr zu synchronisieren.
Ich lasse 1x pro Tag die Softuhr stellen, sodass der Timer IRQ die meiste Zeit nur ein paar µs für die Softuhr benötigt.
Die 25 ms Intervall habe ich gewählt, um auch einen ungenutzten 8 Bit Timer verwenden zu können.
Deine Modifikationen machen doch eigendlich nur Sinn, wenn die Hauptanwendung, das Anzeigen der aktuellen Uhrzeit ist.
Thomas-R
30.03.2006, 21:17
Hallo Alle,
ich versuche die Lib mit einem Mega128 und einem DCF-Modul von Conrad zum Laufen zu bringen. Leider bisher ohne Erfolg. Der Pin für DCF sollte der richtige sein. Ich habe den Debug-mode eingestellt und kann die Impulse beobachten. Die Pausenzeiten sind ok. Der Zähler läuft auch im Sekundentakt bis 59. Allerdings ist die Impulslänge (bei 30) nicht im angegebenen Rahmen. Damit werden wohl auch Parity und Imp=OK nicht besser. Woran könnte das liegen?
Viele Grüße Thomas
Hallo Thomas,
es sieht so aus, als würdest du den falschen Ausgang benutzen ...
So sollte es angeschlossen werden. (ohne externen Pullupwiderstand)
Hallo Leute,
danke für die DCF-Library an W. Krüger, einfach Spitze!
@Henrik:
Eine Zusatzfrage zu deiner abgewandelten Library:
Gibt es auch eine Möglichkeit, die DCF-Zeit in TIME$ und DATE$ zu übernehmen (zu einem Zeitpunkt, den ich im Prog bestimme) OHNE einen Quarz an TOSC anzuschließen?
D.h. kriege ich die Softclock im M32 auch ohne Quarz z.B. mit einem 1Hz-Timerimpuls zum laufen und kann sie dann (z.B. jede halbe Stunde) mit der DCF-Zeit updaten?
Oder könnte man in der Interruptroutine einen Zähler bis 40 einbauen, der bei jedem 40. Aufruf die Sek. um 1 hochzählt?
Gruß Dirk
@Henrik:
Eine Zusatzfrage zu deiner abgewandelten Library:
Gibt es auch eine Möglichkeit, die DCF-Zeit in TIME$ und DATE$ zu übernehmen (zu einem Zeitpunkt, den ich im Prog bestimme) OHNE einen Quarz an TOSC anzuschließen?
D.h. kriege ich die Softclock im M32 auch ohne Quarz z.B. mit einem 1Hz-Timerimpuls zum laufen und kann sie dann (z.B. jede halbe Stunde) mit der DCF-Zeit updaten?
Oder könnte man in der Interruptroutine einen Zähler bis 40 einbauen, der bei jedem 40. Aufruf die Sek. um 1 hochzählt?
Das geht im Prinzip alles. Nur eine Fleißaufgabe, für die mir im Moment die Zeit etwas fehlt.
Um Date$ und Time$, die man dann etwas anders nennen muss, mit der Originallib von Albundy zu realisieren habe ich auf die Schnelle folgendes zusammengeschustert (der gewünschte "Universaleinsekundenzähler" ist auch drin):
'************************************************* ******************************
'* DEMO für DCF77 Library von W. Krueger *
'* leicht abgewandelt von H.Reimers 02.04.2006 *
'************************************************* ******************************
$regfile = "m32def.dat"
$crystal = 7372800
$baud = 9600
$hwstack = 64
$swstack = 64
$framesize = 64
'Config Lcdpin = Pin , Db4 = Pd.4 , Db5 = Pd.5 , Db6 = Pd.6 , Db7 = Pd.7 , _
'E = Pd.3 , Rs = Pd.2
'Config Scl = Portc.0
'Config Sda = Portc.1
'Portc.0 = 1 'Pullup Widerstand ein
'Portc.1 = 1 'Pullup Widerstand ein
'I2cinit 'I2C Initialisierung
'-------------------- Für I2C LCD und M32 Modul --------------------------------
$lib "Lcd_i2c.lib" 'i2c Treiber für das LCD
Dim _lcd_e As Byte 'Nötig für die Enable Auswahl
Const Pcf8574_lcd = 112 'Adresse des LCD-PCF
Waitms 200
_lcd_e = 128 'Für LCDs mit 1 Controller
Config Scl = Portc.0
Config Sda = Portc.1
Portc.0 = 1 'Pullup Widerstand ein
Portc.1 = 1 'Pullup Widerstand ein
I2cinit 'I2C Initialisierung
'-------------------------------------------------------------------------------
Config Lcd = 16 * 4
Config Adc = Single , Prescaler = Auto 'Für Analogtastatur
Config Rc5 = Pinc.3 'Benutzt Timer0 und INT0
'Für IR-Tastatur
'-------------------------------------------------------------------------------
$lib "dcf77_m32_A6.lib"
$external Dcf77
Declare Sub Dcf77
Config Timer0 = Timer , Prescale = 1024 'Timer für 40Hz (25ms)
Const Startwert = 76
Timer0 = Startwert
On Timer0 Tim0_isr 'Überlauf alle 25ms
Enable Interrupts
Enable Timer0
'-------------------------------------------------------------------------------
'Config Pinc.2 = 1 'Ausgang
'Beep Alias Pinc.2 'für Summer
Config Pina.6 = Input 'DCF 77 Eingang
Set Porta.6 'Pullup einschalten
Declare Sub Get_funkzeit()
Declare Sub Make_clockstrings()
Dim Status As Byte , Zaehler As Byte , Buffer As Byte , Impuls As Byte
Dim H_sek As Byte , Sekunde As Byte , T_min As Byte , T_std As Byte
Dim Minute As Byte , Stunde As Byte , Wotag As Byte , Tag As Byte
Dim Monat As Byte , Jahr As Byte , Pari As Byte , Pau As Byte , Imp As Byte
Dim Bcd_stunde As Byte
Dim Bcd_minute As Byte
Dim Bcd_sekunde As Byte
Dim Time_s As String * 10
Dim Bcd_tag As Byte
Dim Bcd_monat As Byte
Dim Bcd_jahr As Byte
Dim Date_s As String * 15
Dim Convert_strg As String * 10
Dim Counter_25ms As Word
Dim Counter_1sec As Word
'******************** HAUPTPROGRAMM ********************************************
Main:
Cls
Cursor Off
Lcd " DCF77 TEST"
Wait 5
Cls
Do
'Cls
Call Get_funkzeit()
Loop
End
'*************** ENDE HAUPTPROGRAMM ********************************************
Sub Get_funkzeit()
Call Make_clockstrings()
'Cls
Locate 1 , 2
Lcd Time_s
Print Time_s
Locate 2 , 2
If Status.3 = 1 And Status.4 = 1 Then Lcd Date_s
Locate 4 , 2
Lcd Bin(status)
'Wait 1
End Sub
'-------------------------------------------------------------------------------
Sub Make_clockstrings()
Bcd_stunde = Makebcd(stunde)
Bcd_minute = Makebcd(minute)
Bcd_sekunde = Makebcd(sekunde)
Bcd_tag = Makebcd(tag)
Bcd_monat = Makebcd(monat)
Bcd_jahr = Makebcd(jahr)
Time_s = Bcd(bcd_stunde) + ":" + Bcd(bcd_minute) + ":" + Bcd(bcd_sekunde)
Date_s = Lookupstr(wotag , Wochentag) + " " + Bcd(bcd_tag) + "." + _
Bcd(bcd_monat) + ".20" + Bcd(bcd_jahr)
End Sub
'-------------------------------------------------------------------------------
'------------------------ Interrupt Routine ------------------------------------
Tim0_isr:
Timer0 = Startwert
Incr Counter_25ms
If Counter_25ms > 39 Then
Counter_25ms = 0
Incr Counter_1sec
End If
Call Dcf77
Return
'------------------------ Daten für Wochentag ----------------------------------
Wochentag:
Data " " , "Mo" , "Di" , "Mi" , "Do" , "Fr" , "Sa" , "So"
Grüße
Henrik
Henrik, vielen Dank, da habe ich ja wieder was zum Ausprobieren!
Warum funktioniert eigentlich Albundys Lib nicht mit den internen Variablen der Softclock, also z.B. so:
copyright = W.Krueger, geändert D. Ottensmeyer
comment = DCF 77 Decoder
libversion = 1.00
date = 02.04.2006
statement = ----------------------------------
statement = muss alle 25ms ausgeführt werden !
statement = ----------------------------------
[Dcf77]
Dcf77:
.equ DCF_Port = $10 ;$10 = Pind
.equ DCF_Pin = 3 ;3 = Pin 3
.equ Imp0min = 70 ;minimale Länge des Minutenimpulses
.equ Imp1min = 6 ;minimale Länge des "1" Impulses
;alles darunter wird als "0" Impuls gewertet
.def Temp1 = r16
.def Temp2 = r17
.def Temp3 = r18
.def _min = r19
.def _hour = r20
.def Status = r21
;Bit0 = aktueller DCF Status
;Bit1 = vorheriger DCF Status
;Bit2 = Uhr synchronisieren
;Bit3 = 59 Impulse empfangen
;Bit4 = Parität OK
.def Impuls = r22
.def Zaehler = r23
.def Buffer = r24
.def Pari = r25
;------------------------------------
*lds Status,{Status} ;Status laden
rcall Softuhr ;Softuhr bearbeiten
*lds Impuls,{Impuls} ;Variablen laden
*lds Zaehler,{Zaehler}
*lds Buffer,{Buffer}
*lds Pari,{Pari}
in temp1,Dcf_Port ;DCF Port lesen
bst temp1,Dcf_Pin ;Status holen
bld Status,0 ;aktuellen Status speichern
inc Zaehler ;Impulslänge erhöhen
bst Status,0 ;akuellen Status prüfen
brts Puls20 ;Status Low -> weiter
bst Status,1 ;vorherigen Status prüfen
brtc Puls40 ;vorheriger Status Low -> Ende
ldi temp1,Imp0min ;Minutenimpuls Minimalwert laden
cp Zaehler,temp1 ;Impulslänge Minimalwert überschritten
brcs Puls10 ;nein -> weiter
*sts {Pau},Zaehler ;--------> Minutenimpulslänge speichern für Debug
clr Buffer ;Empfangspuffer löschen
clr Impuls ;Impulszähler löschen
bst Status,4 ;Parität OK ?
brtc Puls5 ;Nein -> weiter
bst Status,3 ;59 Impulse empfangen ?
brtc Puls5 ;Nein -> weiter
set
bld Status,2 ;Status Uhr synchronisieren setzen
Puls5:
clt
bld Status,3 ;Status 59 Impulse löschen
bld Status,4 ;Status Parität OK löschen
Puls10:
clr Zaehler ;Impulslänge löschen
rjmp Puls40 ;Ende
Puls20:
bst Status,1 ;vorherigen Status prüfen
brts Puls40 ;vorheriger Status Low -> Ende
ldi temp1,Imp1min ;Minimalwert für "1" Impuls laden
cp Zaehler,temp1 ;Minimalwert unterschritten ?
brcs Puls30 ;ja -> weiter
*sts {imp},Zaehler ;--------> Impulslänge Height speichern für Debug
cpi Impuls,28 ;beim Paritätsbit Min keine Negation
breq Puls25
cpi Impuls,35 ;beim Paritätsbit Std keine Negation
breq Puls25
ldi Temp1,1
eor Pari,Temp1 ;Paritätsbit Negation
Puls25:
sec ;Carry setzen ( "1" empfangen )
ror Buffer ;Carry in Empfangspuffer
inc Impuls ;Impulszähler erhöhen
rcall Auswerten ;Impulse auswerten
rjmp Puls40 ;Ende
Puls30:
*sts {imp},Zaehler ;--------> Impulslänge Low speichern für Debug
clc ;Carry löschen ( "0" empfangen )
ror Buffer ;Carry in Empfangspuffer
inc Impuls ;Impulszähler erhöhen
rcall Auswerten ;Impulse auswerten
Puls40:
bst Status,0 ;aktuellen Status holen
bld Status,1 ;Status speichern
*sts {Status},Status ;Variablen wieder speichern
*sts {Impuls},Impuls
*sts {Zaehler},Zaehler
*sts {Buffer},Buffer
*sts {Pari},Pari
ret
;-------------------------------------------------------------------------------
Softuhr:
*lds Temp1,{H_Sek}
*lds Temp2,{_sec}
*lds _min,{_min}
*lds _hour,{_hour}
bst Status,2 ;Status Uhr synchronisieren ?
brtc Soft10 ;nein -> weiter Softuhr
clt
bld Status,2 ;Status Synchron löschen ?
clr Temp1 ;Hundertstel löschen
clr Temp2 ;Sekunde löschen
*lds Temp3,{T_Min}
mov _min,Temp3 ;Minute auf empfangene Minute
*lds Temp3,{T_Std}
mov _hour,Temp3 ;Stunde auf empfangene Stunde
rjmp Soft20 ;empfangene Zeit übernehmem
Soft10:
inc Temp1 ;Hundertstel Sek erhöhen
cpi Temp1,40 ;1000ms erreicht ?
brne Soft20 ;nein -> Ende
clr Temp1 ;Hundertstel Sek löschen
inc Temp2 ;Sekunde erhöhen
cpi Temp2,60 ;60 Sekunden erreicht ?
brne Soft20 ;nein -> Ende
clr Temp2 ;Sekunde löschen
inc _min ;Minute erhöhen
cpi _min,60 ;60 Minuten erreicht ?
brne Soft20 ;nein -> Ende
clr _min ;Minute löschen
inc _hour ;Stunde erhöhen
cpi _hour,24 ;24 Stunden erreicht ?
brne Soft20 ;nein -> Ende
clr _hour ;Stunde löschen
Soft20:
*sts {H_Sek},Temp1 ;Basic Variablen mit empfangenen
*sts {_sec},Temp2 ;Werten laden
*sts {_min},_min
*sts {_hour},_hour
ret
;-------------------------------------------------------------------------------
Auswerten:
cpi Impuls, 21 ;21. Impuls
brne Aus10 ;nein -> weiter
clr Buffer
clr Pari
Aus10:
cpi Impuls, 28 ;28. Impuls
brne Aus15 ;nein -> weiter
lsr Buffer ;Buffer 1x schieben, da Minute nur 7 Bit
rcall Bcd2dez ;in Dezimal wandeln
*sts {T_Min},Buffer ;Temp Minute schreiben
clr Buffer
Aus15:
cpi Impuls, 29 ;Minuten Parität
brne Aus20
clr Temp3
bst Buffer,7 ;Paritätsbit selektieren
bld Temp3,0 ;Paritätsbit in Temp3 Bit0 kopieren
cp Temp3,Pari ;Parität überprüfen
brne Aus26 ;Fehler -> Ende
clr Pari
clr Buffer
Aus20:
cpi Impuls, 35 ;35. Impuls
brne Aus25 ;nein -> weiter
lsr Buffer ;Buffer 2x schieben, da Stunde nur 6 Bit
lsr Buffer
rcall Bcd2dez ;in Dezimal wandeln
*sts {T_Std},Buffer ;Temp Stunde schreiben
clr Buffer
Aus25:
cpi Impuls, 36 ;Stunden Parität
brne Aus30
clr Temp3
bst Buffer,7 ;Paritätsbit selektieren
bld Temp3,0 ;Paritätsbit in Temp3 Bit0 kopieren
cp Temp3,Pari ;Parität überprüfen
breq Aus27 ;Pari OK -> weiter
Aus26:
ret ;Fehler -> Ende
Aus27:
set ;T-Bit setzen
bld Status,4 ;Bit4 Status setzen (Parität)
clr Buffer
Aus30:
cpi Impuls,42 ;42. Impuls
brne Aus40
lsr Buffer ;Buffer 2x schieben, da Tag nur 6 Bit
lsr Buffer
rcall Bcd2dez ;in Dezimal wandeln
*sts {_day},Buffer ;Tag schreiben
clr Buffer
Aus40:
cpi Impuls,45 ;45. Impuls
brne Aus50
lsr Buffer ;Buffer 5x schieben, da Wochentag nur 3 Bit
lsr Buffer
lsr Buffer
lsr Buffer
lsr Buffer
rcall Bcd2dez ;in Dezimal wandeln
*sts {Wotag},Buffer ;Wochentag schreiben
clr Buffer
Aus50:
cpi Impuls,50 ;50. Impuls
brne Aus60
lsr Buffer ;Buffer 3x schieben, da Monat nur 5 Bit
lsr Buffer
lsr Buffer
rcall Bcd2dez ;in Dezimal wandeln
*sts {_month},Buffer ;Monat schreiben
clr Buffer
Aus60:
cpi Impuls,58 ;58. Impuls
brne Aus70
rcall Bcd2dez ;in Dezimal wandeln
*sts {_year},Buffer ;Jahr schreiben
clr Buffer
Aus70:
cpi Impuls,59 ;59. Impuls
brne Aus80
set ;T-Bit setzen
bld Status,3 ;Bit3 Status setzen (59 Impulse)
Aus80:
cpi Impuls,60 ;bei mehr als 59 Impulsen (Störimpulse)
brne Aus90
clt ;T-Bit löschen
bld Status,3 ;Bit3 Status löschen (59 Impulse)
bld Status,4 ;Bit4 Status löschen (Parität)
Aus90:
ret
;-------------------------------------------------------------------------------
Bcd2dez:
mov Temp1,Buffer
andi Temp1,$0F
Bcd10:
subi Buffer,$10
brcs Bcd20
subi Temp1,$F6
rjmp Bcd10
Bcd20:
mov Buffer,Temp1
ret
[end]
Natürlich habe ich die Softclock im Prog konfiguriert.
Funktioniert aber leider nicht so, wie ich mir das vorgestellt hatte (nämlich gar nicht!).
Alternativ hatte ich schon Versuche mit dem CONFIG Clock = User gemacht, aber auch noch nicht sehr erfolgreich.
Ich will ja eigentlich die BASCOM-Softclock mit DATE$ und TIME$ (ohne Uhrenquarz) nutzen und sie bei Bedarf (bestimme ich selbst, wann ich Bedarf habe!) mit der DCF-Zeit updaten.
Naja, ich muss halt 'mal weiter probieren. Vielleicht geht's ja irgendwie.
Vielen Dank nochmal!
Gruß Dirk
Hallo Dirk,
warum sollte die Lib nicht auch mit der Bascom Softclock funktionieren ?
Ich gehe mal davon aus, dass die Variablen _sec, _min u.s.w. dezimal vorliegen müssen und nicht BCD ???
Dann sollte diese Lib funktionieren.
Natürlich vorher in Bascom mit "Config Clock=Soft" die entsprechenden Variablen initialisieren.
Ich kann es leider nicht testen, da ich im Moment kein DCF-Modul zur Verfügung habe.
Hallo,
ohne Uhrenquarz kann Bascoms Softclock einfach nicht funktionieren. Alle Timings sind auf die 32,schlagmichtot KHz Frequenz zugeschnitten.
Mit Uhrenquarz habe ich das in der Variation ja schon vorgeführt. Zu beachten ist allerdings, daß der von Bascom benutzte asynchrone Timer2 mit seinem Interrupt während der DCF77-Synchronisation disabled werden muss, sonst kann es Kuddelmuddel geben.
Grüße
Henrik
Thomas-R
02.04.2006, 20:59
Danke Albundy,
es funktioniert tadellos. Ich wäre nie auf invertiert gekommen!
Gruß Thomas!
Hallo Henrik,
ohne Uhrenquarz kann Bascoms Softclock einfach nicht funktionieren. Alle Timings sind auf die 32,schlagmichtot KHz Frequenz zugeschnitten.
Das ist genau mein Problem! Aber ich habe die Antwort noch nicht so klar wie du.
Lt. BASCOM-Anleitung werden die Variablen _sec ... durch CONFIG CLOCK = ... dimensioniert und DATE$, TIME$ angelegt. Ich soll auch z.B. _sec ändern können, was in TIME$ berücksichtigt wird.
Dabei ist der asynchrone Timer doch erst mal unwichtig: Die Variablen gibt es dann ja und den Timer kann ich erstmal "disablen".
Und die Variablen möchte ich nutzen, damit ich normal in BASCOM auf DATE$ und TIME$ zugreifen kann. Zur Not auch in der Form, dass ich _sec selbst in einem Unterprogramm jede Sekunde hochzähle.
Geht das wirklich nicht? :-s
Gruß Dirk
Hallo albundy,
warum sollte die Lib nicht auch mit der Bascom Softclock funktionieren ?
Leider klappt's (bei mir) nicht. :(
Ich versuch's weiter.
Gruß Dirk
Lt. BASCOM-Anleitung werden die Variablen _sec ... durch CONFIG CLOCK = ... dimensioniert und DATE$, TIME$ angelegt. Ich soll auch z.B. _sec ändern können, was in TIME$ berücksichtigt wird.
Dabei ist der asynchrone Timer doch erst mal unwichtig: Die Variablen gibt es dann ja und den Timer kann ich erstmal "disablen".
Und die Variablen möchte ich nutzen, damit ich normal in BASCOM auf DATE$ und TIME$ zugreifen kann.
Das ist korrekt ! Und genau so, habe ich dich auch verstanden.
Das die Variablen der Softuhr in Bascom von der Lib versorgt werden müssen (da kein Uhrenquarz angeschlossen wird) ist ja klar.
Und dabei den OVF2 zu disablen ist auch eine gute Idee !!!
Ich verstehe aber nicht, das die geänderte Lib so nicht funktioniert ???
Alle Variablen werden doch durch die Lib entsprechend beschrieben.
Wenn es dir nur um die formatierte Ausgabe von Time$ und Date$ geht, kannst du dir doch auch eine eigene Funktion dafür schreiben.
Hallo albundy,
also... mit deiner Lib wird die Zeit (in DATE$ und TIME$) durch DCF einmal aktualisiert, soll dann aber ja selbst weiterlaufen.
Das passiert aber nicht, sondern die Zeit steht auf der aktualisierten DCF-Zeit fest.
Eine eigene Anzeige für DATE$ und TIME$ habe ich.
Übrigens: Ich meine ja nicht deine Original-Lib mit Demos, die bei mir super funktionieren!
Gruß Dirk
Hallo albundy,
also... mit deiner Lib wird die Zeit (in DATE$ und TIME$) durch DCF einmal aktualisiert, soll dann aber ja selbst weiterlaufen.
Das passiert aber nicht, sondern die Zeit steht auf der aktualisierten DCF-Zeit fest.
Eine eigene Anzeige für DATE$ und TIME$ habe ich.
Ja, wie soll sie den auch weiterlaufen, ohne getaktet zu werden? Nimm doch einfach die Original-Library von Albundy, bastele date$ und time$ selbst (wie in meinem oben geposteten Beispiel die SUB "Makeclockstrings()" ) und gut isses. Ich schreibe nicht umsonst, daß sich Modifikationen eher für den fortgeschrittenen Anwender eignen.
Grüße
Henrik
Hallo Henrik,
Ja, wie soll sie den auch weiterlaufen, ohne getaktet zu werden?
Das habe ich schon verstanden. Meine Frage ist eigentlich, wie ich sie wieder "takten" kann. Bei der Original-Lib von albundy wird ja auch seine Softclock (mit anderen Variablen) "getaktet" (bzw. in der Interruptroutine hochgezählt), das möchte ich mit der Softclock auch machen.
Ich schreibe nicht umsonst, daß sich Modifikationen eher für den fortgeschrittenen Anwender eignen.
Ich lerne gern und werde dann zum fortgeschrittenen Anwender.
Gruß Dirk
Hallo Henrik,
Ja, wie soll sie den auch weiterlaufen, ohne getaktet zu werden?
Das habe ich schon verstanden. Meine Frage ist eigentlich, wie ich sie wieder "takten" kann.
Ganz einfach, indem du endlich den Uhrenquarz an TOSC1 und TOSC" hängst. Nur und ausschließlich damit funktioniert Bascoms Softclock. Wie oft denn noch?
Bei der Original-Lib von albundy wird ja auch seine Softclock (mit anderen Variablen) "getaktet" (bzw. in der Interruptroutine hochgezählt), das möchte ich mit der Softclock auch machen.
Na die braucht und bekommt ja auch brav ihren 40Hz Takt via Interrupt. Das bedeutet gleichzeitig, daß bei Frequenzen über 8 Mhz zwingend der (wertvolle) 16bit Timer1 benutzt werden muss. Der Vorteil der Nutzung des langsamen Uhrenquarzes bei Bascoms Softclock im asynchronen Modus liegt darin, daß der Interrupt nur 1x pro Sekunde hereinplatzt, die Interruptroutine aber mit voller Prozessorgeschwindigkeit abgearbeitet wird.
Grüße
Henrik
Hallo Henrik,
verstanden! War sehr deutlich.
(Dabei will ich ja eigentlich nur die [highlight=red:fd757fffd3]Variablen[/highlight:fd757fffd3] der Softclock und eigentlich nicht den Takt (32768Hz Quarz an TOSC) nutzen. Aber ich will hier 'mal nicht weiter nerven und mache noch ein paar Versuche, bevor ich aufgebe.)
Also Henrik, keep cool und danke für die Hilfe!
Gruß Dirk
Hallo Dirk,
verstanden! War sehr deutlich.
böse gemeint war das nicht, das Thema ist nur komplex und mir fehlt die Zeit das alles im einzelnen aufzudröseln :-).
(Dabei will ich ja eigentlich nur die [highlight=red:d9beb835f0]Variablen[/highlight:d9beb835f0] der Softclock und eigentlich nicht den Takt (32768Hz Quarz an TOSC) nutzen. Aber ich will hier 'mal nicht weiter nerven und mache noch ein paar Versuche, bevor ich aufgebe.)
Na ja, alleine mit den Variablen wirst Du nicht glücklich. Mit den Variablen soll ja etwas passieren. Date$ und Time$ sollen berechnet werden, _min, _sec, _hour sollen weiterzählen usw. Sonst passiert genau das, was Du festgestellt hast: Es wird einmal auf den eingelesenen Stand gebracht und da bleibt es dann, wenn nicht fortlaufend aktualisiert wird.
Als Hilfe zur Selbsthilfe versuche ich kurz zu erklären. was im Groben bei Config Clock passiert:
1) Es werden die Variablen angelegt.
2) Es wird die datetime.lib eingebunden.
Abhängig von soft oder user wird nun entweder alles in datetime erledigt (im Sekundentakt) oder bei user werden die Label:
getdatetime:
settime:
setdate:
im Hauptprogramm oder einer weiteren Lib angesprungen. Auch das passiert im Sekundentakt, den Timer2 mit dem von Dir so ungeliebten Uhrenquarz zur Verfügung stellt.
Der Programmierer muss nun dafür sorgen, daß diese Label entsprechende Subroutinen enthalten. Es müssen nur die Uhrzeit und das Datum (dezimal) zur Verfügung stehen, den Rest errechnet wieder die datetime.lib.
Aus den oben genannten Voraussetzungen geht hervor, daß die DCF77 Routine naturlich laufen müsste, damit sie datetime die entsprechenden aktuellen Informationen geben kann.
Abgesehen davon, daß man für effizientes Arbeiten die DCF77.lib nicht unerheblich umschreiben müsste, hätten wir auch das Ziel des weniger störenden Interrupts nicht erreicht. Im Gegenteil: Statt eines Interrupts funken nun zwei in der Gegend herum.
Bei meiner Modifikation umgehe ich das Problem, indem ich einfach nach erfolgter Synchronisation die Daten an Bascoms Softclock die Daten übergebe, den DCF77 Timerinterrupt abschalte und den Softclockinterrupt einschalte. Von nun an rechnet brav Softclock mit all seinen Vorteilen, bis ich wieder aktualisieren möchte (wenn Bedingung erfüllt - wieder Timer umschalten, Synchronisieren, Softclock aktualisieren, wieder Timer umschalten).
Wenn Du nun nur die zusätzliche Funktionalität der Softclockvariablen haben möchtest, musst Du das im Hauptprogramm selbst nachbilden. Im DCF77 Interrupt geht das nicht, der würde zu lang.
Hoffe das macht die Sache etwas klarer.
BTW: Du nervst nicht, nur muss ich hier mit einem Projekt fertigwerden (auch so eine Fleißarbeit) von dem dann mehrere Schulklassen abhängen... Die Jungs und Mädels würden es mir recht übelnehmen, wenn ich sie nicht rechtzeitig mit Hard- und Software füttern würde :-).
Viele Grüße
Henrik
Hallo Henrik und albundy,
so, nach einer durchgemachten Nacht und nachdem ich heute tagsüber 2x von meinem Chef am Arbeitsplatz geweckt werden mußte, funktioniert es jetzt.
Ergebnis: Die Softclock läuft jetzt nachweisbar (Ausgabe von DATE$ und TIME$) permanent und OHNE den Uhrenquarz. Zeit und Datum sind in BASCOM jederzeit abfragbar.
Das wollte ich wissen!!! O:)
Ich nehme dafür die DCF77_soft.lib von albundy!!
@Henrik: Es ist mir klar, daß ein 40Hz-Interrupt für den Dauerbetrieb der Softclock mit DCF-Aktualisierung eine hohe Ressource ist. Das geht sicher nur, wenn die anderen Aufgaben des M32 das zulassen. Bei mir ist das der Fall. Mir ist auch klar, dass ein Uhrenquarz wesentlich besser wäre. Aber man macht im Leben viele sinnlose Dinge (heiraten o.ä.).
Gruß und vielen Dank an albundy für die lib!
Dirk
N ábend zusammen
als absoluter Neuling habe ich schon viel gelesen und auch schon einiges ausprobiert, einiges funktionierte, anderes nicht.
Da ich gerade erst das gehen lerne, von laufen kann noch nicht die Rede sein, möchte ich hier zum Thema mal was fragen.
Wollte als Projekt eine Uhr mit DCF 77 programmieren.Habe mir das Programm nebst Lib hier runtergeladen.
Meine Frage in der Lib wird der Pin A7 als DCF Eingang gesetzt, ich arbeite mit einem Atmega 8L dort gibts ja keine A Ports also wollte ich den Port C5 verwenden.Bei stöbern im Netz habe ich gefunden das $15 für die C Ports in der Lib steht muß, nicht $19 wie für A. Ist das richtig ??
Habe die Lib dann auf $15 Port 5 umgeschrieben. Ebenfalls im Programm den Port auf PinC.5 gesetzt, und reingeladen.
Die Uhreit fängt wie immer normal an zu laufen, jedoch findet keine Einstellung via DCf statt. Ach ja DCF Modul von Reichelt, "Ein" auf GND damit der RX immer läuft.Habe an Pin C5 ja statisch 5Volt durch den Befehl =1 im Programm, dagegen arbeitet jetzt das DCF Signal.Ist da der Fehler zu suchen, oder hat jemand eine Idee wo es klemmt.
Habe den Programmteil Debuggen auch mal aktiviert, Pausenlänge und Impuls bleiben auf 0 stehen, kein Signal also.
Ich hoffe ich habe das richtig verstanden, das das DCF Signal die Uhr stellt, oder wird der Impuls nur zum synchronisieren benutzt?
Vielen Dank für Eure Antworten
HP
N ábend zusammen
Meine Frage in der Lib wird der Pin A7 als DCF Eingang gesetzt, ich arbeite mit einem Atmega 8L dort gibts ja keine A Ports also wollte ich den Port C5 verwenden.Bei stöbern im Netz habe ich gefunden das $15 für die C Ports in der Lib steht muß, nicht $19 wie für A. Ist das richtig ??
Ne, das ist schon mal falsch. Die betreffenden Zeilen müssten Für Portc.5 für den Mega8 so aussehen:
[Dcf77]
Dcf77:
.equ DCF_Port = $13 ;$19 = Pinc - gewünschter Port
.equ DCF_Pin = 5 ;5 = Pin 5 - gewünschter Pin des Ports
Versuche es mal damit :-).
Grüße
Henrik
Hallo Henrik
Erstmal vielen Dank für deine Info, Du hattest recht 15 war nicht richtig, 13 wenn auch sonst eine nicht beliebte Zahl war in diesem Fall die Richtige.
Damit klappte es auf Anhieb, Signale werden empfangen ,...NUR
die Einstellung im Programm Zeile 29 diesen Befehl muß ich abstellen, sonst arbeitet das DCF Signal gegen den Pullupwiderstand, soll heissen, am IC Port liegen 5V an, gegen die die 4 Volt von DCF nichts ausrichten können.
Den Port nicht mit Pull Up hochgelegt funktioniert.
Werde jetzt mal den Debug beenden und sehen was die Uhr so zeigt.
Danke.
HP
Ja da bin ich schon wieder, nun habe ich die Uhr 5 Minuten laufen lassen,aber die korrekte Uhrzeit wird nicht angezeigt, sollte sie das machen ??
Das einzig komische was sich ergeben hat ist, das nach ca 4 Minuten eine 3 Sekundenstelle aufgetaucht ist., sowas wie ne zehntelsekunden Stelle.Die Null steht aber fest
Nach 8 Minuten taucht in Zeile 2 das Datum ?? oder was es sein Soll auf, also haben wir heute den 45.25.20165, welch ein Zeitsprung....
Die Uhrzeit bleibt davon unberührt, nichts neues dort
Vielleicht hat ja jemand dazu eine Idee.
HP
Hallo!
Richtigen Ausgang genommen (invertiert)?
Passenden Timer gewählt?
Mit welchem Quarz arbeitest Du?
Timerprescaler im Hauptprogramm richtig angepasst?
Grüße
Henrik
Moin Henrik
kam erst heute morgen bzw mittag zum lesen deiner Mail.
Also zum Thema Ausgang, welchen Ausgang meinst du, den vom DCF Empfänger?? der hat ja nur einen, oder spezifiziere mal den Ausgang.
Invertiert bezieht sich auf welchen Ausgang oder meinst du den Eingangsport am Chip
Ich benutze den Standardquarz der heisst R036JAB6a, denke das ist der 3,686400Mhz der beim Experimentierboard dabei ist.
Prescaler steht im Programm auf 1024,
hm im Orginalprogramm ist ein anderer Quarz drin, vielleicht passt der Prescalerwert nicht zu meiner Quarzfrequenz??
HP
Hallo HP,
Ich benutze den Standardquarz der heisst R036JAB6a, denke das ist der 3,686400Mhz der beim Experimentierboard dabei ist.
Prescaler steht im Programm auf 1024
das kannst du so lassen. Nur "Const Startwert=158" musst du ändern auf 166.
Invertiert bezieht sich auf welchen Ausgang ...
das ist der Ausgang vom Reichelt-Modul, und der ist schon invertiert.
Mit dem geänderten Startwert müsste es dann funktionieren.
Hallo Al
ok habe den Wert mal auf die von dir angesagten 166 gestellt.
Mal sehen was passiert.
Eine Frage habe ich aber noch, sollte wenn es jetzt mit 166 funktioniert, die Uhrzeit auf den richtigen Wert gestellt werden ?? habe beim testen hier schon die merkwürdigsten Datumanzeigen gehabt, aber die Uhrzeit ist immer weitergelaufen, soll heissen, nach dem einschalten mit einer Sekunde angefangen und dann immer weiter fortlaufend hochgezählt., nicht nahgestellt.
So habe das Signal vom DCF mal an C5 kontrolliert, ist also da, aber nach 8 Minuten keine Zeitanpassung oder Datumsanzeige.
Habe heute mittag mal nach Henriks Liste gerechnet, in seiner Tabelle gibts ja leider für den 8 mit 3,6Mhz keine Werte, aber Prescale 512 wird schon vom Compiler verboten, und bei 1024 , Startwert 114 hatte ich zwar empfangsänderungen auf den Display aber alles ziemlich wirres Zeug.
Im Programm steht Zeile 56 das der Doppelpunkt, Welcher, sind ja genug davon da, blinken soll.Ist dies eine Empfangskontrolle??
Komisch ist bei mir ... meinem Moad, das zu unbestimmten Zeiten hinter der Einersekunde plötzlich eine Nul fest steht.Manchmal ist sie schon nach 2-4 Minuten da, andere Male kommt sie garnicht.????
Weiss jemand noch Rat.
HP
wassermann
06.04.2006, 07:13
Hallo,
hab's vielleicht falsch verstanden oder nicht kapiert.
Bei mir wird nämlich nur synchronisiert und dann Ebbe ....
Ich hab mir auch schon _Hour o.ä. per print geschickt, aber keine Änderung der Werte.
Die Lib ist doch erstmal zuständig für die "DCF77".
Und im Beispiel von hrei wird per Config Clock = Soft dafür gesorgt, dass die entsprechenden Variablen (Time$, _Hour, usw.) initialisiert werden. Richtig?
Timer 0 läuft durch Prescaler und Startwert.
Aber wie läuft Timer 2? Der sollte sich doch um den sec-Takt kümmern?(P.S.: Ich hab nen Quarz an TOSC1/2: 7,3728MHz). Muss ich die DateTime.Lib noch extra einbinden, oder wird das durch Config Clock gemacht?
Natürlich sollt's auch per Timer0 bis 40 zählen funktionieren (Bsp von hrei).
Danke im voraus.
Aber wie läuft Timer 2? Der sollte sich doch um den sec-Takt kümmern?(P.S.: Ich hab nen Quarz an TOSC1/2: 7,3728MHz). Muss ich die DateTime.Lib noch extra einbinden, oder wird das durch Config Clock gemacht?
Natürlich sollt's auch per Timer0 bis 40 zählen funktionieren (Bsp von hrei).
1) Es muss nichts zusätzlich eingebunden werden, das macht Config Clock.
2) Der Uhrenquarz muss 32768 kHz haben. Warum? Weil 32768/128/256=1.
3) Bitte, bitte, das ist kein Stabilbaukasten. Bei Unklarheiten hilft oft das Lesen der Bascom Hilfe weiter :-).
Grüße
Henrik
@HP
ok habe den Wert mal auf die von dir angesagten 166 gestellt.
Mal sehen was passiert.
und bei 1024 , Startwert 114 hatte ich zwar empfangsänderungen auf den Display aber alles ziemlich wirres Zeug.
hasst du überhaupt eine Ahnung was du da machst ???
Lies dir unbedingt mal in der Hilfe oder im Wissensbereich etwas über Timer durch.
Dort wird auch erklärt, was es mit dem "Prescale" auf sich hat und welche Werte überhaupt möglich sind.
Wenn der Timer nicht 100% stimmt, kommt eben nur "wirres Zeug" heraus.
So habe das Signal vom DCF mal an C5 kontrolliert, ist also da, aber nach 8 Minuten keine Zeitanpassung oder Datumsanzeige.
das sagt doch überhaupt nichts über die Empfangsqualität der Impulse aus. Deshalb habe ich für Debugzwecke "Imp" und "Pau" eingebaut.
Der Wert "Imp" muss immer zwischen 2 und 8 liegen.
Im Programm steht Zeile 56 das der Doppelpunkt, Welcher, sind ja genug davon da, blinken soll.Ist dies eine Empfangskontrolle??
If H_sek > 20 Then 'Doppelpunkt blinken lassen
Locate 1 , 12
Lcd " "
End If
H_sek steht für Hundertstel Sekunde.
Bei Werten > 20 ( das entspricht 20*25 mS = 0,5 Sekunde) soll der Doppelpunkt an der Position 12 (Zeile1) gelöscht werden.
Die übrige Zeit wird er angezeigt.
Sorry, aber welcher das ist, findest du auch allein heraus ...
N´Abend
also als großer James Dean Fan würde ich jetzt sagen "denn sie wissen nicht..." aber nun, war vor meiner Zeit.
Sie funktioniert,!! In einigen Mails zuvor sprachen wir über das Signal vom DCF Empfänger.Daraufhin erwähnte ich das ich den Eingangsport bei mir nicht aktiv 1 beschalten konnte, weil dann 5 Volt vom Kontroller auf die 4,5 Volt vom DCF trafen. Nun habe ich mir das mal genauer angeschaut, und mir fiel noch der Satz ein, das Signal ist invertiert.
Moment mal, dann muß ja, habe nun einen BC107 zum invertieren verwendet, den Port auf aktiv 1 sprich 5 Volt gelegt, eine halbwegs vernüntige Empfangsposition gesucht, und im Debug die Signale kontrolliert. Und siehe da, alles so wie´s beschrieben wurde.
Danke für eure Ausdauer.
HP
Hallo albundy,
noch eine Frage zu deiner Dcf77_soft.lib.
Könnte man dort ein Flag ergänzen, dass in BASCOM als "DCF-Signal liegt an!" gelesen werden kann. Das wäre nicht identisch mit Status.2, sondern wäre schon 1, wenn einige korrekte Einsen und Nullen empfangen wurden oder so. Fertige DCF-Module oder RTCs haben ja auch so ein Bit für DCF-Empfang ist vorhanden. Wie machen die das?
Gruß Dirk
Hallo Dirk,
eigendlich war die Dcf77_soft.lib nur eine Notlösung für dich, die ich nicht weiter vervollständigen wollte.
... wäre schon 1, wenn einige korrekte Einsen und Nullen empfangen wurden oder so.
ab wann sollte denn das Flag gesetzt werden ?
im Moment wird das erste Flag ( Status.4 ) bei korrekter Parität von Stunde und Minute gesetzt. ( in der 36. Sekunde )
Fertige DCF-Module oder RTCs haben ja auch so ein Bit für DCF-Empfang ist vorhanden
ein Empfang ist ja auch schon vorhanden, wenn Störimpulse empfangen werden, die nicht in der Tolleranz vom DCF Signal liegen.
Hallo albundy,
o.k. kapiert. Ich probiere 'mal etwas mit dem Status.4 herum.
Auf der Basis von deiner Dcf77_soft.lib habe ich für meine Zwecke eine eigene Version geschrieben, die in Status noch zwei Bits ergänzt für "Uhr wurde 1x nach DCF gestellt" und für "Uhr nach DCF stellen EIN". Mit dem letzten Bit stoppe ich das Stellen der Uhr, sie läuft dann intern so lange weiter, bis ich das Bit im BASIC-Programm wieder auf 1 setze.
Mit dem anderen Bit speichere ich Status.2 dauerhaft, damit ich feststellen kann, ob die Uhr einmal mit DCF gestellt wurde.
Ich habe auch das Umspringen von 23.59.59 auf einen neuen Tag, Monat und Jahr eingefügt.
Jetzt läuft alles bei ersten Tests ganz gut.
Vielen Dank nochmal für die Unterstützung.
Gruß Dirk
Hallo Leute,
jetzt ist meine Version der Dcf77_soft.lib fertig geworden und getestet.
Die 1. Version stammt von albundy.
Was ich wollte: Die Softclock von Bascom nutzen ohne Uhrenquarz an TOSC1/2 mit der Möglichkeit, ein Aktualisieren der Softclock durch DCF zu machen (z.B. jede Stunde oder 1x am Tag ...).
Dazu habe ich die dcf77_soft.lib von albundy um folgende Funktionen erweitert:
1. Status-Bit 5 bedeutet: Uhr wurde 1x nach DCF gestellt. Das Bit bleibt high, bis das Basic-Programm es auf low setzt oder bis der Wochentag auf 29, 30 oder 31 wechselt (weil die lib nicht weiß, wieviele Tage der Monat hat und deshalb das Datum evtl. falsch ist).
2. Status-Bit 7 bedeutet: Uhr kann nach DCF gestellt werden. Ist das Bit low, läuft nur die Softclock intern weiter ohne DCF-Empfang. Das Bit muss vom Basic-Programm gestellt werden.
3. Die Softclock zählt jetzt auch das Datum (Tag, Monat, Jahr) mit korrektem Überlauf weiter. Status.5 wird gelöscht, wenn Tag 29, 30 oder 31 erreicht ist, damit kann dann das Basic-Programm z.B. den DCF-Empfang einschalten (Status.7 = 1), um das Datum neu zu holen.
Hier die lib:
copyright = W.Krueger
comment = DCF 77 Decoder
libversion = 2.00 (D. Ottensmeyer)
date = 09.04.2006
statement = ----------------------------------
statement = muss alle 25ms ausgeführt werden !
statement = ----------------------------------
[Dcf77]
Dcf77:
.equ DCF_Port = $10 ;$10 = Pind
.equ DCF_Pin = 3 ;3 = Pin 3
.equ Imp0min = 70 ;minimale Länge des Minutenimpulses
.equ Imp1min = 6 ;minimale Länge des "1" Impulses
;alles darunter wird als "0" Impuls gewertet
.def Temp1 = r16
.def Temp2 = r17
.def Temp3 = r18
.def Minute = r19
.def Stunde = r20
.def Status = r21
;Bit0 = aktueller DCF Status
;Bit1 = vorheriger DCF Status
;Bit2 = Uhr synchronisieren
;Bit3 = 59 Impulse empfangen
;Bit4 = Parität OK
;Bit5 = Uhr wurde 1x gestellt
;Bit7 = Uhr nach DCF stellen
.def Impuls = r22
.def Zaehler = r23
.def Buffer = r24
.def Pari = r25
;------------------------------------
*lds Status,{Status} ;Status laden
rcall Softuhr ;Softuhr bearbeiten
bst Status,7 ;Status Uhr nach DCF stellen ?
brts Puls0 ;ja -> weiter
*sts {Status},Status
ret
Puls0:
*lds Impuls,{Impuls} ;Variablen laden
*lds Zaehler,{Zaehler}
*lds Buffer,{Buffer}
*lds Pari,{Pari}
in temp1,Dcf_Port ;DCF Port lesen
bst temp1,Dcf_Pin ;Status holen
bld Status,0 ;aktuellen Status speichern
inc Zaehler ;Impulslänge erhöhen
bst Status,0 ;akuellen Status prüfen
brts Puls20 ;Status Low -> weiter
bst Status,1 ;vorherigen Status prüfen
brtc Puls40 ;vorheriger Status Low -> Ende
ldi temp1,Imp0min ;Minutenimpuls Minimalwert laden
cp Zaehler,temp1 ;Impulslänge Minimalwert überschritten
brcs Puls10 ;nein -> weiter
*sts {Pau},Zaehler ;--------> Minutenimpulslänge speichern für Debug
clr Buffer ;Empfangspuffer löschen
clr Impuls ;Impulszähler löschen
bst Status,4 ;Parität OK ?
brtc Puls5 ;Nein -> weiter
bst Status,3 ;59 Impulse empfangen ?
brtc Puls5 ;Nein -> weiter
set
bld Status,2 ;Status Uhr synchronisieren setzen
Puls5:
clt
bld Status,3 ;Status 59 Impulse löschen
bld Status,4 ;Status Parität OK löschen
Puls10:
clr Zaehler ;Impulslänge löschen
rjmp Puls40 ;Ende
Puls20:
bst Status,1 ;vorherigen Status prüfen
brts Puls40 ;vorheriger Status Low -> Ende
ldi temp1,Imp1min ;Minimalwert für "1" Impuls laden
cp Zaehler,temp1 ;Minimalwert unterschritten ?
brcs Puls30 ;ja -> weiter
*sts {imp},Zaehler ;--------> Impulslänge Height speichern für Debug
cpi Impuls,28 ;beim Paritätsbit Min keine Negation
breq Puls25
cpi Impuls,35 ;beim Paritätsbit Std keine Negation
breq Puls25
ldi Temp1,1
eor Pari,Temp1 ;Paritätsbit Negation
Puls25:
sec ;Carry setzen ( "1" empfangen )
ror Buffer ;Carry in Empfangspuffer
inc Impuls ;Impulszähler erhöhen
rcall Auswerten ;Impulse auswerten
rjmp Puls40 ;Ende
Puls30:
*sts {imp},Zaehler ;--------> Impulslänge Low speichern für Debug
clc ;Carry löschen ( "0" empfangen )
ror Buffer ;Carry in Empfangspuffer
inc Impuls ;Impulszähler erhöhen
rcall Auswerten ;Impulse auswerten
Puls40:
bst Status,0 ;aktuellen Status holen
bld Status,1 ;Status speichern
*sts {Status},Status ;Variablen wieder speichern
*sts {Impuls},Impuls
*sts {Zaehler},Zaehler
*sts {Buffer},Buffer
*sts {Pari},Pari
ret
;-------------------------------------------------------------------------------
Softuhr:
*lds Temp1,{H_Sek}
*lds Temp2,{_sec}
*lds Minute,{_min}
*lds Stunde,{_hour}
bst Status,2 ;Status Uhr synchronisieren ?
brtc Soft10 ;nein -> weiter Softuhr
clt
bld Status,2 ;Status Synchron löschen
bst Status,7 ;Status Uhr nach DCF stellen ?
brtc Soft10 ;nein -> nicht neu stellen
set
bld Status,5 ;Status Uhr 1x gestellt setzen
clr Temp1 ;Hundertstel löschen
clr Temp2 ;Sekunde löschen
*lds Minute,{T_Min} ;Minute auf empfangene Minute
*lds Stunde,{T_Std} ;Stunde auf empfangene Stunde
rjmp Soft20 ;empfangene Zeit übernehmen
Soft10:
inc Temp1 ;Hundertstel Sek erhöhen
cpi Temp1,40 ;1000ms erreicht ?
brne Soft20 ;nein -> Ende
clr Temp1 ;Hundertstel Sek löschen
inc Temp2 ;Sekunde erhöhen
cpi Temp2,60 ;60 Sekunden erreicht ?
brne Soft20 ;nein -> Ende
clr Temp2 ;Sekunde löschen
inc Minute ;Minute erhöhen
cpi Minute,60 ;60 Minuten erreicht ?
brne Soft20 ;nein -> Ende
clr Minute ;Minute löschen
inc Stunde ;Stunde erhöhen
cpi Stunde,24 ;24 Stunden erreicht ?
brne Soft20 ;nein -> Ende
clr Stunde ;Stunde löschen
*lds Temp3,{_day}
inc Temp3 ;Tag erhöhen
cpi Temp3,29 ;Tag 29 erreicht ?
brlo Soft19 ;bis 28 -> Ende
clt ;ab 29 -> Hat Monat 29,30,31 Tage ?
bld Status,5 ;Status Uhr 1x gestellt löschen
; set ;Datum nach DCF stellen !
; bld Status,7 ;Status Uhr nach DCF stellen setzen
cpi Temp3,32 ;Tag 32 erreicht ?
brne Soft19 ;nein -> Ende
ldi Temp3,1 ;Tag 1 setzen
*sts {_day},Temp3
*lds Temp3,{_month}
inc Temp3 ;Monat erhöhen
cpi Temp3,13 ;Monat 13 erreicht ?
brne Soft18 ;nein -> Ende
ldi Temp3,1 ;Monat 1 setzen
*sts {_month},Temp3
*lds Temp3,{_year}
inc Temp3 ;Jahr erhöhen
cpi Temp3,100 ;Jahr 100 erreicht ?
brne Soft17 ;nein -> Ende
clr Temp3 ;Jahr 00 setzen
Soft17:
*sts {_year},Temp3
rjmp Soft20
Soft18:
*sts {_month},Temp3
rjmp Soft20
Soft19:
*sts {_day},Temp3
Soft20:
*sts {H_Sek},Temp1
*sts {_sec},Temp2
*sts {_min},Minute
*sts {_hour},Stunde
ret
;-------------------------------------------------------------------------------
Auswerten:
cpi Impuls, 21 ;21. Impuls
brne Aus10 ;nein -> weiter
clr Buffer
clr Pari
Aus10:
cpi Impuls, 28 ;28. Impuls
brne Aus15 ;nein -> weiter
lsr Buffer ;Buffer 1x schieben, da Minute nur 7 Bit
rcall Bcd2dez ;in Dezimal wandeln
*sts {T_Min},Buffer ;Temp Minute schreiben
clr Buffer
Aus15:
cpi Impuls, 29 ;Minuten Parität
brne Aus20
clr Temp3
bst Buffer,7 ;Paritätsbit selektieren
bld Temp3,0 ;Paritätsbit in Temp3 Bit0 kopieren
cp Temp3,Pari ;Parität überprüfen
brne Aus26 ;Fehler -> Ende
clr Pari
clr Buffer
Aus20:
cpi Impuls, 35 ;35. Impuls
brne Aus25 ;nein -> weiter
lsr Buffer ;Buffer 2x schieben, da Stunde nur 6 Bit
lsr Buffer
rcall Bcd2dez ;in Dezimal wandeln
*sts {T_Std},Buffer ;Temp Stunde schreiben
clr Buffer
Aus25:
cpi Impuls, 36 ;Stunden Parität
brne Aus30
clr Temp3
bst Buffer,7 ;Paritätsbit selektieren
bld Temp3,0 ;Paritätsbit in Temp3 Bit0 kopieren
cp Temp3,Pari ;Parität überprüfen
breq Aus27 ;Pari OK -> weiter
Aus26:
ret ;Fehler -> Ende
Aus27:
set ;T-Bit setzen
bld Status,4 ;Bit4 Status setzen (Parität)
clr Buffer
Aus30:
cpi Impuls,42 ;42. Impuls
brne Aus40
lsr Buffer ;Buffer 2x schieben, da Tag nur 6 Bit
lsr Buffer
rcall Bcd2dez ;in Dezimal wandeln
*sts {_day},Buffer ;Tag schreiben
clr Buffer
Aus40:
cpi Impuls,45 ;45. Impuls
brne Aus50
lsr Buffer ;Buffer 5x schieben, da Wochentag nur 3 Bit
lsr Buffer
lsr Buffer
lsr Buffer
lsr Buffer
rcall Bcd2dez ;in Dezimal wandeln
*sts {WoTag},Buffer ;Wochentag schreiben
clr Buffer
Aus50:
cpi Impuls,50 ;50. Impuls
brne Aus60
lsr Buffer ;Buffer 3x schieben, da Monat nur 5 Bit
lsr Buffer
lsr Buffer
rcall Bcd2dez ;in Dezimal wandeln
*sts {_month},Buffer ;Monat schreiben
clr Buffer
Aus60:
cpi Impuls,58 ;58. Impuls
brne Aus70
rcall Bcd2dez ;in Dezimal wandeln
*sts {_year},Buffer ;Jahr schreiben
clr Buffer
Aus70:
cpi Impuls,59 ;59. Impuls
brne Aus80
set ;T-Bit setzen
bld Status,3 ;Bit3 Status setzen (59 Impulse)
Aus80:
cpi Impuls,60 ;bei mehr als 59 Impulsen (Störimpulse)
brne Aus90
clt ;T-Bit löschen
bld Status,3 ;Bit3 Status löschen (59 Impulse)
bld Status,4 ;Bit4 Status löschen (Parität)
Aus90:
ret
;-------------------------------------------------------------------------------
Bcd2dez:
mov Temp1,Buffer
andi Temp1,$0F
Bcd10:
subi Buffer,$10
brcs Bcd20
subi Temp1,$F6
rjmp Bcd10
Bcd20:
mov Buffer,Temp1
ret
[end]
... und ein Testprog mit einem 4x16 LCD:
$regfile = "m32def.dat" 'ATmega 32
$crystal = 8000000 'Quarz: 8 MHz
$baud = 9600
$hwstack = 32 'hardware stack
$swstack = 10 'software stack
$framesize = 40 'frame space
Config Date = Dmy , Separator = . 'deutsches Format für Datum
Config Clock = Soft
Disable Timer2 'ausgeschaltet lassen
$lib "dcf77_soft.lib" 'LIB für DCF77
$external Dcf77
Declare Sub Dcf77
'################################################# ##########################
'Hauptprogramm:
'LCD konfigurieren:
Wait 1
Config Lcdpin = Pin , Db4 = Portb.4 , Db5 = Portb.5 , Db6 = Portb.6 , Db7 = Portb.7 , E = Portb.1 , Rs = Portb.0
Config Lcd = 16 * 4 'LCD 164A
'Startmeldung:
Cls
Lcd "* RNBFRA V1.22 *"
Wait 5
Cls
Config Timer0 = Timer , Prescale = 1024 'Timer 40Hz
Const Startwert = 61 'Für 8MHz
Timer0 = Startwert
On Timer0 Tim0_isr 'Überlauf alle 25ms
Enable Interrupts
Enable Timer0
'---------------------- Pin für DCF Eingang definieren ---------------------
'Jeder Portpin kann benutzt werden.
'Auch in der "Dcf77_soft.lib" entsprechend anpassen !!!
Config Pind.3 = Input 'DCF 77 Eingang
Set Portd.3 'Pullup ein
Declare Sub Showstatus()
Declare Sub Showtime()
'------------------- Variablen für DCF Routine -----------------------------
Dim Status As Byte , Zaehler As Byte , Buffer As Byte , Impuls As Byte
Dim H_sek As Byte , T_min As Byte , T_std As Byte , Wotag As Byte
Dim Pari As Byte , Pau As Byte , Imp As Byte
Dim I As Byte
'---------------------------------------------------------------------------
'Hauptprogramm:
Cls
Cursor Off
Date$ = "01.01.00"
Time$ = "00:00:00"
Status.7 = 0 'Uhr nach DCF stellen: AUS
Status.5 = 0 'Uhr wurde nicht gestellt
I = 0
'****************** HAUPTPROGRAMMSCHLEIFE **********************************
Do
Cls
Call Showtime()
Call Showstatus()
If _min = 58 And Status.7 = 0 Then Status.5 = 0 '1x pro Stunde nach DCF stellen
If Status.5 = 0 Then Status.7 = 1 Else Status.7 = 0 'Zeit nicht aktuell: Stellen!
Wait 1
Loop
End
'************* ENDE HAUPTPROGRAMM ******************************************
Sub Showstatus() 'Status anzeigen
If I = 0 Then I = 1 Else I = 0
Locate 1 , 1
If Status.5 = 1 Then
Lcd "*DCF-Soft Clock*"
Else
Lcd "***Soft Clock***"
End If
Locate 4 , 1
If Status.7 = 1 Then
Lcd "DCF:On "
Else
Lcd "DCF:Off"
End If
Locate 4 , 9
If Status.4 = 1 And I = 0 Then
Lcd " Signal"
Else
Lcd " "
End If
End Sub
'---------------------------------------------------------------------------
Sub Showtime()
Locate 2 , 5
Lcd Time$ 'Zeit an LCD
'Print Time$ 'Zeit an Terminal
If Status.5 = 1 Then
Locate 3 , 3
Wotag = Dayofweek()
Lcd Lookupstr(wotag , Wochentag) ; ". "
Lcd Date$
End If
End Sub
'---------------------- Interrupt Routine DCF77 ----------------------------
Tim0_isr:
Timer0 = Startwert
Call Dcf77
Return
'################################################# ##########################
'Programm Ende:
End
'---------------------- Daten für Wochentag --------------------------------
Wochentag:
Data "Mo" , "Di" , "Mi" , "Do" , "Fr" , "Sa" , "So"
'################################################# ##########################
Die Demo zeigt neben Uhrzeit und Datum, ob die Softuhr ohne DCF-Aktualisierung läuft "Soft Clock" oder schon 1x nach DCF gestellt wurde "DCF-Soft Clock".
In der 4. Zeile erscheint "DCF:Off", wenn in der lib keine DCF-Decodierung erfolgt oder "DCF:On", wenn der Decoder eingeschaltet ist.
Dort blinkt auch "Signal", wenn die Parität o.k. ist (heißt: Es liegt wohl ein DCF-Signal an ...).
Viel Spaß damit.
Gruß Dirk
Für den Bau einer Wohnzimmeruhr, die permanent Zeit und Datum anzeigt, habe ich meine Library noch einmal überarbeitet.
Es wird jetzt das komplette DCF Empfangstelegramm auf korrekte Parität überprüft. Die Softwareuhr wurde so erweitert,
dass auch Tag, Monat und Jahr, bei schlechtem Empfang weiterzählt.
Hier noch mal die überarbeitete Version meiner DCF Library.
infosystems
19.08.2006, 07:31
Hallo,
Ich versuche die Uhrzeit am Terminal auszugeben.
bei mir kommt aber leider als Anzeige die Form
21:2:35
Ich möchte aber die Ausgabe in der Form
21:02:35
Wird da die 0 im Program unterdrückt, oder kommt die schon über des DCF signal nicht an?
Viele Grüße
Richard
Schau mal in der Hilfe den
Befehl FORMAT
an.
Beachte auch den Hinweis in einem anderen Forumsbeitrag zum Beispiel in der Hilfe.
joshi1010
04.09.2006, 22:36
@Dirk
Hallo,
Ich habe mit Deiner Lib noch ein kleines Problem...
Uhrzeit und Datum werden korrekt dargestellt. Allerdings läuft die Uhr zu schnell. Das kann man wunderbar sehen, wenn sie mit DCF syncronisiert wird. Die Uhr 'gewinnt' pro Std. etwa 2min !? Da ich nur den internen Osc. einsetze (zu Testzwecken, da ich zu faul war, einen passenden Quarz herauszusuchen), ist eine gewisse Ungenauigkeit zu erwarten. Was mir aber auffällt ist, das die Uhr alle 10 Sek. einen zu schnellen Sprung zur nächsten Sek. macht.
Irgendeine Idee?
Ansonsten gute Arbeit!
Viele Grüsse
Urs
Hi Urs,
Die Uhr 'gewinnt' pro Std. etwa 2min !?
UUps! Bei mir ist das auf keinen Fall so. Die Softclock (ohne Uhrenquarz) läuft mit höchstens 1 Sek. Abweichung pro Stunde. Hast du den richtigen Timer-Startwert für deine Taktfrequenz genommen?
Wie auch immer ... Ich habe jetzt eine neue LIB-Version, vielleicht klappt es ja damit besser:
copyright = W.Krueger
comment = DCF77-Decoder und Softclock
libversion = 2.50 (D. Ottensmeyer)
date = 05.09.2006
statement = ----------------------------------
statement = muss alle 25ms ausgeführt werden !
statement = Neu: komplette Paritätsprüfung
statement = Neu: Auswertung der Bits 15..20
statement = Neu: erweiterte Softclock
statement = ----------------------------------
[Dcf77_soft]
.equ DCF_Port = $10 ;$10 = Portd
.equ DCF_Pin = 3 ;3 = Pin 3
.equ Imp0min = 70 ;minimale Länge des Minutenimpulses
.equ Imp1min = 6 ;minimale Länge des "1" Impulses
;alles darunter wird als "0" Impuls gewertet
.def Temp1 = r16
.def Temp2 = r17
.def Status = r18
;Bit0 = aktueller DCF Status
;Bit1 = vorheriger DCF Status
;Bit2 = 58 Impulse empfangen
;Bit3 = Parität OK
;Bit4 = Stundenparität OK
;Bit5 = Uhr nach DCF gestellt
;Bit6 = Datum nach DCF gestellt
;Bit7 = Uhr nach DCF stellen
.def Impulse = r19
.def Counter = r20
.def Buffer = r21
.def Parity = r22
Dcf77_soft:
*lds Status,{Dcfstatus} ;Status laden
rcall Softclock ;Softclock bearbeiten
bst Status,7 ;Status Uhr nach DCF stellen ?
brts Puls0 ;ja -> weiter
*sts {Dcfstatus},Status
ret
;-------------------------------------------------------------------------------
[Dcf77]
.equ DCF_Port = $10 ;$10 = Pind
.equ DCF_Pin = 3 ;3 = Pin 3
.equ Imp0min = 70 ;minimale Länge des Minutenimpulses
.equ Imp1min = 6 ;minimale Länge des "1" Impulses
;alles darunter wird als "0" Impuls gewertet
.def Temp1 = r16
.def Temp2 = r17
.def Status = r18
;Bit0 = aktueller DCF Status
;Bit1 = vorheriger DCF Status
;Bit2 = 58 Impulse empfangen
;Bit3 = Parität OK
;Bit4 = Stundenparität OK
;Bit5 = Uhr nach DCF gestellt
;Bit6 = Datum nach DCF gestellt
;Bit7 = Uhr nach DCF stellen
.def Impulse = r19
.def Counter = r20
.def Buffer = r21
.def Parity = r22
Dcf77:
*lds Status,{Dcfstatus} ;Status laden
bst Status,7 ;Status Uhr nach DCF stellen ?
brts Puls0 ;ja -> weiter
ret
Puls0:
*lds Impulse,{Dcfimpulse} ;Variablen laden
*lds Counter,{Dcfcounter}
*lds Buffer,{Dcfbuffer}
*lds Parity,{Dcfparity}
in temp1,Dcf_Port ;DCF Port lesen
bst temp1,Dcf_Pin ;Status holen
bld Status,0 ;aktuellen Status speichern
inc Counter ;Impulslänge erhöhen
bst Status,0 ;aktuellen Status prüfen
brts Puls20 ;Status Low -> weiter
bst Status,1 ;vorherigen Status prüfen
brtc Puls40 ;vorheriger Status Low -> Ende
ldi temp1,Imp0min ;Minutenimpuls Minimalwert laden
cp Counter,temp1 ;Impulslänge Minimalwert überschritten
brcs Puls10 ;nein -> weiter
*sts {Dcfpau},Counter ;--------> Minutenimpulslänge speichern für Debug
clr Buffer ;Empfangspuffer löschen
clr Impulse ;Impulszähler löschen
bst Status,3 ;Parität OK ?
brtc Puls15 ;Nein -> weiter
bst Status,2 ;58 Impulse empfangen ?
brtc Puls15 ;Nein -> weiter
rcall Stellen ;empfangene Zeit übernehmen
Puls5:
clt
bld Status,2 ;Status 58 Impulse löschen
bld Status,3 ;Status Parität OK löschen
bld Status,4 ;Status Stundenparität OK löschen
Puls10:
clr Counter ;Impulslänge löschen
rjmp Puls40 ;Ende
Puls15:
bst Status,4 ;Stundenparität OK ?
brtc Puls5
rcall Zeitstellen ;nur Uhrzeit übernehmen
rjmp Puls5
Puls20:
bst Status,1 ;vorherigen Status prüfen
brts Puls40 ;vorheriger Status Low -> Ende
ldi temp1,Imp1min ;Minimalwert für "1" Impuls laden
cp Counter,temp1 ;Minimalwert unterschritten ?
brcs Puls30 ;ja -> weiter
*sts {Dcfimp},Counter ;--------> Impulslänge High speichern für Debug
cpi Impulse,28 ;beim Paritätsbit Min keine Negation
breq Puls25
cpi Impulse,35 ;beim Paritätsbit Std keine Negation
breq Puls25
cpi Impulse,58 ;beim Paritätsbit Datum keine Negation
breq Puls25
ldi Temp1,1
eor Parity,Temp1 ;Paritätsbit Negation
Puls25:
sec ;Carry setzen ( "1" empfangen )
ror Buffer ;Carry in Empfangspuffer
rcall Auswerten ;Impulse auswerten
inc Impulse ;Impulszähler erhöhen
rjmp Puls40 ;Ende
Puls30:
*sts {Dcfimp},Counter ;--------> Impulslänge Low speichern für Debug
clc ;Carry löschen ( "0" empfangen )
ror Buffer ;Carry in Empfangspuffer
rcall Auswerten ;Impulse auswerten
inc Impulse ;Impulszähler erhöhen
Puls40:
bst Status,0 ;aktuellen Status holen
bld Status,1 ;Status speichern
*sts {Dcfstatus},Status ;Variablen wieder speichern
*sts {Dcfimpulse},Impulse
*sts {Dcfcounter},Counter
*sts {Dcfbuffer},Buffer
*sts {Dcfparity},Parity
ret
;-------------------------------------------------------------------------------
Softclock: ;muss 40x pro Sekunde aufgerufen werden
*lds Temp1,{Dcfhsec}
inc Temp1 ;Hundertstel Sek erhöhen
cpi Temp1,40 ;1000ms erreicht ?
breq Soft10 ;ja -> weiter
*sts {Dcfhsec},Temp1
ret ;sonst Ende
Soft10:
clr Temp1 ;Hundertstel Sek löschen
*sts {Dcfhsec},Temp1
*lds Temp1,{_sec}
inc Temp1 ;Sekunde erhöhen
cpi Temp1,60 ;60 Sekunden erreicht ?
breq Soft20 ;ja -> weiter
*sts {_sec},Temp1
ret
Soft20:
clr Temp1 ;Sekunde löschen
*sts {_sec},Temp1
*lds Temp1,{_min}
inc Temp1 ;Minute erhöhen
cpi Temp1,60 ;60 Minuten erreicht ?
breq Soft30 ;ja -> weiter
*sts {_min},Temp1
ret
Soft30:
clr Temp1 ;Minute löschen
*sts {_min},Temp1
*lds Temp1,{_hour}
inc Temp1 ;Stunde erhöhen
cpi Temp1,24 ;24 Stunden erreicht ?
breq Soft40 ;ja -> weiter
*sts {_hour},Temp1
ret
Soft40:
clr Temp1 ;Stunde löschen
*sts {_hour},Temp1
*lds Temp1,{_dayofweek}
inc Temp1 ;Wochentag erhöhen
cpi Temp1,8 ;letzter Wochentag erreicht ?
breq Soft50 ;ja -> weiter
*sts {_dayofweek},Temp1
ret
Soft50:
ldi Temp1,1 ;Wochentag auf "1" (Montag)
*sts {_dayofweek},Temp1
*lds Temp1,{_day} ;Tag holen
*lds Temp2,{_month} ;Monat holen
ldi zl,low(Tagdaten*2)
ldi zh,high(Tagdaten*2) ;Anzahl Tage pro Monat holen
add zl,Temp2 ;Zeiger auf aktuellen Monat
lpm ;Anzahl Tage holen
cp Temp1,r0 ;Monatsende erreicht ?
brne Soft90 ;nein -> weiter
cpi Temp2,2 ;Monatsende Februar ?
brne Soft60 ;nein -> weiter
clt ;Evtl. Schaltjahr mit 29.2.
bld Status,6 ;Status Datum nach DCF gestellt löschen
Soft60:
cpi Temp2,6 ;Monatsende Juni ?
brne Soft70 ;nein -> weiter
clt ;Zur Jahresmitte evtl. Schaltsekunde
bld Status,5 ;Status Uhr nach DCF gestellt löschen
Soft70:
ldi Temp1,1 ;Tag auf 1
cpi Temp2,12 ;Jahresende erreicht ?
brne Soft100 ;nein -> weiter
clt ;Zum Jahreswechsel evtl. Schaltsekunde
bld Status,5 ;Status Uhr nach DCF gestellt löschen
*lds Temp2,{_year} ;Jahr holen
inc Temp2 ;Jahr erhöhen
cpi Temp2,100 ;Jahr 100 erreicht ?
brne Soft80 ;nein -> Ende
clr Temp2 ;Jahr 00 setzen
Soft80:
*sts {_year},Temp2 ;speichern
ldi Temp2,1 ;Monat auf 1
rjmp Soft110
Soft90:
inc Temp1 ;Tag erhöhen
rjmp Soft110
Soft100:
inc Temp2 ;Monat erhöhen
Soft110:
*sts {_day},Temp1 ;Datum speichern
*sts {_month},Temp2
ret
Stellen:
*lds Temp1,{Dcftemp+2}
*sts {_day},Temp1 ;Tag auf empfangenen Tag
*lds Temp1,{Dcftemp+3}
*sts {_dayofweek},Temp1 ;Wochentag auf empfangenen Wochentag
*lds Temp1,{Dcftemp+4}
*sts {_month},Temp1 ;Monat auf empfangenen Monat
*lds Temp1,{Dcftemp+5}
*sts {_year},Temp1 ;Jahr auf empfangenes Jahr
set
bld Status,6 ;Status Datum nach DCF gestellt setzen
Zeitstellen:
ldi Temp1,1 ;Hundertstel zurücksetzen
*sts {Dcfhsec},Temp1 ;(1. Intervall 25ms kürzer !)
clr Temp1
*sts {_sec},Temp1 ;Sekunde auf 0 setzen
*lds Temp1,{Dcftemp}
*sts {_min},Temp1 ;Minute auf empfangene Minute
*lds Temp1,{Dcftemp+1}
*sts {_hour},Temp1 ;Stunde auf empfangene Stunde
*lds Temp1,{Dcftemp+6}
*sts {Dcfflags},Temp1 ;DCF77-Bits 15..20 aktualisieren
set
bld Status,5 ;Status Uhr nach DCF gestellt setzen
ret
Tagdaten:
.db 00, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
;-------------------------------------------------------------------------------
Auswerten:
cpi Impulse,14 ;14. Impuls
brne Aus5 ;nein -> weiter
clr Buffer
Aus5:
cpi Impulse,20 ;20. Impuls
brne Aus10 ;nein -> weiter
bst Buffer,7 ;Startbit 20 (S) selektieren
brtc Aus26 ;Fehler -> Ende
lsr Buffer ;Buffer 2x schieben, da 6 Bit
lsr Buffer
*sts {Dcftemp+6},Buffer ;Temp DCF77-Bits 15..20 schreiben
;Inhalt Buffer -> Bit0 (R) : Reserve-Antenne des DCF77-Senders
; Bit1 (A1): Ankündigung des Wechsels MEZ <-> MESZ
; Bit2 (Z1): \__ Z1/Z2: 10 = MESZ, 01 = MEZ
; Bit3 (Z2): /
; Bit4 (A2): Ankündigung einer Schaltsekunde
; Bit5 (S) : Startbit f. Zeitinformationen (immer 1)
clr Buffer
clr Parity
Aus10:
cpi Impulse,27 ;27. Impuls
brne Aus15 ;nein -> weiter
lsr Buffer ;Buffer 1x schieben, da Minute nur 7 Bit
rcall Bcd2dez ;in Dezimal wandeln
*sts {Dcftemp},Buffer ;Temp Minute schreiben
clr Buffer
Aus15:
cpi Impulse,28 ;Minuten Parität
brne Aus20
clr Temp1
bst Buffer,7 ;Paritätsbit selektieren
bld Temp1,0 ;Paritätsbit in Temp1 Bit0 kopieren
cp Temp1,Parity ;Minutenparität überprüfen
brne Aus26 ;Fehler -> Ende
clr Parity
clr Buffer
Aus20:
cpi Impulse,34 ;34. Impuls
brne Aus25 ;nein -> weiter
lsr Buffer ;Buffer 2x schieben, da Stunde nur 6 Bit
lsr Buffer
rcall Bcd2dez ;in Dezimal wandeln
*sts {Dcftemp+1},Buffer ;Temp Stunde schreiben
clr Buffer
Aus25:
cpi Impulse,35 ;Stunden Parität
brne Aus30
clr Temp1
bst Buffer,7 ;Paritätsbit selektieren
bld Temp1,0 ;Paritätsbit in Temp1 Bit0 kopieren
cp Temp1,Parity ;Stundenparität überprüfen
breq Aus27 ;Parität OK -> weiter
Aus26:
ret ;Fehler -> Ende
Aus27:
set
bld Status,4 ;Bit4 Status setzen (Stundenparität)
clr Parity
clr Buffer
Aus30:
cpi Impulse,41 ;41. Impuls
brne Aus40
lsr Buffer ;Buffer 2x schieben, da Tag nur 6 Bit
lsr Buffer
rcall Bcd2dez ;in Dezimal wandeln
*sts {Dcftemp+2},Buffer ;Temp Tag schreiben
clr Buffer
Aus40:
cpi Impulse,44 ;44. Impuls
brne Aus50
lsr Buffer ;Buffer 5x schieben, da Wochentag nur 3 Bit
lsr Buffer
lsr Buffer
lsr Buffer
lsr Buffer
rcall Bcd2dez ;in Dezimal wandeln
*sts {Dcftemp+3},Buffer ;Temp Wochentag schreiben
clr Buffer
Aus50:
cpi Impulse,49 ;49. Impuls
brne Aus60
lsr Buffer ;Buffer 3x schieben, da Monat nur 5 Bit
lsr Buffer
lsr Buffer
rcall Bcd2dez ;in Dezimal wandeln
*sts {Dcftemp+4},Buffer ;Temp Monat schreiben
clr Buffer
Aus60:
cpi Impulse,57 ;57. Impuls
brne Aus70
rcall Bcd2dez ;in Dezimal wandeln
*sts {Dcftemp+5},Buffer ;Temp Jahr schreiben
clr Buffer
Aus70:
cpi Impulse,58 ;Restparität
brne Aus80
set ;T-Bit setzen
bld Status,2 ;Bit2 Status setzen (58 Impulse)
clr Temp1
bst Buffer,7 ;Paritätsbit selektieren
bld Temp1,0 ;Paritätsbit in Temp1 Bit0 kopieren
cp Temp1,Parity ;Restparität überprüfen
brne Aus90 ;Fehler -> Ende
set ;T-Bit setzen
bld Status,3 ;Bit3 Status setzen (Parität)
Aus80:
cpi Impulse,59 ;mehr als 58 Impulse (d.h. Störimpulse)
brne Aus90
clt ;T-Bit löschen
bld Status,2 ;Bit2 Status löschen (58 Impulse)
Aus90:
ret
;-------------------------------------------------------------------------------
Bcd2dez:
mov Temp1,Buffer
andi Temp1,$0F
Bcd10:
subi Buffer,$10
brcs Bcd20
subi Temp1,$F6
rjmp Bcd10
Bcd20:
mov Buffer,Temp1
ret
[end]
Die LIB kann man MIT oder OHNE einen Uhrenquarz an TOSC1/2 verwenden. Ohne Quarz nimmt man einfach DCF77_soft, mit Quarz die Routine DCF77.
Die ISR sieht dann so aus:
'---------------------------------------------------------------------------
Getdatetime: 'Nicht genutzt!
Setdate:
Settime:
Return
'---------------------- Interrupt Routine DCF77 ----------------------------
Tim2_isr:
Timer2 = Startwert
Call Dcf77_soft
Return
... wobei Getdatetime usw. nur bei der DCF77_soft Variante nötig ist.
Gruß Dirk
Hi Urs,
... noch vergessen ...
Hier die beiden include-Dateien für die LIB V2.50. Kann man einfach ins eigene Prog mit $include "DCF77.bas" einbinden:
Zuerst die DCF77.bas für den Betrieb MIT Uhrenquarz:
'################################################# ##########################
'Programmname: DCF77.BAS
'Aufgabe:
'Include-Programm für die DCF77.lib
'
'Hardware:
'M32 mit 8 MHz
'Es ist ein DCF-Empfänger (CONRAD 641138) an Portd.3 angeschlossen
'und ein Uhrenquarz 32768Hz an Pinc.6/Pinc.7 (TOSC1/2).
'################################################# ##########################
Config Date = Dmy , Separator = . 'deutsches Datumsformat
Config Clock = Soft 'Softclock aktivieren
' (läuft mit Timer2!)
$lib "dcf77.lib" 'LIB für DCF77
$external Dcf77
Declare Sub Dcf77
Config Timer0 = Timer , Prescale = 1024 'Timer 40Hz
Const Startwert = 61 'Für 8MHz
Timer0 = Startwert
On Timer0 Tim0_isr 'Überlauf 40x/s
Enable Interrupts
Disable Timer0 'zunächst ausschalten
'---------------------- Pin für DCF Eingang definieren ---------------------
'Jeder Portpin kann benutzt werden.
'Auch in der "Dcf77.lib" entsprechend anpassen !!!
Config Pind.3 = Input 'DCF77 Eingang
Set Portd.3 'Pullup ein
'--------------------- Variablen der DCF77.lib -----------------------------
Dim _dayofweek As Byte , Dcfstatus As Byte , Dcfflags As Byte
'_dayofweek -> 1..7 (Mo..So)
'Dcfstatus -> Bit0: intern Bit4: Stundenparität OK
' Bit1: intern Bit5: Uhr nach DCF gestellt
' Bit2: 58 Impulse empfangen Bit6: Datum nach DCF gestellt
' Bit3: Parität OK Bit7: Uhr nach DCF stellen
' ACHTUNG: Bits 0..4 NUR LESEN!!!
'Dcfflags -> Bit0 (R) : Reserve-Antenne des DCF77-Senders
' Bit1 (A1): Ankündigung des Wechsels MEZ <-> MESZ
' Bit2 (Z1): \__ Z1/Z2: 10 = MESZ, 01 = MEZ
' Bit3 (Z2): /
' Bit4 (A2): Ankündigung einer Schaltsekunde
' Bit5 (S) : Startbit f. Zeitinformationen (immer 1)
'Interne Variablen der DCF77.lib:
Dim Dcfcounter As Byte , Dcfbuffer As Byte , Dcfimpulse As Byte
Dim Dcfparity As Byte , Dcfhsec As Byte , Dcftemp(7) As Byte
Dim Dcfpau As Byte , Dcfimp As Byte 'Nur für Debug!
'---------------------------------------------------------------------------
Dcfstatus.7 = 0 'Uhr nach DCF stellen: AUS
Dcfstatus.5 = 0 'Uhrzeit inaktuell
Dcfstatus.6 = 0 'Datum inaktuell
... und dann die Version DCF77_soft.bas für die Softclock OHNE Uhrenquarz:
'################################################# ##########################
'Programmname: DCF77_soft.BAS
'Aufgabe:
'Include-Programm für die DCF77.lib
'
'Hardware:
'M32 mit 8 MHz
'Es ist ein DCF-Empfänger (CONRAD 641138) an Portd.3 angeschlossen.
'################################################# ##########################
Config Date = Dmy , Separator = . 'deutsches Datumsformat
Config Clock = User 'Softclock aktivieren
$lib "dcf77.lib" 'LIB für DCF77
$external Dcf77_soft
Declare Sub Dcf77_soft
Config Timer2 = Timer , Prescale = 1024 'Timer 40Hz
Const Startwert = 61 'Für 8MHz
Timer2 = Startwert
On Timer2 Tim2_isr 'Überlauf 40x/s
Enable Interrupts
Enable Timer2
'---------------------- Pin für DCF Eingang definieren ---------------------
'Jeder Portpin kann benutzt werden.
'Auch in der "Dcf77.lib" entsprechend anpassen !!!
Config Pind.3 = Input 'DCF77 Eingang
Set Portd.3 'Pullup ein
'--------------------- Variablen der DCF77.lib -----------------------------
Dim _dayofweek As Byte , Dcfstatus As Byte , Dcfflags As Byte
'_dayofweek -> 1..7 (Mo..So)
'Dcfstatus -> Bit0: intern Bit4: Stundenparität OK
' Bit1: intern Bit5: Uhr nach DCF gestellt
' Bit2: 58 Impulse empfangen Bit6: Datum nach DCF gestellt
' Bit3: Parität OK Bit7: Uhr nach DCF stellen
' ACHTUNG: Bits 0..4 NUR LESEN!!!
'Dcfflags -> Bit0 (R) : Reserve-Antenne des DCF77-Senders
' Bit1 (A1): Ankündigung des Wechsels MEZ <-> MESZ
' Bit2 (Z1): \__ Z1/Z2: 10 = MESZ, 01 = MEZ
' Bit3 (Z2): /
' Bit4 (A2): Ankündigung einer Schaltsekunde
' Bit5 (S) : Startbit f. Zeitinformationen (immer 1)
'Interne Variablen der DCF77.lib:
Dim Dcfcounter As Byte , Dcfbuffer As Byte , Dcfimpulse As Byte
Dim Dcfparity As Byte , Dcfhsec As Byte , Dcftemp(7) As Byte
Dim Dcfpau As Byte , Dcfimp As Byte 'Nur für Debug!
'---------------------------------------------------------------------------
Dcfstatus.7 = 0 'Uhr nach DCF stellen: AUS
Dcfstatus.5 = 0 'Uhrzeit inaktuell
Dcfstatus.6 = 0 'Datum inaktuell
Demo-Progs evtl. auf Anfrage, falls es bei dir nicht so läuft!
Gruß Dirk
Hallo Leute,
danke erst mal an AlBundy an die Library. Super!
Wie kann ich denn nun aber festlegen, das die DCF-Routine nur z.B. einmal/TAg 03:00 Uhr ausgeführt wird, für 5 Minuten oder so. Damit sie auch sicher empfängt.
Dann meine Variablen für Stunde Min, sek, Tag... aktualisiert und dann wieder stehen bleibt bis zum nächsten Tag?
Also praktisch auch den Interrupt solange beendet?
Raffe ich irgendwie nicht. Bin aber auch noch Anfänger.
Also, falls ich jemand mit dieser trivialen Frage nerve, dann einfach ignorieren.
Danke, Andreas
joshi1010
06.09.2006, 16:57
Hallo Dirk,
erstmal besten Dank für die prompte Antwort!
"Hast du den richtigen Timer-Startwert für deine Taktfrequenz genommen? "
..ist der aus deinem Demo (Const Startwert = 61)
Nun ja,das Proggi läuft bei mir auf nem Mega8 - aber das sollte eigentlich egal sein !?
folgendes hatte ich auskommentiert:
$crystal = 8000000 'Quarz: 8 MHz
$baud = 9600
$hwstack = 32 'hardware stack
$swstack = 10 'software stack
$framesize = 40
- weil, wie gesagt, der interne Osc.benutzt wird
- RS232 nicht benötigt wird
- $hwstack, $swstack, $framesize fehlermeldungen beim Compilieren verursachen. So habe ich das erstmal dem Compiler überlassen. Möglicherweise besteht da ein Zusammenhang!? Allerdings setzt Du in Deinem neuen Beispiel diese Einstellungen auch nicht mehr.
So ich den heut' abend Zeit finde,werd ich Deine neueLib mal testen.
Besten Dank
bis denne
Urs
n
joshi1010
06.09.2006, 17:07
@dl1akp
ich noch mal...
könnte mir denken,das in Dirk's Beispiel folgende Zeile für den Aufruf der DCF-Sync. verantw. ist:
"If _min = 58 And Status.7 = 0 Then Status.5 = 0 '1x pro Stunde nach DCF stellen"
Die DCF-Routine wird auf jeden Fall beim Start (Reset) des Proz.
aufgerufen und dann einmal pro Stunde (in der 58 Min.)
man könnte _min mal durch _hour ersetzen :
"If _hour = 03 And Status.7 = 0 Then Status.5 = 0 "
jetzt sollte DCF immer nur um 3.00 Uhr einmal aufgerufen werden.
Nur so'n Vorschlag, getestet hab ich's nicht.
Bis denne
Urs
Hallo Leute,
der DCF-Empfang kann auf 2 Arten zu jeder Stunde gestartet werden.
Bei der Version mit Uhrenquarz:
If _min = 0 And Dcfstatus.7 = 0 Then '1x pro Stunde:
Dcfstatus.5 = 0 'Zeit inaktuell
Dcfstatus.6 = 0 'Datum inaktuell
End If
'Wenn Uhr oder Datum inaktuell, dann nach DCF stellen:
'Timer0 ist nur aktiv, solange DCF-Empfang läuft!!!
If Dcfstatus.5 = 0 Or Dcfstatus.6 = 0 Then
Dcfstatus.7 = 1
Enable Timer0
Else
Dcfstatus.7 = 0
Disable Timer0
End If
... und ohne Uhrenquarz:
If _min = 0 And Dcfstatus.7 = 0 Then '1x pro Stunde:
Dcfstatus.5 = 0 'Zeit inaktuell
Dcfstatus.6 = 0 'Datum inaktuell
End If
'Wenn Uhr oder Datum inaktuell, dann nach DCF stellen:
If Dcfstatus.5 = 0 Or Dcfstatus.6 = 0 Then Dcfstatus.7 = 1 Else Dcfstatus.7 = 0
Bei dieser Version darf natürlich der Timer nicht disabled werden, weil dann die Softuhr stehen bleibt.
Gruß Dirk
bertl100
13.09.2006, 20:44
Hi Progger!
Bei Bascom 1.11.8.3 kommt bei mir der Fehler
ISR already defined TIM0_ISR
Wie gibts das?? Stimmt nicht
bertl100
13.09.2006, 20:59
Wo kann ich die DCF77_Soft lib downloaden?
bertl100
13.09.2006, 22:10
Ich bin vielleicht etwas LÄSTIG aber kann mir jemand genau sagen wie ich den DCF-Empfang in einem vorhandenen Code einbinden kann??
Mittlerweile stehen hier mehrere Codes und ich kenn mich einfach nicht mehr aus. Ich hätte gerne mal etwas Durchblick und da ich kein Masterprogrammer bin wäre es nett wenn jemand so Keimfrei wäre einen absolut lauffähigen dcf-Code mit der richtigen lib oder lbx hier reinzustellen.
Bussie!!!! :)
Hi bertl100,
wo hakt's denn?
Die "DCF77.lib" ist das Teil, dass ich als 1. Codeblock in meinem Beitrag vom 15.9. um 17.32 Uhr angegeben habe. Einfach alles da raus kopieren und als DCF77.lib in das LIB-Verzeichnis von BASCOM tun! Das wars!
Dein eigenes Programm (muttu noch selbst schreiben!) zur Darstellung der Zeit und zum DCF-Empfang muss folgendes machen:
a) "DCF77_soft.bas" mit $include "DCF77_soft.bas" einbinden, wenn du keinen Uhrenquarz benutzt.
ODER
b) "DCF77.bas" mit $include "DCF77.bas" einbinden, wenn du einen Uhrenquarz benutzt.
[Beide Progs sind in meinem Beitrag vom 5.9., 17.38 Uhr]
c) Die ISR einbinden. Ein Beispiel dafür ist der 2. untere Codeblock in meinem Beitrag vom 5.9., 17.32 Uhr.
Dein Programm muss jetzt nur noch die BASCOM-Uhrzeit time$ und date$ ausgeben. Am 6.9., 20.26 Uhr habe ich Beispiele ergänzt, wie man den DCF-Decoder ein- und ausschaltet.
Alles klar?
Gruß Dirk
bertl100
14.09.2006, 22:34
Jetzt ist es mir schon klarer, aber mich würde der Ablauf der .lib interessieren damit ich selbst auch Änderungen vornehmen kann.
1. Erfolgt die Synchronisation nur jede Stunde oder muss etwas permanent Abgearbeitet werden?(Irgendwo steht alle 25mS)
Wäre interessant, da in meiner Hauptschleife schon 2 Schnittstellen abgefragt werden müssen.
2. Bei Soft gibt es noch andere Unterfunktionen-----GETTIME---GETDATE........
Wozu brauch ich die?
3. Steht Datum und Zeit bei soft dann in den TIME und DATE Variablen?
Wenn ja, kann ich diese Variablen formatieren damit ich sie über SPI schicken kann?--Byteweise---Habe ein SPI Display mit Touch
Es ist mir schon klar, dass hier keiner eine detallierte Beschreibung
machen wird, aber ich hoffe ihr könnt mir in groben Zügen den Ablauf schildern.
MFG
Bertl
Hallo Bertl,
der DCF-Empfang (bzw. die Decodierung) in der DCF77.lib erfolgt NUR, wenn du das willst.
Mit Dcfstatus.7 = 0 schaltest du ihn AUS und mit Dcfstatus.7 = 1 EIN.
Das kannst du z.B. jede volle Stunde machen (siehe mein Beitrag hier am 6.9., 20.26 Uhr!). Oder wann du willst.
Die DCF77.lib braucht einen Timer und muss alle 25ms aufgerufen werden. Schau dir die DCF77_soft.bas und DCF77.bas an! In diesen Progs, die du in dein Programm - wie gesagt - mit $include einbinden kannst, wird der Timer dafür definiert. Du brauchst dich darum nicht zu kümmern. Die ISR kannst du auch so übernehmen, wie ich sie gepostet hatte.
Dein Prog sieht also z.B. so aus:
'Deine Definitionen
$include "DCF77.bas" 'Ein Uhrenquarz vorhanden!
Do
Gosub Anzeige_der_BASCOM_Zeit 'Selbst schreiben!
If _min = 0 And Dcfstatus.7 = 0 Then '1x pro Stunde:
Dcfstatus.5 = 0 'Zeit inaktuell
Dcfstatus.6 = 0 'Datum inaktuell
End If
'Wenn Uhr oder Datum inaktuell, dann nach DCF stellen:
'Timer0 ist nur aktiv, solange DCF-Empfang läuft!!!
If Dcfstatus.5 = 0 Or Dcfstatus.6 = 0 Then
Dcfstatus.7 = 1
Enable Timer0
Else
Dcfstatus.7 = 0
Disable Timer0
End If
'Hier noch andere wichtige Dinge!
Loop
End
'Nur nötig OHNE Uhrenquarz!!!
'Getdatetime: 'Nicht genutzt!
'Setdate:
'Settime:
'Return
'ISR - Interrupt Routine DCF77
Tim0_isr:
Timer0 = Startwert
Call Dcf77
Return
Anzeige_der_BASCOM_Zeit:
'Anzeige der Zeitvariablen!
Return
Das Unterprogramm "Anzeige_der_BASCOM_Zeit" muss nur die BASCOM-Variablen für die Zeit, also _hour, _min, _sec, ... auf dem LCD oder mit Print auf der RS232 ausgeben. Das schaffst du locker!
Wenn du KEINEN Uhrenquarz hast, nimmst du die DCF77_soft.bas anstelle von DCF77.bas, in der ISR machst du aus jeder 0 eine 2. Vor den Befehlen Getdatetime ... machst du 4x das ' weg und entfernst Enable Timer0 und Disable Timer0.
Alles klar? :-k
Muss funktionieren! Sonst: Bau 'mal alles so zusammen, wie du meinst und poste dein Prog dann hier, dann kann man besser was dazu sagen!
Gruß Dirk
bertl100
15.09.2006, 19:39
@ Dirk
Ich finde es echt super von dir, dass du hier eine kleine Beschreibung für mich reinstellst :) :)
Ich bekam immer einen Compillierfehler.
Genau das ist es was ich brauche. Ich bekomme wahrscheinlich Morgen meine neue Eigenbauplatine. Dann werd ich es sicher zum laufen bringen.
Herzlichen Dank!!!!!!!
bertl100
16.09.2006, 19:06
Ich habe jetzt dein Programm in meines integriert.
Schaus dir mal an. Ich lass die Zeit nur im Sekundentakt anzeigen da mein SPI Touch Display ziemlich viel zu Tun hätte.
Von der Struktur her müsste es nun Passen aber ich hab meine Platine noch nicht bekommen, ergo kann ich das Programm erst dann an der Hardware testen.
MFG
Bertl
bertl100
16.09.2006, 19:33
Wie stell ich den Timer für meinem 14,745600 MHz Quarz ein?
bertl100
16.09.2006, 19:39
Für diesen Quarz brauch ich den Timer 1. Was muss ich da alles ändern??
Hallo bertl100,
ja, du brauchst den Timer1.
Prescale 8
Timer-Startwert 19463
Die Änderungen sind in DCF77_soft.bas bzw. DCF77.bas und in der ISR im Hauptprogramm. Einfach Timer0 durch Timer1 ersetzen und Prescale und die Konstante Startwert anpassen.
Gruß Dirk
bertl100
16.09.2006, 22:01
Für die Variable Startwert musste ich ein Integer definieren, da "const" nur 8 Bit Zahlen kann.
An der library sonst ist nichts zu ändern,oder?
Wie kommst du auf diesen Startwert? Mit dem Programm für die Timerkonfiguration komme ich auf 19455.
Hallo bertl100,
const ist es eigentlich egal, wie groß der Wert ist, also einfach:
Const Startwert = 19463 (In DCF77_soft.bas!!!)
(Ist ja keine Variable, sondern eben eine Konstante!)
Der Wert 19463 ist korrigiert um die BASCOM-typische push/pop Orgie, die bei jedem ISR-Aufruf abläuft, aber 19455 wird auch funktionieren.
Gruß Dirk
bertl100
17.09.2006, 14:21
Kann ich in meiner Hauptschleife mit
If Dcfflags.4 = 1 Then
Gosub Anzeige_der_bascom_zeit
end if
im Sekundentakt die Sub für die Zeitanzeige aufrufen?
Laut Beschreibung ist dieses Flag für die Sekunden.
MFG
Bertl
Hallo bertl100,
... ne, geht so nicht.
Vorschlag:
If Sekunde <> _sec Then
Cls
Gosub Anzeige_der_BASCOM_Zeit
Sekunde = _sec
End If
Das braucht nur noch eine Bytevariable "Sekunde".
Gruß Dirk
bertl100
17.09.2006, 22:51
Alles klar
Vielen Dank!
Hallo,
helft mir doch mal auf die Sprünge:
Wie berechnet ihr den Wert für Prescale und Startwert nach einem gewünschten Quarz??
Habe kein Hilfsprogramm, oder ähnliches gefunden. Ist mir irgendwie unklar.
Danke schon mal...
Andreas
Peacemaker666
26.09.2006, 20:34
Hallo
Hat jemand die Lib mit dem Modul von Reichelt am laufen? bei mir will es überhaupt nix tun.
Benutze das Pollin Board V2 "geht wunderbar" mit Atmega16-16PU und 8Mhz.
An dem Bsp. habe ich folgendes geändert-
in der Lib:
.equ DCF_Port = $12 ;$12 = Portd
.equ DCF_Pin = 7 ;7 = Pin 7
in der .bas
$regfile = "m16def.dat"
$crystal = 8000000
Config Timer0 = Timer, Prescale = 1024
Const Startwert = 61
@albundy thx für die Lib ;-)
P.S. ich bekomme als Status immer 3
cya Peacemaker
Hallo,
.equ DCF_Port = $12 ;$12 = Portd
.equ DCF_Pin = 7 ;7 = Pin 7
Portd ($12) ist in diesem Fall falsch, da bei Eingabe (DCF77) der Pind abgefragt wird.
du musst DCF_Port = $10 einsetzen.
fosslerg
06.10.2006, 23:21
muss vorausschicken, dass ich novize bin, also wahrscheinlich ist der fehler einfach zu finden (hoffe ich zumindest)
ich habe die lib von dirk in der version 2.50 in verwendung, samt zugehörigen include-code
auf meinem mega128 mit 16MHz und uhrenquarz + conrad dcf77.
interner pullup, invertierter ausgang des CDF, sauberes DCF-signal (mit oszi geprüft)
Timer ist der 16bit-timer, prescale und stratwert angepasst an die taktfrequenz, interupts an diesen timer1 angepasst, port A0 im code und der LIB eingetragen.
bei inbetriebnahme wird staus.7 auf 1 gesetzt, detto status.2 (seltsam- sofort nach status.7- in der selben sekunde) und status.0 (keine ahnung was der tut)
die variable dcfcounter läuft von 0-256 in etwa 6-7sek, dcfbuffer und dcfparity bleiben auf 0, dcfpulse steht auf 1, dcfpau auf 0, dcfimp auf 1 (beide in der lib enabled).
was sagt euch dieses fehlverhalten? bin ratlos und hoffe auf eure hilfe
grüsse aus wien
günter
Hallo Günter,
manchmal liegt das Prob im Detail:
Poste doch 'mal deine Änderungen!
Zur Sicherheit: Uhrenquarz 32768 Hz an TOSC1/2 wirklich vorhanden?
Gruß Dirk
fosslerg
07.10.2006, 14:26
ja, der uhrenquarz ist mit 32,nochwas kHZ vorhanden, die interne Soft-clock des atmel geht auch brav.
habe das glück mit dem farb-grafik-display relativ viel auf einmal anzeigen zu können, daher sehe ich auch alle angeben des vorigen posts auf einmal.
ich sehe auch, dass ich das signal tatsächlich am pin ankommt zumal ich das signal des input-pins auf einen output mit LED dahinter "hinüberspiegle"
der pin als eingang ist der A0, das reister für die A-ports ist lt. bescheibung des M128 das $19 wenn ich das alles richtig interpretiert habe.
so nun aufgelistet:
deine lib v2.50, register $19, pin0 also port A0 am prozessor
uhrenquarz aus TOSC, softclock läuft auch
timer Timer1 wegen 16bit aufgrund 16MHz prozessortakt
interupt auf Timer1 geändert, prescale auf 8, start auf 15536
signalform des DCF ist so wie's sein soll, timings des DCF habe ich mit Oszi nachgemessen, alles wie es sein soll
wenn ich nicht alles schon 7x nachgeprüft und überlegt hätte, hätte ich nie gepostet, ich habe auch diese thread schon quasi auswendig gelernt aber keinen hinweis darauf gefunden was ich falsch mache.
vielen dank für deine hilfe!
günter
Hallo Günter,
das was du schreibst, klingt alles richtig.
Ich würde als nächstes Folgendes machen:
Nimm einen anderen Eingangspin nicht aus PortA, weil PortA ja zunächst als ADC definiert ist (z.B. Pind.0),- evtl. ist das die Ursache.
Als Timer-Startwert habe ich 15543, aber 15536 müßte auch gehen.
Hier noch meine LIB V2.52, da ist ein Fehler in der Softclock ausgebügelt, der in die V2.50 reingerutscht war:
copyright = W.Krueger
comment = DCF77-Decoder und Softclock
libversion = 2.52 (D. Ottensmeyer)
date = 07.10.2006
statement = ----------------------------------
statement = muss alle 25ms ausgeführt werden !
statement = Neu: komplette Paritätsprüfung
statement = Neu: Auswertung der Bits 15..20
statement = Neu: erweiterte Softclock
statement = ----------------------------------
[Dcf77_soft]
.equ DCF_Port = $10 ;$10 = Portd
.equ DCF_Pin = 3 ;3 = Pin 3
.equ Imp0min = 70 ;minimale Länge des Minutenimpulses
.equ Imp1min = 6 ;minimale Länge des "1" Impulses
;alles darunter wird als "0" Impuls gewertet
.def Temp1 = r16
.def Temp2 = r17
.def Status = r18
;Bit0 = aktueller DCF Status
;Bit1 = vorheriger DCF Status
;Bit2 = 58 Impulse empfangen
;Bit3 = Parität OK
;Bit4 = Stundenparität OK
;Bit5 = Uhr nach DCF gestellt
;Bit6 = Datum nach DCF gestellt
;Bit7 = Uhr nach DCF stellen
.def Impulse = r19
.def Counter = r20
.def Buffer = r21
.def Parity = r22
Dcf77_soft:
*lds Status,{Dcfstatus} ;Status laden
rcall Softclock ;Softclock bearbeiten
bst Status,7 ;Status Uhr nach DCF stellen ?
brts Puls0 ;ja -> weiter
*sts {Dcfstatus},Status
ret
;-------------------------------------------------------------------------------
[Dcf77]
.equ DCF_Port = $10 ;$10 = Pind
.equ DCF_Pin = 3 ;3 = Pin 3
.equ Imp0min = 70 ;minimale Länge des Minutenimpulses
.equ Imp1min = 6 ;minimale Länge des "1" Impulses
;alles darunter wird als "0" Impuls gewertet
.def Temp1 = r16
.def Temp2 = r17
.def Status = r18
;Bit0 = aktueller DCF Status
;Bit1 = vorheriger DCF Status
;Bit2 = 58 Impulse empfangen
;Bit3 = Parität OK
;Bit4 = Stundenparität OK
;Bit5 = Uhr nach DCF gestellt
;Bit6 = Datum nach DCF gestellt
;Bit7 = Uhr nach DCF stellen
.def Impulse = r19
.def Counter = r20
.def Buffer = r21
.def Parity = r22
Dcf77:
*lds Status,{Dcfstatus} ;Status laden
bst Status,7 ;Status Uhr nach DCF stellen ?
brts Puls0 ;ja -> weiter
ret
Puls0:
*lds Impulse,{Dcfimpulse} ;Variablen laden
*lds Counter,{Dcfcounter}
*lds Buffer,{Dcfbuffer}
*lds Parity,{Dcfparity}
in temp1,Dcf_Port ;DCF Port lesen
bst temp1,Dcf_Pin ;Status holen
bld Status,0 ;aktuellen Status speichern
inc Counter ;Impulslänge erhöhen
bst Status,0 ;aktuellen Status prüfen
brts Puls20 ;Status Low -> weiter
bst Status,1 ;vorherigen Status prüfen
brtc Puls40 ;vorheriger Status Low -> Ende
ldi temp1,Imp0min ;Minutenimpuls Minimalwert laden
cp Counter,temp1 ;Impulslänge Minimalwert überschritten
brcs Puls10 ;nein -> weiter
*sts {Dcfpau},Counter ;--------> Minutenimpulslänge speichern für Debug
clr Buffer ;Empfangspuffer löschen
clr Impulse ;Impulszähler löschen
bst Status,3 ;Parität OK ?
brtc Puls15 ;Nein -> weiter
bst Status,2 ;58 Impulse empfangen ?
brtc Puls15 ;Nein -> weiter
rcall Stellen ;empfangene Zeit übernehmen
Puls5:
clt
bld Status,2 ;Status 58 Impulse löschen
bld Status,3 ;Status Parität OK löschen
bld Status,4 ;Status Stundenparität OK löschen
Puls10:
clr Counter ;Impulslänge löschen
rjmp Puls40 ;Ende
Puls15:
bst Status,4 ;Stundenparität OK ?
brtc Puls5
rcall Zeitstellen ;nur Uhrzeit übernehmen
rjmp Puls5
Puls20:
bst Status,1 ;vorherigen Status prüfen
brts Puls40 ;vorheriger Status Low -> Ende
ldi temp1,Imp1min ;Minimalwert für "1" Impuls laden
cp Counter,temp1 ;Minimalwert unterschritten ?
brcs Puls30 ;ja -> weiter
*sts {Dcfimp},Counter ;--------> Impulslänge High speichern für Debug
cpi Impulse,28 ;beim Paritätsbit Min keine Negation
breq Puls25
cpi Impulse,35 ;beim Paritätsbit Std keine Negation
breq Puls25
cpi Impulse,58 ;beim Paritätsbit Datum keine Negation
breq Puls25
ldi Temp1,1
eor Parity,Temp1 ;Paritätsbit Negation
Puls25:
sec ;Carry setzen ( "1" empfangen )
ror Buffer ;Carry in Empfangspuffer
rcall Auswerten ;Impulse auswerten
inc Impulse ;Impulszähler erhöhen
rjmp Puls40 ;Ende
Puls30:
*sts {Dcfimp},Counter ;--------> Impulslänge Low speichern für Debug
clc ;Carry löschen ( "0" empfangen )
ror Buffer ;Carry in Empfangspuffer
rcall Auswerten ;Impulse auswerten
inc Impulse ;Impulszähler erhöhen
Puls40:
bst Status,0 ;aktuellen Status holen
bld Status,1 ;Status speichern
*sts {Dcfstatus},Status ;Variablen wieder speichern
*sts {Dcfimpulse},Impulse
*sts {Dcfcounter},Counter
*sts {Dcfbuffer},Buffer
*sts {Dcfparity},Parity
ret
;-------------------------------------------------------------------------------
Softclock: ;muss 40x pro Sekunde aufgerufen werden
*lds Temp1,{Dcfhsec}
inc Temp1 ;Hundertstel Sek erhöhen
cpi Temp1,40 ;1000ms erreicht ?
breq Soft10 ;ja -> weiter
*sts {Dcfhsec},Temp1
ret ;sonst Ende
Soft10:
clr Temp1 ;Hundertstel Sek löschen
*sts {Dcfhsec},Temp1
*lds Temp1,{_sec}
inc Temp1 ;Sekunde erhöhen
cpi Temp1,60 ;60 Sekunden erreicht ?
breq Soft20 ;ja -> weiter
*sts {_sec},Temp1
ret
Soft20:
clr Temp1 ;Sekunde löschen
*sts {_sec},Temp1
*lds Temp1,{_min}
inc Temp1 ;Minute erhöhen
cpi Temp1,60 ;60 Minuten erreicht ?
breq Soft30 ;ja -> weiter
*sts {_min},Temp1
ret
Soft30:
clr Temp1 ;Minute löschen
*sts {_min},Temp1
*lds Temp1,{_hour}
inc Temp1 ;Stunde erhöhen
cpi Temp1,24 ;24 Stunden erreicht ?
breq Soft40 ;ja -> weiter
*sts {_hour},Temp1
ret
Soft40:
clr Temp1 ;Stunde löschen
*sts {_hour},Temp1
*lds Temp1,{_dayofweek}
inc Temp1 ;Wochentag erhöhen
cpi Temp1,8 ;letzter Wochentag erreicht ?
brne Soft50 ;nein -> weiter
ldi Temp1,1 ;Wochentag auf "1" (Montag)
Soft50:
*sts {_dayofweek},Temp1
*lds Temp1,{_day} ;Tag holen
*lds Temp2,{_month} ;Monat holen
ldi zl,low(Tagdaten*2)
ldi zh,high(Tagdaten*2) ;Anzahl Tage pro Monat holen
add zl,Temp2 ;Zeiger auf aktuellen Monat
lpm ;Anzahl Tage holen
cp Temp1,r0 ;Monatsende erreicht ?
brne Soft90 ;nein -> weiter
cpi Temp2,2 ;Monatsende Februar ?
brne Soft60 ;nein -> weiter
clt ;Evtl. Schaltjahr mit 29.2.
bld Status,6 ;Status Datum nach DCF gestellt löschen
Soft60:
cpi Temp2,6 ;Monatsende Juni ?
brne Soft70 ;nein -> weiter
clt ;Zur Jahresmitte evtl. Schaltsekunde
bld Status,5 ;Status Uhr nach DCF gestellt löschen
Soft70:
ldi Temp1,1 ;Tag auf 1
cpi Temp2,12 ;Jahresende erreicht ?
brne Soft100 ;nein -> weiter
clt ;Zum Jahreswechsel evtl. Schaltsekunde
bld Status,5 ;Status Uhr nach DCF gestellt löschen
*lds Temp2,{_year} ;Jahr holen
inc Temp2 ;Jahr erhöhen
cpi Temp2,100 ;Jahr 100 erreicht ?
brne Soft80 ;nein -> Ende
clr Temp2 ;Jahr 00 setzen
Soft80:
*sts {_year},Temp2 ;speichern
ldi Temp2,1 ;Monat auf 1
rjmp Soft110
Soft90:
inc Temp1 ;Tag erhöhen
rjmp Soft110
Soft100:
inc Temp2 ;Monat erhöhen
Soft110:
*sts {_day},Temp1 ;Datum speichern
*sts {_month},Temp2
ret
Stellen:
*lds Temp1,{Dcftemp+2}
*sts {_day},Temp1 ;Tag auf empfangenen Tag
*lds Temp1,{Dcftemp+3}
*sts {_dayofweek},Temp1 ;Wochentag auf empfangenen Wochentag
*lds Temp1,{Dcftemp+4}
*sts {_month},Temp1 ;Monat auf empfangenen Monat
*lds Temp1,{Dcftemp+5}
*sts {_year},Temp1 ;Jahr auf empfangenes Jahr
set
bld Status,6 ;Status Datum nach DCF gestellt setzen
Zeitstellen:
ldi Temp1,1 ;Hundertstel zurücksetzen
*sts {Dcfhsec},Temp1 ;(1. Intervall 25ms kürzer !)
clr Temp1
*sts {_sec},Temp1 ;Sekunde auf 0 setzen
*lds Temp1,{Dcftemp}
*sts {_min},Temp1 ;Minute auf empfangene Minute
*lds Temp1,{Dcftemp+1}
*sts {_hour},Temp1 ;Stunde auf empfangene Stunde
*lds Temp1,{Dcftemp+6}
*sts {Dcfflags},Temp1 ;DCF77-Bits 15..20 aktualisieren
set
bld Status,5 ;Status Uhr nach DCF gestellt setzen
ret
Tagdaten:
.db 00, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
;-------------------------------------------------------------------------------
Auswerten:
cpi Impulse,14 ;14. Impuls
brne Aus5 ;nein -> weiter
clr Buffer
Aus5:
cpi Impulse,20 ;20. Impuls
brne Aus10 ;nein -> weiter
bst Buffer,7 ;Startbit 20 (S) selektieren
brtc Aus26 ;Fehler -> Ende
lsr Buffer ;Buffer 2x schieben, da 6 Bit
lsr Buffer
*sts {Dcftemp+6},Buffer ;Temp DCF77-Bits 15..20 schreiben
;Inhalt Buffer -> Bit0 (R) : Reserve-Antenne des DCF77-Senders
; Bit1 (A1): Ankündigung des Wechsels MEZ <-> MESZ
; Bit2 (Z1): \__ Z1/Z2: 10 = MESZ, 01 = MEZ
; Bit3 (Z2): /
; Bit4 (A2): Ankündigung einer Schaltsekunde
; Bit5 (S) : Startbit f. Zeitinformationen (immer 1)
clr Buffer
clr Parity
Aus10:
cpi Impulse,27 ;27. Impuls
brne Aus15 ;nein -> weiter
lsr Buffer ;Buffer 1x schieben, da Minute nur 7 Bit
rcall Bcd2dez ;in Dezimal wandeln
*sts {Dcftemp},Buffer ;Temp Minute schreiben
clr Buffer
Aus15:
cpi Impulse,28 ;Minuten Parität
brne Aus20
clr Temp1
bst Buffer,7 ;Paritätsbit selektieren
bld Temp1,0 ;Paritätsbit in Temp1 Bit0 kopieren
cp Temp1,Parity ;Minutenparität überprüfen
brne Aus26 ;Fehler -> Ende
clr Parity
clr Buffer
Aus20:
cpi Impulse,34 ;34. Impuls
brne Aus25 ;nein -> weiter
lsr Buffer ;Buffer 2x schieben, da Stunde nur 6 Bit
lsr Buffer
rcall Bcd2dez ;in Dezimal wandeln
*sts {Dcftemp+1},Buffer ;Temp Stunde schreiben
clr Buffer
Aus25:
cpi Impulse,35 ;Stunden Parität
brne Aus30
clr Temp1
bst Buffer,7 ;Paritätsbit selektieren
bld Temp1,0 ;Paritätsbit in Temp1 Bit0 kopieren
cp Temp1,Parity ;Stundenparität überprüfen
breq Aus27 ;Parität OK -> weiter
Aus26:
ret ;Fehler -> Ende
Aus27:
set
bld Status,4 ;Bit4 Status setzen (Stundenparität)
clr Parity
clr Buffer
Aus30:
cpi Impulse,41 ;41. Impuls
brne Aus40
lsr Buffer ;Buffer 2x schieben, da Tag nur 6 Bit
lsr Buffer
rcall Bcd2dez ;in Dezimal wandeln
*sts {Dcftemp+2},Buffer ;Temp Tag schreiben
clr Buffer
Aus40:
cpi Impulse,44 ;44. Impuls
brne Aus50
lsr Buffer ;Buffer 5x schieben, da Wochentag nur 3 Bit
lsr Buffer
lsr Buffer
lsr Buffer
lsr Buffer
rcall Bcd2dez ;in Dezimal wandeln
*sts {Dcftemp+3},Buffer ;Temp Wochentag schreiben
clr Buffer
Aus50:
cpi Impulse,49 ;49. Impuls
brne Aus60
lsr Buffer ;Buffer 3x schieben, da Monat nur 5 Bit
lsr Buffer
lsr Buffer
rcall Bcd2dez ;in Dezimal wandeln
*sts {Dcftemp+4},Buffer ;Temp Monat schreiben
clr Buffer
Aus60:
cpi Impulse,57 ;57. Impuls
brne Aus70
rcall Bcd2dez ;in Dezimal wandeln
*sts {Dcftemp+5},Buffer ;Temp Jahr schreiben
clr Buffer
Aus70:
cpi Impulse,58 ;Restparität
brne Aus80
set ;T-Bit setzen
bld Status,2 ;Bit2 Status setzen (58 Impulse)
clr Temp1
bst Buffer,7 ;Paritätsbit selektieren
bld Temp1,0 ;Paritätsbit in Temp1 Bit0 kopieren
cp Temp1,Parity ;Restparität überprüfen
brne Aus90 ;Fehler -> Ende
set ;T-Bit setzen
bld Status,3 ;Bit3 Status setzen (Parität)
Aus80:
cpi Impulse,59 ;mehr als 58 Impulse (d.h. Störimpulse)
brne Aus90
clt ;T-Bit löschen
bld Status,2 ;Bit2 Status löschen (58 Impulse)
Aus90:
ret
;-------------------------------------------------------------------------------
Bcd2dez:
mov Temp1,Buffer
andi Temp1,$0F
Bcd10:
subi Buffer,$10
brcs Bcd20
subi Temp1,$F6
rjmp Bcd10
Bcd20:
mov Buffer,Temp1
ret
[end]
Viel Erfolg!
Dirk
fosslerg
09.10.2006, 23:05
zunächst mal der grund warum der code zunächst nicht funktioniert hat:
wenn man einen 16MHz-quarz verbaut dann sollte man _nicht_ crystal=8000000 drinstehen haben ..... ](*,) ](*,) ](*,)
kaum macht man's richtig geht's auch schon (besser) :-b
nun habe ich den fehler gefunden und behoben nur um vor einer neuen ungewissheit zu stehen, die ich mir schon wieder nicht erklären kann.
verwende mittlerweile deine lib 2.52. die statusbits für parity und stundenparity gehen nach einiger zeit beide auf high, das flag für zeit und datum stellen (bit7) steht auch auf high, nur nachdem das flag für 58 impulse nicht kommt wird die zeit natürlcih nicht übernommen (sofern ich den assembler richtig lese).
was ich aber nicht verstehe- der zähler für die impulse läuft bis 255 und nix passiert- eigentlich sollte der doch irgendwann gezielt gelöscht werden?
die frage ist jetzt die- stimmt irgendwo im hauptprogramm von mir was nicht, empfang (schliesse ich eigentl. aus)?, lib (???)
(wieder) ratlose grüße
günter
Hallo Günter,
der Impulszähler darf nicht bis 255 hochzählen!
Ich würde erst nur ein "Minimalprogramm" zur Anzeige ausprobieren. Ich habe mal so ein Kurzprog hier eingestellt,- du müßtest noch deine Timer-Variante anpassen:
'Hauptprogramm:
Cls
Cursor Off
Date$ = "01.01.00"
Time$ = "00:00:00"
Sekunde = 0
'* HAUPTPROGRAMMSCHLEIFE *
Do
If Sekunde <> _sec Then
Cls
Call Showtime()
Sekunde = _sec
End If
If _min = 0 And Dcfstatus.7 = 0 Then '1x pro Stunde:
Dcfstatus.5 = 0 'Zeit inaktuell
Dcfstatus.6 = 0 'Datum inaktuell
End If
'Wenn Uhr oder Datum inaktuell, dann nach DCF stellen:
'Timer0 ist nur aktiv, solange DCF-Empfang läuft!!!
If Dcfstatus.5 = 0 Or Dcfstatus.6 = 0 Then
Dcfstatus.7 = 1
Enable Timer0
Else
Dcfstatus.7 = 0
Disable Timer0
End If
Loop
End
'* ENDE HAUPTPROGRAMM *
Sub Showtime()
Locate 1 , 1 'Zeile 1:
Lcd Time$ 'Uhrzeit
Locate 2 , 1 'Zeile 2:
Lcd Date$ 'Datum
End Sub
fosslerg
12.10.2006, 22:34
weiss jetzt nicht, wie ich den code so poste wie ihr, daher mache ich das so als text.
$regfile = "m128def.dat"
$framesize = 32
$swstack = 256
$hwstack = 64
$lib "dcf77.lib" 'LIB für DCF77
$external Dcf77
Declare Sub Dcf77
Declare Sub Lcd_print(byval Lcd_text As String , Byval Lcd_posx As Byte , Byval Lcd_posy As Byte , Byval Fontsize As Byte , Byval Lcd_fcolor As Byte , Byval Lcd_bcolor As Byte)
'----------------------------------------------------------------------
Lcd_port Alias Portb 'Port B
Ddrb = &B01100110 'Port B: 4 Pins output
Const Kommando = 0 'Eine folgendes Kommando wird durch "1" eingeleitet
Const Parameter = 1 'Eine folgende Parameterübergabe wird durch "0" eingeleitet
Const Rs = 6
Const Cs = 5
Const Sdata = 2
Const Sclk = 1 'd.h. Port B.1
Const Blau = &B00000011 'Vordefinierte Konstanten für die Farbwerte machen das Programmiererleben leichter:
Const Gelb = &B11111100
Const Rot = &B11100000
Const Gruen = &B00011100
Const Schwarz = &B00000000
Const Weiss = &B11111111
Const Hellgruen = &B00111110
Const Dunkelgruen = &B00010100
Const Dunkelrot = &B10100000
Const Dunkelblau = &B00000010
Const Hellblau = &B00011111
Const Orange = &B11111000
'================================================= ==========================
' Includes für DCF77
Config Date = Dmy , Separator = . 'deutsches Datumsformat
Config Clock = Soft 'Softclock aktivieren
' (läuft mit Timer2!)
Config Timer1 = Timer , Prescale = 8 'Timer 40Hz
Const Startwert = 15543 'Für 16MHz
Timer1 = Startwert
On Timer1 Tim1_isr 'Überlauf 40x/s
Enable Interrupts
Disable Timer1 'zunächst ausschalten
'---------------------- Pin für DCF Eingang definieren ---------------------
'Jeder Portpin kann benutzt werden.
'Auch in der "Dcf77.lib" entsprechend anpassen !!!
Config Pind.3 = Input 'DCF77 Eingang
Portd.3 = 1 'Pullup ein
Config Pind.5 = Output
Set Portd.5
Config Pind.7 = Input
Portd.7 = 1
Dim Count As Word
Count = 0
'--------------------- Variablen der DCF77.lib -----------------------------
Dim _dayofweek As Byte , Dcfstatus As Byte , Dcfflags As Byte
'_dayofweek -> 1..7 (Mo..So)
'Dcfstatus -> Bit0: intern Bit4: Stundenparität OK
' Bit1: intern Bit5: Uhr nach DCF gestellt
' Bit2: 58 Impulse empfangen Bit6: Datum nach DCF gestellt
' Bit3: Parität OK Bit7: Uhr nach DCF stellen
' ACHTUNG: Bits 0..4 NUR LESEN!!!
'Dcfflags -> Bit0 (R) : Reserve-Antenne des DCF77-Senders
' Bit1 (A1): Ankündigung des Wechsels MEZ <-> MESZ
' Bit2 (Z1): \__ Z1/Z2: 10 = MESZ, 01 = MEZ
' Bit3 (Z2): /
' Bit4 (A2): Ankündigung einer Schaltsekunde
' Bit5 (S) : Startbit f. Zeitinformationen (immer 1)
'Interne Variablen der DCF77.lib:
Dim Dcfcounter As Byte , Dcfbuffer As Byte , Dcfimpulse As Byte
Dim Dcfparity As Byte , Dcfhsec As Byte , Dcftemp(7) As Byte
Dim Dcfpau As Byte , Dcfimp As Byte 'Nur für Debug!
Dim Helper As String * 3
'---------------------------------------------------------------------------
Dcfstatus = 0
Dcfstatus.7 = 0 'Uhr nach DCF stellen: AUS
Dcfstatus.5 = 1 'Uhrzeit inaktuell
Dcfstatus.6 = 1 'Datum inaktuell
' End für DCF77
'================================================= ==========================
Date$ = "01.01.06"
Time$ = "01:00:00"
Gosub Lcd_init
Gosub Lcd_cls 'Display löschen
'-------------------------------------------------------------------------------
'Hauptprogramm
'-------------------------------------------------------------------------------
Do 'endless loop
Call Lcd_print( "started" , 1 , 10 , 0 , Weiss , Blau)
' If _min = 0 And Dcfstatus.7 = 0 Then '1x pro Stunde:
If Pind.7 = 0 Then
Dcfstatus.5 = 0 'Zeit inaktuell
Dcfstatus.6 = 0 'Datum inaktuell
End If
'Wenn Uhr oder Datum inaktuell, dann nach DCF stellen:
'Timer1 ist nur aktiv, solange DCF-Empfang läuft!!!
If Dcfstatus.5 = 0 Or Dcfstatus.6 = 0 Then
Dcfstatus.7 = 1
Enable Timer1
Call Lcd_print( "Ena" , 1 , 3 , 0 , Weiss , Blau)
Helper = Str(dcfstatus)
Call Lcd_print(helper , 1 , 4 , 0 , Rot , Weiss)
Else
Dcfstatus.7 = 0
Disable Timer1
Call Lcd_print( "Dis" , 5 , 3 , 0 , Weiss , Rot)
End If
Call Lcd_print(time$ , 1 , 1 , 0 , Weiss , Blau)
Call Lcd_print(date$ , 1 , 2 , 0 , Weiss , Blau)
Helper = Str(dcfstatus)
Call Lcd_print(helper , 1 , 4 , 0 , Rot , Weiss)
Helper = Str(dcfcounter)
Call Lcd_print(helper , 1 , 6 , 0 , Rot , Weiss)
Helper = Str(dcfbuffer)
Call Lcd_print(helper , 6 , 6 , 0 , Rot , Weiss)
Helper = Str(dcfimpulse)
Call Lcd_print(helper , 11 , 6 , 0 , Rot , Weiss)
Helper = Str(dcfparity)
Call Lcd_print(helper , 16 , 6 , 0 , Rot , Weiss)
Helper = Str(dcfpau)
Call Lcd_print(helper , 1 , 7 , 0 , Gruen , Weiss)
Helper = Str(dcfimp)
Call Lcd_print(helper , 6 , 7 , 0 , Gruen , Weiss)
If Pind.3 = 0 Then
Portd.5 = 0
Else
Portd.5 = 1
End If
Loop
End 'end program
'================================================= ==============================
Tim1_isr:
Call Dcf77
Return
die restlichen definitionen für dasd farbdisplay habe ich weggelöscht, weil die tun nichts zur sache. sonst wars das aber.
mit pinD.7 starte ich den DCF, später mal wird das dann über die zeit erfolgen (aber das wäre für die tests jetzt recht unpraktisch)
ich kann mir leider nicht erklären warum der impulse-counter über die 58 hinausläuft obwohl zu diesem zeitpunktdie zwei parity's auf 1 stehen.
vielen dank für allfällige tips
günter
Hallo Günter,
für Codeblöcke kannst du oben "Code" anklicken, dann den Code einfügen und wieder auf "Code" klicken. Am Anfang wird dann (Code) und am Ende (/Code) eingefügt (hier runde Klammern anstelle der eckigen!).
Zu deinem Prog:
1. Ich kann nicht erkennen, wie du Pind.7 beschaltet hast. Wenn er dauerhaft auf GND liegt, müßte der Decoder ständig AN sein und die Zeit irgendwann übernehmen.
2. Die ISR ist nicht richtig! Sie muss so aussehen:
Tim1_isr:
[highlight=red:19a9190e4a]Timer1 = Startwert[/highlight:19a9190e4a]
Call Dcf77
Return
Gruß Dirk
fosslerg
13.10.2006, 22:06
hallo dirk,
vielen dank für deine nachhilfe. kleine ursache, grosse wirkung.
deine letzter tip mit dem startwert war's.
funktioniert bestens!
lg günter
Hallo Günter,
habe auch das Display von Display3000.
Ich würde gern den funktionierenden Code mit Displayansteuerung erben.
Ist es möglich den Code zubekommen?
MfG
fosslerg
17.10.2006, 08:36
sorry, hat ein bisserl gedauert (war nicht da).
einige anmerkungen dazu:
verwendete lib ist die 2.50 von Dirk (danke!) lib spare ich mir an dieser stelle- port anpassen nicht vergessen
chip der M128 auf dem D062x von display3000
16MHz-quarz (achtung bei timer-def und $crystal)
dcf-empfang wird getriggert mit D.7 (untere taste am D062x)
dcf selbst ist der conrad-empfänger, mit invertiertem ausgang an D.3
D.5 bildet das D.3 signal auf einer LED ab.
einige ausgaben am display zwecks check ob und was das ding tut.
habe versucht den code einzufügen, falle aber über die längenbegrenzung des beitrages drüber. schicke dir den code aber gerne auch per mail direkt zu. bei interesse schicke mir eine nachricht mit deiner adresse & der code kommt.
viel spass dabei.
lg günter
bertl100
27.10.2006, 22:00
Hallöchen
Leider klappts bei mir noch immer nicht
Die Uhr zählt schön im Sekundentakt hoch, aber der DCF aktualisiert einfach nicht. Ich hab bereits 2 verschiedene Pins verwendet mit entsprechender Adresse, die in der lib einzutragen ist( Soweit ich weiß sind es 2 Einträge).
Den Rest hab ich wie hier beschrieben gemacht.
Hilfe!!!!!
Hallo Bertl100,
poste doch 'mal dein kompl. Prog, dann könnte man nach evtl. Ergänzungen gucken!
Gruß Dirk
bertl100
28.10.2006, 11:46
Ich verwende das RNMEga2560 Modul von Robotikhardware
Momentan hab ich den DCF Empfänger auf Portl.6
Die modofizierte lib.
copyright = W.Krueger
comment = DCF77-Decoder und Softclock
libversion = 2.52 (D. Ottensmeyer)
date = 07.10.2006
statement = ----------------------------------
statement = muss alle 25ms ausgeführt werden !
statement = Neu: komplette Paritätsprüfung
statement = Neu: Auswertung der Bits 15..20
statement = Neu: erweiterte Softclock
statement = ----------------------------------
[Dcf77_soft]
.equ DCF_Port = $109 ;$10 = Portd
.equ DCF_Pin = 6 ;3 = Pin 3
.equ Imp0min = 70 ;minimale Länge des Minutenimpulses
.equ Imp1min = 6 ;minimale Länge des "1" Impulses
;alles darunter wird als "0" Impuls gewertet
.def Temp1 = r16
.def Temp2 = r17
.def Status = r18
;Bit0 = aktueller DCF Status
;Bit1 = vorheriger DCF Status
;Bit2 = 58 Impulse empfangen
;Bit3 = Parität OK
;Bit4 = Stundenparität OK
;Bit5 = Uhr nach DCF gestellt
;Bit6 = Datum nach DCF gestellt
;Bit7 = Uhr nach DCF stellen
.def Impulse = r19
.def Counter = r20
.def Buffer = r21
.def Parity = r22
Dcf77_soft:
*lds Status,{Dcfstatus} ;Status laden
rcall Softclock ;Softclock bearbeiten
bst Status,7 ;Status Uhr nach DCF stellen ?
brts Puls0 ;ja -> weiter
*sts {Dcfstatus},Status
ret
;-------------------------------------------------------------------------------
[Dcf77]
.equ DCF_Port = $109 ;$10 = Pind
.equ DCF_Pin = 6 ;3 = Pin 3
.equ Imp0min = 70 ;minimale Länge des Minutenimpulses
.equ Imp1min = 6 ;minimale Länge des "1" Impulses
;alles darunter wird als "0" Impuls gewertet
.def Temp1 = r16
.def Temp2 = r17
.def Status = r18
;Bit0 = aktueller DCF Status
;Bit1 = vorheriger DCF Status
;Bit2 = 58 Impulse empfangen
;Bit3 = Parität OK
;Bit4 = Stundenparität OK
;Bit5 = Uhr nach DCF gestellt
;Bit6 = Datum nach DCF gestellt
;Bit7 = Uhr nach DCF stellen
.def Impulse = r19
.def Counter = r20
.def Buffer = r21
.def Parity = r22
Dcf77:
*lds Status,{Dcfstatus} ;Status laden
bst Status,7 ;Status Uhr nach DCF stellen ?
brts Puls0 ;ja -> weiter
ret
Puls0:
*lds Impulse,{Dcfimpulse} ;Variablen laden
*lds Counter,{Dcfcounter}
*lds Buffer,{Dcfbuffer}
*lds Parity,{Dcfparity}
in temp1,Dcf_Port ;DCF Port lesen
bst temp1,Dcf_Pin ;Status holen
bld Status,0 ;aktuellen Status speichern
inc Counter ;Impulslänge erhöhen
bst Status,0 ;aktuellen Status prüfen
brts Puls20 ;Status Low -> weiter
bst Status,1 ;vorherigen Status prüfen
brtc Puls40 ;vorheriger Status Low -> Ende
ldi temp1,Imp0min ;Minutenimpuls Minimalwert laden
cp Counter,temp1 ;Impulslänge Minimalwert überschritten
brcs Puls10 ;nein -> weiter
*sts {Dcfpau},Counter ;--------> Minutenimpulslänge speichern für Debug
clr Buffer ;Empfangspuffer löschen
clr Impulse ;Impulszähler löschen
bst Status,3 ;Parität OK ?
brtc Puls15 ;Nein -> weiter
bst Status,2 ;58 Impulse empfangen ?
brtc Puls15 ;Nein -> weiter
rcall Stellen ;empfangene Zeit übernehmen
Puls5:
clt
bld Status,2 ;Status 58 Impulse löschen
bld Status,3 ;Status Parität OK löschen
bld Status,4 ;Status Stundenparität OK löschen
Puls10:
clr Counter ;Impulslänge löschen
rjmp Puls40 ;Ende
Puls15:
bst Status,4 ;Stundenparität OK ?
brtc Puls5
rcall Zeitstellen ;nur Uhrzeit übernehmen
rjmp Puls5
Puls20:
bst Status,1 ;vorherigen Status prüfen
brts Puls40 ;vorheriger Status Low -> Ende
ldi temp1,Imp1min ;Minimalwert für "1" Impuls laden
cp Counter,temp1 ;Minimalwert unterschritten ?
brcs Puls30 ;ja -> weiter
*sts {Dcfimp},Counter ;--------> Impulslänge High speichern für Debug
cpi Impulse,28 ;beim Paritätsbit Min keine Negation
breq Puls25
cpi Impulse,35 ;beim Paritätsbit Std keine Negation
breq Puls25
cpi Impulse,58 ;beim Paritätsbit Datum keine Negation
breq Puls25
ldi Temp1,1
eor Parity,Temp1 ;Paritätsbit Negation
Puls25:
sec ;Carry setzen ( "1" empfangen )
ror Buffer ;Carry in Empfangspuffer
rcall Auswerten ;Impulse auswerten
inc Impulse ;Impulszähler erhöhen
rjmp Puls40 ;Ende
Puls30:
*sts {Dcfimp},Counter ;--------> Impulslänge Low speichern für Debug
clc ;Carry löschen ( "0" empfangen )
ror Buffer ;Carry in Empfangspuffer
rcall Auswerten ;Impulse auswerten
inc Impulse ;Impulszähler erhöhen
Puls40:
bst Status,0 ;aktuellen Status holen
bld Status,1 ;Status speichern
*sts {Dcfstatus},Status ;Variablen wieder speichern
*sts {Dcfimpulse},Impulse
*sts {Dcfcounter},Counter
*sts {Dcfbuffer},Buffer
*sts {Dcfparity},Parity
ret
;-------------------------------------------------------------------------------
Softclock: ;muss 40x pro Sekunde aufgerufen werden
*lds Temp1,{Dcfhsec}
inc Temp1 ;Hundertstel Sek erhöhen
cpi Temp1,40 ;1000ms erreicht ?
breq Soft10 ;ja -> weiter
*sts {Dcfhsec},Temp1
ret ;sonst Ende
Soft10:
clr Temp1 ;Hundertstel Sek löschen
*sts {Dcfhsec},Temp1
*lds Temp1,{_sec}
inc Temp1 ;Sekunde erhöhen
cpi Temp1,60 ;60 Sekunden erreicht ?
breq Soft20 ;ja -> weiter
*sts {_sec},Temp1
ret
Soft20:
clr Temp1 ;Sekunde löschen
*sts {_sec},Temp1
*lds Temp1,{_min}
inc Temp1 ;Minute erhöhen
cpi Temp1,60 ;60 Minuten erreicht ?
breq Soft30 ;ja -> weiter
*sts {_min},Temp1
ret
Soft30:
clr Temp1 ;Minute löschen
*sts {_min},Temp1
*lds Temp1,{_hour}
inc Temp1 ;Stunde erhöhen
cpi Temp1,24 ;24 Stunden erreicht ?
breq Soft40 ;ja -> weiter
*sts {_hour},Temp1
ret
Soft40:
clr Temp1 ;Stunde löschen
*sts {_hour},Temp1
*lds Temp1,{_dayofweek}
inc Temp1 ;Wochentag erhöhen
cpi Temp1,8 ;letzter Wochentag erreicht ?
brne Soft50 ;nein -> weiter
ldi Temp1,1 ;Wochentag auf "1" (Montag)
Soft50:
*sts {_dayofweek},Temp1
*lds Temp1,{_day} ;Tag holen
*lds Temp2,{_month} ;Monat holen
ldi zl,low(Tagdaten*2)
ldi zh,high(Tagdaten*2) ;Anzahl Tage pro Monat holen
add zl,Temp2 ;Zeiger auf aktuellen Monat
lpm ;Anzahl Tage holen
cp Temp1,r0 ;Monatsende erreicht ?
brne Soft90 ;nein -> weiter
cpi Temp2,2 ;Monatsende Februar ?
brne Soft60 ;nein -> weiter
clt ;Evtl. Schaltjahr mit 29.2.
bld Status,6 ;Status Datum nach DCF gestellt löschen
Soft60:
cpi Temp2,6 ;Monatsende Juni ?
brne Soft70 ;nein -> weiter
clt ;Zur Jahresmitte evtl. Schaltsekunde
bld Status,5 ;Status Uhr nach DCF gestellt löschen
Soft70:
ldi Temp1,1 ;Tag auf 1
cpi Temp2,12 ;Jahresende erreicht ?
brne Soft100 ;nein -> weiter
clt ;Zum Jahreswechsel evtl. Schaltsekunde
bld Status,5 ;Status Uhr nach DCF gestellt löschen
*lds Temp2,{_year} ;Jahr holen
inc Temp2 ;Jahr erhöhen
cpi Temp2,100 ;Jahr 100 erreicht ?
brne Soft80 ;nein -> Ende
clr Temp2 ;Jahr 00 setzen
Soft80:
*sts {_year},Temp2 ;speichern
ldi Temp2,1 ;Monat auf 1
rjmp Soft110
Soft90:
inc Temp1 ;Tag erhöhen
rjmp Soft110
Soft100:
inc Temp2 ;Monat erhöhen
Soft110:
*sts {_day},Temp1 ;Datum speichern
*sts {_month},Temp2
ret
Stellen:
*lds Temp1,{Dcftemp+2}
*sts {_day},Temp1 ;Tag auf empfangenen Tag
*lds Temp1,{Dcftemp+3}
*sts {_dayofweek},Temp1 ;Wochentag auf empfangenen Wochentag
*lds Temp1,{Dcftemp+4}
*sts {_month},Temp1 ;Monat auf empfangenen Monat
*lds Temp1,{Dcftemp+5}
*sts {_year},Temp1 ;Jahr auf empfangenes Jahr
set
bld Status,6 ;Status Datum nach DCF gestellt setzen
Zeitstellen:
ldi Temp1,1 ;Hundertstel zurücksetzen
*sts {Dcfhsec},Temp1 ;(1. Intervall 25ms kürzer !)
clr Temp1
*sts {_sec},Temp1 ;Sekunde auf 0 setzen
*lds Temp1,{Dcftemp}
*sts {_min},Temp1 ;Minute auf empfangene Minute
*lds Temp1,{Dcftemp+1}
*sts {_hour},Temp1 ;Stunde auf empfangene Stunde
*lds Temp1,{Dcftemp+6}
*sts {Dcfflags},Temp1 ;DCF77-Bits 15..20 aktualisieren
set
bld Status,5 ;Status Uhr nach DCF gestellt setzen
ret
Tagdaten:
.db 00, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
;-------------------------------------------------------------------------------
Auswerten:
cpi Impulse,14 ;14. Impuls
brne Aus5 ;nein -> weiter
clr Buffer
Aus5:
cpi Impulse,20 ;20. Impuls
brne Aus10 ;nein -> weiter
bst Buffer,7 ;Startbit 20 (S) selektieren
brtc Aus26 ;Fehler -> Ende
lsr Buffer ;Buffer 2x schieben, da 6 Bit
lsr Buffer
*sts {Dcftemp+6},Buffer ;Temp DCF77-Bits 15..20 schreiben
;Inhalt Buffer -> Bit0 (R) : Reserve-Antenne des DCF77-Senders
; Bit1 (A1): Ankündigung des Wechsels MEZ <-> MESZ
; Bit2 (Z1): \__ Z1/Z2: 10 = MESZ, 01 = MEZ
; Bit3 (Z2): /
; Bit4 (A2): Ankündigung einer Schaltsekunde
; Bit5 (S) : Startbit f. Zeitinformationen (immer 1)
clr Buffer
clr Parity
Aus10:
cpi Impulse,27 ;27. Impuls
brne Aus15 ;nein -> weiter
lsr Buffer ;Buffer 1x schieben, da Minute nur 7 Bit
rcall Bcd2dez ;in Dezimal wandeln
*sts {Dcftemp},Buffer ;Temp Minute schreiben
clr Buffer
Aus15:
cpi Impulse,28 ;Minuten Parität
brne Aus20
clr Temp1
bst Buffer,7 ;Paritätsbit selektieren
bld Temp1,0 ;Paritätsbit in Temp1 Bit0 kopieren
cp Temp1,Parity ;Minutenparität überprüfen
brne Aus26 ;Fehler -> Ende
clr Parity
clr Buffer
Aus20:
cpi Impulse,34 ;34. Impuls
brne Aus25 ;nein -> weiter
lsr Buffer ;Buffer 2x schieben, da Stunde nur 6 Bit
lsr Buffer
rcall Bcd2dez ;in Dezimal wandeln
*sts {Dcftemp+1},Buffer ;Temp Stunde schreiben
clr Buffer
Aus25:
cpi Impulse,35 ;Stunden Parität
brne Aus30
clr Temp1
bst Buffer,7 ;Paritätsbit selektieren
bld Temp1,0 ;Paritätsbit in Temp1 Bit0 kopieren
cp Temp1,Parity ;Stundenparität überprüfen
breq Aus27 ;Parität OK -> weiter
Aus26:
ret ;Fehler -> Ende
Aus27:
set
bld Status,4 ;Bit4 Status setzen (Stundenparität)
clr Parity
clr Buffer
Aus30:
cpi Impulse,41 ;41. Impuls
brne Aus40
lsr Buffer ;Buffer 2x schieben, da Tag nur 6 Bit
lsr Buffer
rcall Bcd2dez ;in Dezimal wandeln
*sts {Dcftemp+2},Buffer ;Temp Tag schreiben
clr Buffer
Aus40:
cpi Impulse,44 ;44. Impuls
brne Aus50
lsr Buffer ;Buffer 5x schieben, da Wochentag nur 3 Bit
lsr Buffer
lsr Buffer
lsr Buffer
lsr Buffer
rcall Bcd2dez ;in Dezimal wandeln
*sts {Dcftemp+3},Buffer ;Temp Wochentag schreiben
clr Buffer
Aus50:
cpi Impulse,49 ;49. Impuls
brne Aus60
lsr Buffer ;Buffer 3x schieben, da Monat nur 5 Bit
lsr Buffer
lsr Buffer
rcall Bcd2dez ;in Dezimal wandeln
*sts {Dcftemp+4},Buffer ;Temp Monat schreiben
clr Buffer
Aus60:
cpi Impulse,57 ;57. Impuls
brne Aus70
rcall Bcd2dez ;in Dezimal wandeln
*sts {Dcftemp+5},Buffer ;Temp Jahr schreiben
clr Buffer
Aus70:
cpi Impulse,58 ;Restparität
brne Aus80
set ;T-Bit setzen
bld Status,2 ;Bit2 Status setzen (58 Impulse)
clr Temp1
bst Buffer,7 ;Paritätsbit selektieren
bld Temp1,0 ;Paritätsbit in Temp1 Bit0 kopieren
cp Temp1,Parity ;Restparität überprüfen
brne Aus90 ;Fehler -> Ende
set ;T-Bit setzen
bld Status,3 ;Bit3 Status setzen (Parität)
Aus80:
cpi Impulse,59 ;mehr als 58 Impulse (d.h. Störimpulse)
brne Aus90
clt ;T-Bit löschen
bld Status,2 ;Bit2 Status löschen (58 Impulse)
Aus90:
ret
;-------------------------------------------------------------------------------
Bcd2dez:
mov Temp1,Buffer
andi Temp1,$0F
Bcd10:
subi Buffer,$10
brcs Bcd20
subi Temp1,$F6
rjmp Bcd10
Bcd20:
mov Buffer,Temp1
ret
[end]
bertl100
28.10.2006, 12:38
Muß der Timer 2 für die RTC nicht konfiguriert werden??
Hallo bertl100,
dies hier in der LIB kann ja nicht sein:
.equ DCF_Port = $109 ;$10 = Portd
Du müßtest das $109 durch den richtigen Wert für den PinXY ersetzen. Habe gerade nicht die Doku zum 2560 dabei. Sieh 'mal dort nach!
Gruss Dirk
bertl100
01.11.2006, 17:06
So, ich bin jetzt soweit dass ich etwas von der lib verstehe.
Die Uhr läuft wunderbar und ich lass mir die statusbits 3 bis 5 anzeigen.
Problem:
Jedesmal wenn status.5=1 dann wird meine Uhr auf 00:00:00 zurückgestellt.
Kann mir wer helfen??
bertl100
01.11.2006, 17:18
Alle 24 Sekunden passiert das
Hallo bertl100,
hm, so ist kein Prob zu erkennen.
Ich würde, um den Fehler einzugrenzen, die LCD-Ausgaben komplett durch Print ersetzen und die Ausgabe am Hyperterminal ansehen.
Klappt's damit?
Gruß Dirk
bertl100
01.11.2006, 18:03
Ich hab keine normale RS232 Schnittstelle drauf sondern nur 3 Pins .
Einen Stecker dafür hab ich nicht.
Momentan ist es so, dass ab und zu eine unsinnige Zeit angezeigt wird
45:63:12
Hallo bertl100,
probier 'mal diese vorherige Version:
copyright = W.Krueger
comment = DCF77-Decoder und Softclock
libversion = 2.51 (D. Ottensmeyer)
date = 29.09.2006
statement = ----------------------------------
statement = muss alle 25ms ausgeführt werden !
statement = Neu: komplette Paritätsprüfung
statement = Neu: Auswertung der Bits 15..20
statement = Neu: erweiterte Softclock
statement = ----------------------------------
[Dcf77_soft]
.equ DCF_Port = $10 ;$10 = Portd
.equ DCF_Pin = 3 ;3 = Pin 3
.equ Imp0min = 70 ;minimale Länge des Minutenimpulses
.equ Imp1min = 6 ;minimale Länge des "1" Impulses
;alles darunter wird als "0" Impuls gewertet
.def Temp1 = r16
.def Temp2 = r17
.def Status = r18
;Bit0 = aktueller DCF Status
;Bit1 = vorheriger DCF Status
;Bit2 = 58 Impulse empfangen
;Bit3 = Parität OK
;Bit4 = Stundenparität OK
;Bit5 = Uhr nach DCF gestellt
;Bit6 = Datum nach DCF gestellt
;Bit7 = Uhr nach DCF stellen
.def Impulse = r19
.def Counter = r20
.def Buffer = r21
.def Parity = r22
Dcf77_soft:
*lds Status,{Dcfstatus} ;Status laden
rcall Softclock ;Softclock bearbeiten
bst Status,7 ;Status Uhr nach DCF stellen ?
brts Puls0 ;ja -> weiter
*sts {Dcfstatus},Status
ret
;-------------------------------------------------------------------------------
[Dcf77]
.equ DCF_Port = $10 ;$10 = Pind
.equ DCF_Pin = 3 ;3 = Pin 3
.equ Imp0min = 70 ;minimale Länge des Minutenimpulses
.equ Imp1min = 6 ;minimale Länge des "1" Impulses
;alles darunter wird als "0" Impuls gewertet
.def Temp1 = r16
.def Temp2 = r17
.def Status = r18
;Bit0 = aktueller DCF Status
;Bit1 = vorheriger DCF Status
;Bit2 = 58 Impulse empfangen
;Bit3 = Parität OK
;Bit4 = Stundenparität OK
;Bit5 = Uhr nach DCF gestellt
;Bit6 = Datum nach DCF gestellt
;Bit7 = Uhr nach DCF stellen
.def Impulse = r19
.def Counter = r20
.def Buffer = r21
.def Parity = r22
Dcf77:
*lds Status,{Dcfstatus} ;Status laden
bst Status,7 ;Status Uhr nach DCF stellen ?
brts Puls0 ;ja -> weiter
ret
Puls0:
*lds Impulse,{Dcfimpulse} ;Variablen laden
*lds Counter,{Dcfcounter}
*lds Buffer,{Dcfbuffer}
*lds Parity,{Dcfparity}
in temp1,Dcf_Port ;DCF Port lesen
bst temp1,Dcf_Pin ;Status holen
bld Status,0 ;aktuellen Status speichern
inc Counter ;Impulslänge erhöhen
bst Status,0 ;aktuellen Status prüfen
brts Puls20 ;Status Low -> weiter
bst Status,1 ;vorherigen Status prüfen
brtc Puls40 ;vorheriger Status Low -> Ende
ldi temp1,Imp0min ;Minutenimpuls Minimalwert laden
cp Counter,temp1 ;Impulslänge Minimalwert überschritten
brcs Puls10 ;nein -> weiter
*sts {Dcfpau},Counter ;--------> Minutenimpulslänge speichern für Debug
clr Buffer ;Empfangspuffer löschen
clr Impulse ;Impulszähler löschen
bst Status,3 ;Parität OK ?
brtc Puls5 ;Nein -> weiter
bst Status,2 ;58 Impulse empfangen ?
brtc Puls5 ;Nein -> weiter
rcall Stellen ;empfangene Zeit übernehmen
Puls5:
clt
bld Status,2 ;Status 58 Impulse löschen
bld Status,3 ;Status Parität OK löschen
bld Status,4 ;Status Stundenparität OK löschen
Puls10:
clr Counter ;Impulslänge löschen
rjmp Puls40 ;Ende
Puls20:
bst Status,1 ;vorherigen Status prüfen
brts Puls40 ;vorheriger Status Low -> Ende
ldi temp1,Imp1min ;Minimalwert für "1" Impuls laden
cp Counter,temp1 ;Minimalwert unterschritten ?
brcs Puls30 ;ja -> weiter
*sts {Dcfimp},Counter ;--------> Impulslänge High speichern für Debug
cpi Impulse,28 ;beim Paritätsbit Min keine Negation
breq Puls25
cpi Impulse,35 ;beim Paritätsbit Std keine Negation
breq Puls25
cpi Impulse,58 ;beim Paritätsbit Datum keine Negation
breq Puls25
ldi Temp1,1
eor Parity,Temp1 ;Paritätsbit Negation
Puls25:
sec ;Carry setzen ( "1" empfangen )
ror Buffer ;Carry in Empfangspuffer
rcall Auswerten ;Impulse auswerten
inc Impulse ;Impulszähler erhöhen
rjmp Puls40 ;Ende
Puls30:
*sts {Dcfimp},Counter ;--------> Impulslänge Low speichern für Debug
clc ;Carry löschen ( "0" empfangen )
ror Buffer ;Carry in Empfangspuffer
rcall Auswerten ;Impulse auswerten
inc Impulse ;Impulszähler erhöhen
Puls40:
bst Status,0 ;aktuellen Status holen
bld Status,1 ;Status speichern
*sts {Dcfstatus},Status ;Variablen wieder speichern
*sts {Dcfimpulse},Impulse
*sts {Dcfcounter},Counter
*sts {Dcfbuffer},Buffer
*sts {Dcfparity},Parity
ret
;-------------------------------------------------------------------------------
Softclock: ;muss 40x pro Sekunde aufgerufen werden
*lds Temp1,{Dcfhsec}
inc Temp1 ;Hundertstel Sek erhöhen
cpi Temp1,40 ;1000ms erreicht ?
breq Soft10 ;ja -> weiter
*sts {Dcfhsec},Temp1
ret ;sonst Ende
Soft10:
clr Temp1 ;Hundertstel Sek löschen
*sts {Dcfhsec},Temp1
*lds Temp1,{_sec}
inc Temp1 ;Sekunde erhöhen
cpi Temp1,60 ;60 Sekunden erreicht ?
breq Soft20 ;ja -> weiter
*sts {_sec},Temp1
ret
Soft20:
clr Temp1 ;Sekunde löschen
*sts {_sec},Temp1
*lds Temp1,{_min}
inc Temp1 ;Minute erhöhen
cpi Temp1,60 ;60 Minuten erreicht ?
breq Soft30 ;ja -> weiter
*sts {_min},Temp1
ret
Soft30:
clr Temp1 ;Minute löschen
*sts {_min},Temp1
*lds Temp1,{_hour}
inc Temp1 ;Stunde erhöhen
cpi Temp1,24 ;24 Stunden erreicht ?
breq Soft40 ;ja -> weiter
*sts {_hour},Temp1
ret
Soft40:
clr Temp1 ;Stunde löschen
*sts {_hour},Temp1
*lds Temp1,{_dayofweek}
inc Temp1 ;Wochentag erhöhen
cpi Temp1,8 ;letzter Wochentag erreicht ?
brne Soft50 ;nein -> weiter
ldi Temp1,1 ;Wochentag auf "1" (Montag)
Soft50:
*sts {_dayofweek},Temp1
*lds Temp1,{_day} ;Tag holen
*lds Temp2,{_month} ;Monat holen
ldi zl,low(Tagdaten*2)
ldi zh,high(Tagdaten*2) ;Anzahl Tage pro Monat holen
add zl,Temp2 ;Zeiger auf aktuellen Monat
lpm ;Anzahl Tage holen
cp Temp1,r0 ;Monatsende erreicht ?
brne Soft90 ;nein -> weiter
cpi Temp2,2 ;Monatsende Februar ?
brne Soft60 ;nein -> weiter
clt ;Evtl. Schaltjahr mit 29.2.
bld Status,6 ;Status Datum nach DCF gestellt löschen
Soft60:
cpi Temp2,6 ;Monatsende Juni ?
brne Soft70 ;nein -> weiter
clt ;Zur Jahresmitte evtl. Schaltsekunde
bld Status,5 ;Status Uhr nach DCF gestellt löschen
Soft70:
ldi Temp1,1 ;Tag auf 1
cpi Temp2,12 ;Jahresende erreicht ?
brne Soft100 ;nein -> weiter
clt ;Zum Jahreswechsel evtl. Schaltsekunde
bld Status,5 ;Status Uhr nach DCF gestellt löschen
*lds Temp2,{_year} ;Jahr holen
inc Temp2 ;Jahr erhöhen
cpi Temp2,100 ;Jahr 100 erreicht ?
brne Soft80 ;nein -> Ende
clr Temp2 ;Jahr 00 setzen
Soft80:
*sts {_year},Temp2 ;speichern
ldi Temp2,1 ;Monat auf 1
rjmp Soft110
Soft90:
inc Temp1 ;Tag erhöhen
rjmp Soft110
Soft100:
inc Temp2 ;Monat erhöhen
Soft110:
*sts {_day},Temp1 ;Datum speichern
*sts {_month},Temp2
ret
Stellen:
*lds Temp1,{Dcftemp+2}
*sts {_day},Temp1 ;Tag auf empfangenen Tag
*lds Temp1,{Dcftemp+3}
*sts {_dayofweek},Temp1 ;Wochentag auf empfangenen Wochentag
*lds Temp1,{Dcftemp+4}
*sts {_month},Temp1 ;Monat auf empfangenen Monat
*lds Temp1,{Dcftemp+5}
*sts {_year},Temp1 ;Jahr auf empfangenes Jahr
set
bld Status,6 ;Status Datum nach DCF gestellt setzen
ldi Temp1,1 ;Hundertstel zurücksetzen
*sts {Dcfhsec},Temp1 ;(1. Intervall 25ms kürzer !)
clr Temp1
*sts {_sec},Temp1 ;Sekunde auf 0 setzen
*lds Temp1,{Dcftemp}
*sts {_min},Temp1 ;Minute auf empfangene Minute
*lds Temp1,{Dcftemp+1}
*sts {_hour},Temp1 ;Stunde auf empfangene Stunde
*lds Temp1,{Dcftemp+6}
*sts {Dcfflags},Temp1 ;DCF77-Bits 15..20 aktualisieren
set
bld Status,5 ;Status Uhr nach DCF gestellt setzen
ret
Tagdaten:
.db 00, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
;-------------------------------------------------------------------------------
Auswerten:
cpi Impulse,14 ;14. Impuls
brne Aus5 ;nein -> weiter
clr Buffer
Aus5:
cpi Impulse,20 ;20. Impuls
brne Aus10 ;nein -> weiter
bst Buffer,7 ;Startbit 20 (S) selektieren
brtc Aus26 ;Fehler -> Ende
lsr Buffer ;Buffer 2x schieben, da 6 Bit
lsr Buffer
*sts {Dcftemp+6},Buffer ;Temp DCF77-Bits 15..20 schreiben
;Inhalt Buffer -> Bit0 (R) : Reserve-Antenne des DCF77-Senders
; Bit1 (A1): Ankündigung des Wechsels MEZ <-> MESZ
; Bit2 (Z1): \__ Z1/Z2: 10 = MESZ, 01 = MEZ
; Bit3 (Z2): /
; Bit4 (A2): Ankündigung einer Schaltsekunde
; Bit5 (S) : Startbit f. Zeitinformationen (immer 1)
clr Buffer
clr Parity
Aus10:
cpi Impulse,27 ;27. Impuls
brne Aus15 ;nein -> weiter
lsr Buffer ;Buffer 1x schieben, da Minute nur 7 Bit
rcall Bcd2dez ;in Dezimal wandeln
*sts {Dcftemp},Buffer ;Temp Minute schreiben
clr Buffer
Aus15:
cpi Impulse,28 ;Minuten Parität
brne Aus20
clr Temp1
bst Buffer,7 ;Paritätsbit selektieren
bld Temp1,0 ;Paritätsbit in Temp1 Bit0 kopieren
cp Temp1,Parity ;Minutenparität überprüfen
brne Aus26 ;Fehler -> Ende
clr Parity
clr Buffer
Aus20:
cpi Impulse,34 ;34. Impuls
brne Aus25 ;nein -> weiter
lsr Buffer ;Buffer 2x schieben, da Stunde nur 6 Bit
lsr Buffer
rcall Bcd2dez ;in Dezimal wandeln
*sts {Dcftemp+1},Buffer ;Temp Stunde schreiben
clr Buffer
Aus25:
cpi Impulse,35 ;Stunden Parität
brne Aus30
clr Temp1
bst Buffer,7 ;Paritätsbit selektieren
bld Temp1,0 ;Paritätsbit in Temp1 Bit0 kopieren
cp Temp1,Parity ;Stundenparität überprüfen
breq Aus27 ;Parität OK -> weiter
Aus26:
ret ;Fehler -> Ende
Aus27:
set
bld Status,4 ;Bit4 Status setzen (Stundenparität)
clr Parity
clr Buffer
Aus30:
cpi Impulse,41 ;41. Impuls
brne Aus40
lsr Buffer ;Buffer 2x schieben, da Tag nur 6 Bit
lsr Buffer
rcall Bcd2dez ;in Dezimal wandeln
*sts {Dcftemp+2},Buffer ;Temp Tag schreiben
clr Buffer
Aus40:
cpi Impulse,44 ;44. Impuls
brne Aus50
lsr Buffer ;Buffer 5x schieben, da Wochentag nur 3 Bit
lsr Buffer
lsr Buffer
lsr Buffer
lsr Buffer
rcall Bcd2dez ;in Dezimal wandeln
*sts {Dcftemp+3},Buffer ;Temp Wochentag schreiben
clr Buffer
Aus50:
cpi Impulse,49 ;49. Impuls
brne Aus60
lsr Buffer ;Buffer 3x schieben, da Monat nur 5 Bit
lsr Buffer
lsr Buffer
rcall Bcd2dez ;in Dezimal wandeln
*sts {Dcftemp+4},Buffer ;Temp Monat schreiben
clr Buffer
Aus60:
cpi Impulse,57 ;57. Impuls
brne Aus70
rcall Bcd2dez ;in Dezimal wandeln
*sts {Dcftemp+5},Buffer ;Temp Jahr schreiben
clr Buffer
Aus70:
cpi Impulse,58 ;Restparität
brne Aus80
set ;T-Bit setzen
bld Status,2 ;Bit2 Status setzen (58 Impulse)
clr Temp1
bst Buffer,7 ;Paritätsbit selektieren
bld Temp1,0 ;Paritätsbit in Temp1 Bit0 kopieren
cp Temp1,Parity ;Restparität überprüfen
brne Aus90 ;Fehler -> Ende
set ;T-Bit setzen
bld Status,3 ;Bit3 Status setzen (Parität)
Aus80:
cpi Impulse,59 ;mehr als 58 Impulse (d.h. Störimpulse)
brne Aus90
clt ;T-Bit löschen
bld Status,2 ;Bit2 Status löschen (58 Impulse)
Aus90:
ret
;-------------------------------------------------------------------------------
Bcd2dez:
mov Temp1,Buffer
andi Temp1,$0F
Bcd10:
subi Buffer,$10
brcs Bcd20
subi Temp1,$F6
rjmp Bcd10
Bcd20:
mov Buffer,Temp1
ret
[end]
Gruß Dirk
bertl100
07.11.2006, 20:22
Ich hab noch immr ein Problem mit dem DCF Empfang
1. Was stellt "dcfimpulse" dar? Jeden Impuls zählen?
Wenn ja, dann kommen pro Sekunde etwa 10 Impulse (vorausgesetzt die Ausrichtung stimmt). In anderer Stellung springt "dcfimpulse" im Sekundentakt von 0 auf 1 wobei 0 nur sehr kurz ist.
Am normalen nicht invertierten Ausgangerfolgt die Zählung im Sekundentakt
2. Wenn ich mit meinem (Gott verzeih mir!!) Multimeter messe, dann hab ich in etwa Sekundenimpulse
Kann es nicht doch am Programm liegen?
bertl100
07.11.2006, 22:16
Hat sich erledigt.
Nach langem hin und herdrehen hab ich wohl mal eine Minute lang die richtige Richtung erwischt. Jetzt funzt es!!!!!!!!!!
Geile Sache. Problematisch ist nur, dass man extrem auf Störungen wie PC,
viel Eisen und so aufpassen muß.
Solche Störungen verursachen bei mir mehrere Schaltvorgänge am DCF.
MFG und Herzlichen Dank für die Library Al !!!!!!!
Bertl
mat-sche
03.12.2006, 18:53
Hallo Dirk,
ich versuche seit einiger zeit dein prog vom posting: 09.04.2006, 12:32 bei mir zum laufen zu bringen.
Meine frage ist, was muss ich alles machen und kopieren/compilieren um es bei mir zum laufen zu bekommen?
Um hilfe würd ich dankbar sein!
Gruß MAT
Hallo MAT,
das da am 9.4. war eine alte Version.
Aktueller ist's am 5.9. um 17.32 und 17.38 Uhr.
Ein "Programmrumpf" dazu steht noch am 15.9., 17.13 drin.
Gruß Dirk
P.S.: Falls es nicht läuft, poste mal dein Programm und was du für eine Hardware hast!
mashpeak
03.09.2007, 14:47
Hallo,
ich habe mir die DCF77 Library von "W.Krueger" runtergeladen. Könnte mir jemand die Einstellung der Minutenimpulse erklären. Ich habe keinen Conrad
DCF Empfänger sondern einen Hyline Empfänger mit: 40-60 ms kurze Impulse und 85 - 115 lange Impulse, würde mir gerne die Zeiten ändern.
Über eine Antwort würde ich mich freuen.
Gruss Peter
Hallo Peter,
egal welchen Epfänger du hast:
Die Impulslängen kommen ja vom DCF-Signal und sind festgelegt. Die Einstellungen in den Decodern von W. Krüger und von mir (oder im DCF-Decoder in Bascom) sind dafür schon optimal.
Wenn es bei dir nicht läuft, liegt es nicht an den Impulslängen-Werten.
Gruß Dirk
Schau auch 'mal in die Wiki:
https://www.roboternetz.de/wissen/index.php/DCF77-Decoder_als_Bascom-Library
mashpeak
03.09.2007, 17:36
Hallo Dirk,
danke für die schnelle Antwort, ich habe verschiedene DCF Empfänger gemessen, alle hatten verschiedene Impulslängen. Der normale ideale Impuls sollte 100 bzw. 200 ms lang sein. Gemessen habe ich von
40 - 50ms kurzer und 90 - 100 ms langer
bis zu 90-110ms kurz und 190 - 210ms langer Impuls.
Von daher denke ich das die Impulslänge in der Library berücksichtigt wurde.
Gruss Peter
Hallo Peter,
sicher sind die Grenzwerte für die Impulslängen in den Decodern definiert.
In dem Wiki-Artikel sind diese Grenzwerte auch genannt.
Deine Messungen sind aber so nicht möglich. Wenn ein Empfänger eine korrekte Hüllkurve des DCF77-Signals liefert, dann können die Impulslängen nicht so extrem schwanken.
Gruß Dirk
mashpeak
03.09.2007, 17:52
Hallo Dirk,
die o.g. Messungen stammen nicht von einem Dcf77 Empfänger sonder von verschiedenen Empfängern, der Conrad Empfänger ( 1. Gerneration) hatte die kürzesten Impulse, der HKW Empfänger bedingt durch eine kl. Prozessor die besten Werte, weil der Prozessor die Daten aufbereitet hat. Mein jetziger Empfänger hat 40-65 ms für eine 0 und 85-115ms für eine 1.
Gruss Peter
Hallo Peter,
... die o.g. Messungen stammen nicht von einem Dcf77 Empfänger sonder von verschiedenen Empfängern ...
Ja, schon klar.
Das kann aber trotzdem nicht sein. Grund: Ein einfacher schmalbandiger Empfänger, der die Hüllkurve des DCF77-Signals liefert, kann gar nicht bei gutem Empfang solche Abweichungen am Ausgang erzeugen. Dazu wäre ja schon eine aktive Signalveränderung nötig, die diese Empfänger gar nicht leisten können.
Das ginge natürlich prinzipiell mit deinem Empfänger mit eigenem uC. Aber warum sollte man da die Impulse kürzen? Und dann noch mit hoher variabler Abweichung? (Den Konstrukteur müßte man dann feuern!)
Ist alles unvorstellbar! [-X
Wie hast du denn gemessen?
Gruß Dirk
mashpeak
03.09.2007, 18:38
Hallo Dirk,
habe ein Oszi mit einem externen digitalen Vorsatz. Damit kann ich Spannung, Zeit und Frequenzmessungen machen. Wird an den XY Eingang am Oszi angeschlossen. Bin damit, obwohl es schon etwas älter ist, zufrieden.
Habe damit 5 verschiedene DCF Empfänger gemessen und in Assembler in mein Programm eingebunden und ausprobiert. Habe jetzt den Atmega und Bascom genommen weil doch einfacher und gut erhältlich.
Gruss Peter
Hallo zusammen!
Hab ein Problem mit der dcf dekodierung und zar läuft ein M16 mit 16Mhz und der dcf77_new.lib.
Prescale = 8 ; Startwert = 15536; an Portd.6 hab auch die Lib umgeschrieben nur bekomm ich eine Uhrzeit von 39:84:01!
Woran kann das liegen?
Grus Thomas
mashpeak
05.09.2007, 17:27
Hallo zusammen,
ich habe das Pollin Board Atmega 32 mit 16 Mhz. mit der dcf77 Lib von Albundy, ich würde gerne wenn der DCF Empfang korrekt ausgewertet ist ein Symbol in die LCD Anzeige einblenden welches mir die korrekte Auswetung der Minute anzeigt und bei einer verworfenen Minute wieder verschwindet. Was müsste ich abfragen um den korrekten Empfang der Minute anzuzeigen. Über eine Antwort würde ich mich freuen.
Gruss Peter
@Tom K:
Da braucht man schon eine Glaskugel, um deine Frage zu beantworten!
(Welches ist die dcf77_new.lib? Wie hast du sie umgeschrieben? ...)
@Peter:
Leider gab es im Verlauf dieses langen Postings ein paar Lib-Versionen! Ein Teil (bzw. die Vorlage) stammte von albundy, danach folgten mehrere Versionen, teils auch von mir.
Welche Version nimmst du? Evtl. posten!
In jeder Version gab es aber Flags für "58 Impulse empfangen", "Parität ok" oder so. Die müßte man auswerten, um im LCD die Anzeige "Zeit übernommen" darzustellen.
Gruß Dirk
mashpeak
05.09.2007, 20:17
Sorry habe ich nicht bedacht das es ja mehrere Library Versionen gibt,
benutze die Library Version
" copyright = W.Krueger
comment = DCF 77 Decoder angepasst für Pollin Board
libversion = 1.10
date = 29.04.2006
nochmals Sorry.
Gruss Peter
Hallo Peter,
die Version habe ich nicht,- stammt wohl auch nicht direkt aus diesem Thread!?
Gruß Dirk
mashpeak
05.09.2007, 20:50
Hallo Dirk,
Henrik und Albundy haben auf diese Library in diesem Thread! viele Tips und Anregungen zu dieser Library gegeben.
Gruss Peter
hi
ich hab auch die Version von
copyright = W.Krueger
comment = DCF 77 Decoder
libversion = 1.10
date = 29.04.2006
mit Beispielprogramm download von Seite 4 dieses Theads
hat schon wer diese Lib versucht? bekomme nur Uhrzeiten die es nicht gibt!
In der Lib sowie Beispielprog. hab ich die Pins geändert! auch mit den 4Mhz (intern) funzt es nicht
gruss Thomas
mashpeak
06.09.2007, 06:09
Hallo Thomas,
ich habe die o.g. Lib verwendet mit Pollin Board und 16 Mhz. funktioniert einwandfrei. Wichtig ist den richtigen Port in der Library zu ändern und den invertirten Pin am Empfänger zun nehmen. in der geänderten Lib Version wird die Uhrzeit korrekt angezeigt.
Gruss Peter
Morgen Peter
Ich habe vor einiger Zeit eine Lib verwendet die hat wunderbar funktioniert. nur jetzt ged nix. hab schon einige Ports probiert.
Erst mar Danke für deine Hilfe!
gruss Thomas
Ich hab mich auch schon daran versucht. Aber bei den vielen unterschiedlichen Versionen hab ich nun total den Überblick verloren. Gibts denn nicht irgendwo ein Zip-File mit einer aktuellen Version?
Viele Grüße
Kurt
Hallo Kurt,
bei den vielen unterschiedlichen Versionen hab ich nun total den Überblick verloren.
Ich empfehle die Wiki-Version. Einfach die einzelnen Teile per Copy/Paste zusammenfügen und ein paar doppelte Label löschen.
Ab Bascom 1.11.8.7 würde ich die "eingebaute" DCF77-Funktion nehmen.
Gruß Dirk
Hallo,
ich benötige für meine Steuerung ein bestimmtes Ereignis, weis aber nicht, welche Variable ich da aus der Lib nehmen soll.
Habe meine Lib aus dem Wiki.
UND ZWAR SO WAS HIER:
IF *DCF_SIGNAL_HAT DIE_SOFTUHR_GESTELLT* Then DIES UND JENES
ODER
If *DCF_SIGNAL_KOMPLETT_EMPFANGEN_FUNKUHR_AKTIVIERT* Then DIES UND JENES
Klar ? O:)
Gruß
Papsi
Hallo Papsi,
IF *DCF_SIGNAL_HAT DIE_SOFTUHR_GESTELLT* Then DIES UND JENES
If Dcfstatus.6 = 1 Then DIES UND JENES
If *DCF_SIGNAL_KOMPLETT_EMPFANGEN* Then DIES UND JENES
If Dcfstatus.5 = 1 Then DIES UND JENES
If *FUNKUHR_AKTIVIERT* Then DIES UND JENES
If Dcfstatus.7 = 1 Then DIES UND JENES
Gruß Dirk
Irgendwie erkennt er die Dcfstatus.# nicht.
Egal welchen ich nehme er meckert immer:
...Invalied Datatype...
Irgendwie erkennt er die Dcfstatus.# nicht.
Wenn du den DCF-Decoder aus der Wiki verwendest, dann solltest du erst 'mal die auch im Wiki-Artikel enthaltene Demo (Programme "Decodertest.bas" und "dcf77_soft.bas") genau so wie sie ist zum Laufen bringen. Dann wird auch die Variable Dcfstatus.x erkannt.
Grund: Die Demo enthält alle nötigen Definitionen für die Lib.
Die Demo kannst du dann an deine Anforderungen anpassen, wenn die Original-Version läuft.
Gruß Dirk
Hi,
hier gibts so viele Files und alles habe ich versucht und nichts geht so recht.
Ich habe dem M644 und die Conrad Uhr an b.2 angeklemmt am Invertierten Signal.
Welche lib und welches Programm brauche ich jetzt?.
Wäre einer so nett mir was zu posten was ich nur einfügen muß?
Hallo Trexis5,
wenn du hier 'mal zurückblätterst zu meinem Eintrag vom 6.9.07, 20.55 Uhr, dann steht da alles wesentliche!
Gruß Dirk
Hallo,
also ich habe jetzt dies zu testen erstellt:
http://www.auto-steuerung.de/zip/dcf77_soft.bas
http://www.auto-steuerung.de/zip/test_M32_dcf77_2.bas
http://www.auto-steuerung.de/zip/dcf77.lib
Quarz habe ich auf intern 8Mhz gestellt.
Und den Conradempfänger auf dem Ivertierten Signal angeklemmt ohne Widerstand.
Leider geht nix. Die Uhr läuft zwar, aber kein Signal kommt an. Es blinkt immer -Y- im Display aber die Uhr stellt sich nicht.
Kann mir einer helfen bitte.
Hallo Trexis5,
... habe dem M644 und die Conrad Uhr an b.2 angeklemmt am Invertierten Signal.
Wenn du dir die 3 Programmteile ansiehst, dann steht in JEDEM drin, dass der DCF-Empfänger an [highlight=red:2d3c4aa893]Pind.3[/highlight:2d3c4aa893] angeschlossen ist und dass du Änderungen machen must, wenn du einen anderen Pin benutzen willst.
Wenn du ihn an Pinb.2 angeschlossen hast, wird sich da natürlich nichts tun.
Gruß Dirk
Hi,
ich habe ihn auf Pind.3 (INT1) angeklemmt und auch einen M32 verwendet.
Ich habe extra diesen Pin genommen das es an einer falschen Config nicht liegen kann.
OK, das ist eine neue Info. Vorher war es ein M644, auch in deiner test_M32_dcf77_2.bas wird kein M32 erwähnt.
Also, wenn die Hardware jetzt identisch ist, müßte die Lib ohne Änderungen mit dem Empfänger an Pind.3 laufen.
Wenn nicht, müßtest du schauen, ob der Empfänger störungsfrei arbeiten kann. In der Nähe des PC oder des uCs ist häufig kein Empfang möglich. Manchmal hilft ein anderer Standort, ein größerer Abstand zu elektr. Geräten oder ein Abschirmen der Zuleitungen zum Empfänger.
Gruß Dirk
P.S.: Auch die Taktfrequenz (8 MHz) muss stimmen, sonst müssen noch die Timer-Werte angepasst werden!
Aber das sonst keine Infos auf dem Display erscheinen ist ok?
Locate 10 , 1 : Lcd Dcfstatus.1
Locate 11 , 1 : Lcd Dcfstatus.2
Locate 12 , 1 : Lcd Dcfstatus.3
Locate 13 , 1 : Lcd Dcfstatus.5
Locate 14 , 1 : Lcd Dcfstatus.7
Dost steht immer überall 0 drin außer bei .7 dort ist eine 1 drin.
Hi,
so wie das Programm geschrieben ist stellt sich auch die Uhr?
http://www.auto-steuerung.de/zip/test_M32_dcf77_2.bas
by
Ja, müßte klappen.
Sagst du noch etwas zu deiner Taktfrequenz des M32?
Läuft der bei dir auch mit 8 MHz?
Gruß Dirk
Den habe ich auf intern 8 MHZ gestellt.
Jetzt habe ich mal den 644er genommen. Ist ja gleich wie der M32.
Dort habe ich den externen 16Mhz Quarz genommen und folgendes geändert:
Config Timer1 = Timer , Prescale = 8 'Timer1 für 16Hz
Timer1 = 15536
On Timer1 Tim2_isr
und dann noch im Programm
Tim2_isr:
Timer1 = 15536
Call Dcf77_soft
Return
Das geht auch nicht.
Ich bin ca. 20cm vom Atmel weg.
Mein LCD hast eine CCFL Beleuchtung.
Kann es das sein?
Ok, du hast den Timer1 genommen (im 1. Teil sicher auch noch das "Enable Timer1" geändert).
Der Timerstartwert müßte so für 16 MHz auch ok sein, dann natürlich auch das $crystal = ... noch anpassen.
Das Display könnte schon stören, evtl. 'mal eine simple Ausgabe über RS232 stricken (Display abbauen).
Gruß Dirk
P.S.: Mit dem Bascom ab 1.11.8.7 geht alles mit der "eingebauten" DCF-Funktion. Das kann ich empfehlen, wenn du das hier nicht zum Laufen kriegst.
Wann stellt sich bei meinem Code dann die Uhr?
Laufend?
Also jetzt habe ich ein Abgeschirmtes Kabel genommen und auch einen 12Volt Akku.
Immer noch keinen Empfang. :-(
Hallo Trexis5,
leider kann man aus der Ferne nicht mehr viel raten.
Manchmal ist es nur ein Detail, was nicht stimmt.
Poste doch noch einmal alle Teile, genau so, wie du sie jetzt hast und auch noch einmal deine Hardware (welcher uC, Empfänger wo angeschlossen ...)
Wenn du einen Oszi hast, könntest du die Impulse am Empfängerausgang auch 'mal sichtbar machen. Du kannst auch eine LED über einen Transistor an den Empfänger anschließen, um zu sehen, ob überhaupt ein Signal ankommt.
Gruß Dirk
Hi,
also heute habe ich eine neue DCF Platine erhalten.
Mit der geht es auch nicht, also scheint es da dran nicht zu liegen.
Ich habe das Programmiert:
If Pind.2 = 1 Then
Portb.0 = 1
Else
Portb.0 = 0
End If
jetzt flackert die LED.
Für ne halbe Sekunde geht die LED aus, dann blinkt die wieder.
Wo muß man an dem Conradteil den Ausgang anklemmen?
Habe es an beiden schon probiert, nirgend geht es.
If Sekunde <> _sec Then
'Cls
Call Showtime()
Sekunde = _sec
End If
Genügt das das die Uhr sich stellt?
Könnte ich vielleicht von jemand die .lib bekommen? Vielleicht stimmt da ja was nicht.
Hallo Trexis5,
wenn's blinkt, dann funktioniert der Empfänger. Die kurze Pause müßte 1x pro Minute kommen und ist das Ende eines Minutentelegramms.
Der sog. invertierte Ausgang des CONRAD-Empfängers ist Klemme 4.
Hier noch die Lib, aber mit Pind.3 als Eingang.
copyright = D. Ottensmeyer
comment = DCF77-Decoder und Softclock
libversion = 4.00
date = 25.11.2006
statement = ---------------------------------
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
brne dcf77_16 ;nicht letztes Bit MONAT
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
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,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]
Gruß Dirk
Hi,
könntest du noch bitte die "dcf77_soft.bas" posten?
Weil mit der lib geht es auch noch nicht.
Ich bin noch am Verzweifeln.
So sieht momentan meine Wetterstation aus. Alles geht, außer der blöden DCF77 Funktion.
'################################################# ##########################
'Programmname: DCF77_soft.BAS
'Aufgabe:
'Include-Programm für die dcf77.lib ab Version 4.00
'
'Hardware:
'M32 mit 8 MHz
'Es ist ein DCF-Empfänger (CONRAD 641138) an Portd.3 angeschlossen.
'################################################# ##########################
Config Date = Dmy , Separator = . 'deutsches Datumsformat
Config Clock = User 'Softclock aktivieren
$lib "dcf77_V400.lib" 'LIB für DCF77
$external Dcf77_init
Declare Sub Dcf77_init
$external Dcf77_soft
Declare Sub Dcf77_soft
Config Timer2 = Timer , Prescale = 1024 'Timer 40Hz
Const Startwert = 61 'Für 8MHz
Timer2 = Startwert
On Timer2 Tim2_isr 'Überlauf 40x/s
Enable Interrupts
Enable Timer2
'---------------------- Pin für DCF Eingang definieren ---------------------
'Jeder Portpin kann benutzt werden.
'Auch in der "dcf77.lib" entsprechend anpassen !!!
Config Pind.3 = Input 'DCF77 Eingang
Set Portd.3 'Pullup ein
'--------------------- Variablen der dcf77.lib -----------------------------
Dim _dayofweek As Byte , Dcfstatus As Byte , Dcfflags As Byte
'_dayofweek -> 1..7 (Mo..So)
'Dcfstatus -> Bit0: 15. Impuls erreicht Bit4: 58 Impulse empfangen
' Bit1: Minutenparität OK Bit5: Gültiges DCF77-Telegramm
' Bit2: Stundenparität OK Bit6: Softclock nach DCF gestellt
' Bit3: Parität OK Bit7: DCF-Decoder EIN
' ACHTUNG: Bits 0..5 NUR LESEN!!!
'Dcfflags -> Bit0 (R) : Rufbit für Alarmierung der PTB-Mitarbeiter
' Bit1 (A1): Ankündigung des Wechsels MEZ <-> MESZ
' Bit2 (Z1): \__ Z1/Z2: 10 = MESZ, 01 = MEZ
' Bit3 (Z2): /
' Bit4 (A2): Ankündigung einer Schaltsekunde
' Bit5 (S) : Startbit f. Zeitinformationen (immer 1)
'_sec, _min, _hour, _day, _month, _year sind die Variablen der Softclock
'Interne Variablen der dcf77.lib:
Dim Dcf77counter As Byte
Dim Dcf77parity As Byte
Dim Dcf77impulse As Byte
'Dcf77buffer(9): bits 0..7, bits 8..14, flags (= bits 15..20), min, hour,
' day, dayofweek, month, year
Dim Dcf77buffer(9) As Byte
Dim Dcf77shifter As Byte
Dim Dcf77tal As Byte
Dim Dcf77tah As Byte
Dim Dcf77hsec As Byte
Dim Dcf77bits0_7 As Byte 'DCF77-Bits 0..7
Dim Dcf77bits8_14 As Byte 'DCF77-Bits 8..14
Dim Dcf77val_cnt As Byte 'Validitäts-Zähler
Dim Dcf77lastbit As Byte 'LastBit-Pausenlänge
Dim Dcf77databit As Byte 'DataBit-Pausenlänge
'---------------------------------------------------------------------------
Dcfstatus.7 = 0 'DCF-Decoder AUS
Dcfstatus.6 = 0 'Softclock inaktuell
Call Dcf77_init 'LIB initialisieren
Hi,
also geht immer noch nicht.
Der Sender liegt 30cm vom Atmel weg in einem Geschirmten Kabel.
Die LED blinkt so im sekundentakt.
Wie kann ich was auslesen ob überhaupt was ankommt?
Irgendwelche Bits oder akommende Daten.
Wie muß ich die lib ändern wenn ich (OC0/AIN1) PB3 verwenden will anstatt dem (INT0) PD2 ?
Das kann doch nicht möglich sein.
In den Hauptprogramm sind einige Zeilen Auskommentiert - warum? Hat das mit dem Stellen zu tun?
Hi,
also ich bin voll am verzweifeln.
Es geht einfach nix. Ich sitze schon fast 2 Wochen an der blöden Uhr ohne das die einen Zucker macht.
Ich hänge nochmal alles an was ich habe.
Also Hauptprogramm, dcf77.bas und die libs.
Ich habe alle aus dem Forum probiert, aber dann bekomme ich immer auch Fehlermeldungen das einige sub's nicht definiert wären usw.
Wäre echt super nett wenn sich einer das mal ansehen würde. Ich habe das Programm auch komplett gekürzt, das man das DCF-Zeugs besser sieht.
Der Empfänger ist an PD.2 angeklemmt und mein M32 hat einen 16MHZ Quarz.
Benötigen tue ich die Softuhr vom Atmel.
Hallo Trexis5,
so, habe alles gesichtet:
1. Dcf77_soft.lib:
Scheint alles ok, PD2 als Eingang eingetragen.
2. Dcf77_2_soft.bas:
Die Zeile:
"Disable Timer1 'zunächst ausschalten" ... löschen!
Dafür:
"Enable Interrupts
Enable Timer1" ... einfügen!
3. M32.bas:
Zeigt ja aktuell nichts außer deiner LED an PB0 an, weil die Sub Showtime in der DO-LOOP gar nicht aufgerufen wird.
Ich würde nur ...
If Sekunde <> _sec Then
Cls
Locate 1 , 1 'Zeile 1:
Lcd Time$ ; " " 'Uhrzeit
Sekunde = _sec
End If
... in die DO-LOOP packen bis alles läuft.
Der Teil ...
'Wenn Uhr oder Datum inaktuell, dann nach DCF stellen:
'Timer0 ist nur aktiv, solange DCF-Empfang läuft!!!
If Dcfstatus.5 = 0 Or Dcfstatus.6 = 0 Then
Dcfstatus.7 = 1
Enable Timer0
Else
Dcfstatus.7 = 0
Disable Timer0
End If
... muss ganz raus, weil der Timer nicht abgeschaltet werden kann (sowieso nicht Timer0!)
Mehr fällt mir spontan nicht auf!
Zumindest müßte die Uhrzeit jetzt weiter laufen (ohne DCF-Synchronisierung).
Schreib doch 'mal, wie's klappt.
Wenn's nicht klappt:
1. Timer1 noch für andere Zwecke benutzt?
2. Andere Interrupt-lastige oder Timer-basierte Dinge im Rest deiner Software?
3. Wirklich externe 16 MHz oder interner Teiler? Fusebits korrekt?
4. DCF-Empfänger arbeitet störungsfrei?
Gruß Dirk
1. Nein Timer1 nicht benutzt, nur Timer0. Ich brauche nur einen 1sec. Takt.
2. Weiß nicht. Ich habe das Pollin Funkmodul dran,sonst nix.
3. Ja 16Mhz und Fuses sind auf 111111 richtig gestellt.
4. Ja die LED blinkt sauber im Sekundentakt.
5. Die Zeit schicke ich über Seriell zum M644 und zeige es dort an. Die Uhrzeit ändert sich auf dem Display sauber, aber es ändert sich nicht die Zeit auf die aktuelle.
... teste erst das einfache DCF77-Prog, zu dem ich die Änderungen gepostet habe!
Was klappt da jetzt? Was nicht?
Poste ggf., wie du genau die 3 Teile geändert hast.
Erst dann macht es Sinn, in deinem größeren Prog etwas anzupassen.
Gruß Dirk
P.S.: Testest du wirklich mit der genannten Hardware oder ist das eher eine "Trockenübung"?
(Das kann dann schwierig werden!)
Das was ich ein Post vorher angehängt habe, mit dem Teste ich.
Ich habe ja an dem M32 kein Display, desswegen muss ich ja die Zeit senden.
Ansonsten habe ich alles übernommen was du gepostet hast.
Anbei der Schaltplan meines Aufbaus.
Ganz rechts am M32 hängt der DCF77 Empfänger.
Hi,
erstmal 1000mal danke Dirk.
Der Code geht und auch der DCF77 Empfänger.
Aber sobald ich das Funkmodul von pollin anklemme geht der Empfänger nicht mehr.
So ein mist.
Jetzt weiß ich nicht mehr weiter.
Hallo Trexis5,
wenn ich den Schaltplan angucke, ist da alles ok.
Was ich evtl. probieren würde:
1. An JP5 zwischen GND und +5V einen Kondensator 100nF
2. Irgendwo einen Elko 100uF zwischen GND und +5V (falls nicht schon verbaut...)
3. Gute Masseverbindung zwischen beiden M32, Funkmodul und JP5 - GND
4. Räumliche Distanz zwischen DCF-Empfänger und Funkmodul vergrößern
5. PD2 und PD3 nicht auf längeren Strecken parallel verlegen
Sonst fällt mir nichts ein.
Gruß Dirk
peterfido
29.12.2007, 13:56
Könnte sein, dass das Funkmodul bissel den Empfang stört. Bei mir läuft der Empfang übrigens am besten, wenn GND der Schaltung geerdet ist. Als Empfänger nutze ich den aus dem 9,99 Euro Wecker vom ALDI...
Hi,
wenn ich zwei Atmel mit RDX TXD verbinde und diese 2cm voneinander aufbaue dann gehts.
Also ein Atmel funkt und der andere Empfängt das DCF Signal.
Also kanns keine Funkstörung sein.
Das hat irgendwas mit dem Timer zu tun denke ich.
Hallo Trexis5,
Das hat irgendwas mit dem Timer zu tun denke ich.
Gut möglich. Ich kenne nicht die Lib für das Funkmodul. Wird dort evtl. Timer1 benutzt?
Es würde auch Probleme geben, wenn dort Interrupts für Senden oder Empfang länger gesperrt würden.
Wenn du Timer/IRQ-Konflikte ausschließen kannst, könnte man programmtechnisch z.B. entweder DCF decodieren ODER funken, bzw. z.B. 1x pro Stunde eine neue DCF-Zeit empfangen und solange den Funkverkehr stoppen, bis die neue Zeit da ist.
Gruß Dirk
Wie gehe ich vor wenn ich eine Harwareuhr habe?
Jetzt geht es, aber nur mit :
Config Dcf77 = Pind.7 , Inverted = 1 , Check = 0 , Update = 0 , Timer1sec = 1 , Timer = 1 , Debug = 1
Enable Interrupts
Also es liegt am Timer. Mit dem Timer2 und einem 4Mhz Quarz geht es, mit dem Timer1 und einem 16MHz Quarz bekomme ich es nicht zum laufen.
Const Startwert = 15535 bei Timer 1
Hallo Leute,
gerne hätte ich einfach nur hier mitgelesen, was gelernt und die DCF Routine erfolgreich angewandt.
Doch leider scheitert's bei mir schon beim compilen der test_M32_dcf77_2.bas.
Error : 261 Line : 233 Array expected [DCF77BUFFER] , in File : E:\ELEKTR....
Ich verwende die Bascom Demo Version 1.11.8.7. Kann das sein das das Programm zu groß ist?
Wäre schön wenn mir da jemand helfen könnte ...
Gruß - jürgen
Das ist kein Problem.
Das kommt bei jedenm. Kannste ignorieren.
Knickohr
21.04.2008, 19:42
Hallo Dirk, hallo zusammen.
Eine wunderbare Lib habt ihr da gebastelt. GANZ DICKES LOB !
Funktioniert super. Vor allem was Störanfälligkeit und Empfangsbedingungen betrifft.
http://www.sternhimmel-ueber-ulm.de/scratch/Wetter.jpg http://www.sternhimmel-ueber-ulm.de/scratch/128x240.jpg
Die BASCOM-Routine ist zu störanfällig und zeigt immer wieder unsinnige Werte an. Da fehlt wohl eine saubere Validitätsprüfung. Außerdem war es nicht möglich, den Uhrenquarz in einer Softclock mit der DCF-Routine von BASCOM zu vereinigen. Spätestens nach 2 Minuten habe ich ein sauberes und gültiges DCF77-Telegramm empfangen. Auch unter widrigen Empfangsbedingungen.
Allerdings hat die Routine noch 2 kleine Makel. Es kommt bei der Compilierung zu einem Fehler, den man aber vernachlässigen kann. Weiterhin ist die Auswahl des DCF77-Eingangspins nicht so einfach frei wählbar. Da muß man in der Lib ein wenig "froschen". Ich verstehe sehr wenig von ASM, aber es müßte doch möglich sein, diese beiden unschönen Dinge auszumerzen.
Was machen eigentlich die Validitätsprüfung und der Plausibilitätscheck genau ?
Thomas
Hallo in Richtung Blautopf... ;)
Das mit der komischen Anzeige habe ich auch das Problem.
Liegt daran, das alle 25ms der Timer überläuft und in die ISR springt.
Wenn nun gerade was dagestellt werden soll, und er mittendrin springt, dann kommt bei mir auch Mist raus.
Habe aber leider noch keine Lösung finden können.
Und das mit dem Pin ist - naja - umständlich - aber mir eher egal.
Gruß
Papsi
PS
Was haste denn da für ein LCD?
Knickohr
21.04.2008, 19:57
Hallo Papsi,
ich deaktiviere den Timer, wenn ein gültiges DCF77-Telegramm empfangen wurde. So alle Stunde schalte ich ihn wieder ein und synchronisiere die Zeit. Mit einem Uhrenquarz in der Softclock ist das kein Problem mehr.
Das Display ist ein MS240128A2 mit T6963C-Controller. Schau mal in der Bucht unter "240x128" nach.
Thomas
Wird denn trotzdem noch Mist angezeigt, auch wenn Du den Timer nur alle paar Stunden laufen lässt?
Knickohr
21.04.2008, 20:50
Hin und wieder mal kommen ein paar Pixel, die nichts auf dem Display verloren haben. Aber mit einem CLS ist dann alles wieder sauber.
Passiert ja nur während dem DCF77-Empfang und da auch nur ab und zu.
Thomas
Knickohr
21.04.2008, 23:28
Hallo,
hab noch was "Unschönes" festgestellt. Die Uhr geht um fast genau 1 Sekunde vor !
Nicht weiter schlimm, stört wahrscheinlich auch (fast) niemanden. Wollte es nur mal so anmerken ;)
Thomas
Hallo,
ich habe das heute mal mit dem Timer stoppen probiert.
Wenn ich abe den Timer anhalte, dann bleibt auch meine Uhrzeit auf dem Display stehen.
Ich habe die Lib aus dem Wiki in Betrieb und kenne mich mit Asembler nicht aus.
Es wird bei mir alle 25ms in die ISR gesprungen und die Lib aufgerufen.
Wenn aber der Timer steht, dann bleibt alles stehen.
Wie hast Du das gelöst?
Gruß
Papsi
Knickohr
22.04.2008, 17:25
Ach Papsi,
Du hast die Routine ohne den Uhrenquarz ?
Das kann dann auch nicht funktionieren, da muß der Timer laufen. Ich verwende zusätzlich einen genauen Uhrenquarz (nicht diese Billigdinger) und lasse die Softclock von BASCOM laufen.
Thomas
Hallo Knickohr,
Eine wunderbare Lib habt ihr da gebastelt. GANZ DICKES LOB !
Danke, danke ... :oops:
Was machen eigentlich die Validitätsprüfung und der Plausibilitätscheck genau ?
Das wird in dem DCF77-Wiki-Artikel ganz gut beschrieben:
https://www.roboternetz.de/wissen/index.php/DCF77-Decoder_als_Bascom-Library
Übrigens: Tolle Wetterstation! Könntest du noch etwas zur Hardware schreiben? Ich habe da auch gerade was fertig und mich würde interessieren, welche Sensoren du verbaut hast.
Gruß Dirk
Knickohr
22.04.2008, 18:28
Hallo Dirk,
schau mal hier :
http://www.avr-praxis.de/forum/showthread.php?p=623
Den Wiki-Artikel habe ich nur überflogen, weil die Lib nicht auf Anhieb funktioniert hat. Die nötigen Informationen habe ich mir dann aus diesem Beitrag geholt ;)
Kann man den doofen Array expected [DCF77BUFFER] noch irgendwie ausmerzen ? Ist doof, immer die Fehlermeldung im Compiler zu sehen.
Thomas
Hallo Thomas,
danke für den Link! Für meine Wetterstation habe ich das HTM1735-Modul für die Innenraum-Feuchte und -Temperatur genommen. Den MPXA4100A nehme ich für den Luftdruck und einen simplen LDR für die Helligkeitsmessung.
Den Außenfühler habe ich mit einem KT110 (Temp.) bestückt und für die Feuchte draußen mache ich Versuche mit dem SHS A3, der aber leider erst ab 60% eine Messung ermöglicht.
Den Compilerfehler (Array expected [DCF77BUFFER]) habe ich auch schon versucht, wegzubekommen: Bisher ohne Erfolg. Das Array ist ordnungsgemäß definiert, also liegt kein Fehler vor. Das Programm wird auch fehlerfrei compiliert trotz der Fehlermeldung.
Gruß Dirk
@ Knickohr
Kannst Du dein Code mal hier anhängen...
Will mich nicht extra in dem anderen Forum anmelden.
Knickohr
22.04.2008, 20:43
Hallo,
gerade frisch compiliert ;)
Thomas
Hallo Knickohr,
Was hast Du für einen Uhrenquarz (Reichelt Bestnr. ??? ;) ) und wie und wo wird der angeschlossen.
Habe ich noch nie verwendet.
Habe an meiner Steuerung nur ein Standard 8MHz Quarz mit den 2 22pF C´s
Gruß
Papsi
Knickohr
23.04.2008, 23:58
TOSC1 und TOSC2
und dann das Config Soft ... nicht vergessen. Dann mußt Du aber für den DCF77-Decoder einen anderen Timer verwenden und die Lib anders "anspringen". Steht im Wiki ganz genau beschrieben oder auch hier vorher im Beitrag.
Den Quarz, den ich verwende, wirst Du nicht so ohne weiteres bekommen. Ist ein SMD-Uhrenquarz mit militärischen Spezifikationen. Aber der von Conrad, Reichelt, blahbha Uhrenquarz mit 32768Hz tut es auch ;)
Thomas
kann man sich diese Ominöse dcf77 lib auch runterladen oder muss man die sich zusammenkopieren
geht das auch mit dem pollin DCF modul das ja erst nach 2bis 20min gestartet werden kann mitels schalter via portpin des controllers
@magic33:
kann man sich diese Ominöse dcf77 lib auch runterladen oder muss man die sich zusammenkopieren
Welche "Ominöse dcf77 lib" meinst du? Wenn du die aus RN-Wissen meinst, dann habe ich die 'mal angehängt, damit du nicht kopieren must.
Wenn du die neueren BASCOM-Versionen hast, würde ich stattdessen die "eingebaute" DCF-Funktion nehmen.
... geht das auch mit dem pollin DCF modul das ja erst nach 2bis 20min gestartet werden kann mitels schalter via portpin des controllers
Die Lib aus RN-Wissen hat keine Funktion zum Einschalten eines DCF-Moduls. Das ist ja aber einfach zu machen: Immer wenn Status.7 gleich 1 ist, muss der Decoder eingeschaltet werden.
Wenn du die Bascom-Funktion nimmst, gibt es einen Parameter (SWITCHPOWER), mit dem du einen Portpin schalten kanst.
Gruß Dirk
P.S.: Das Pollin-DCF-Modul braucht übrigens eine kleine Treiberstufe (Transistor) zum Anschluß an den uC.
Danke für die schnelle info
Hallo,
bin neu hier. Kann mir jemand sagen,
wie ich an die Library von albundy
bezw. die Tipps von hrei rankomme?
Hook
bertl100
05.12.2009, 16:21
Eigentlich brauchst du die ja gar nicht, da Bascom mittlerweile eine eigene Lib eingebettet hat.
Musst nur einbinden und laut Hilfe in Bascom damit arbeiten.
Bertl100
Vielen Dank für die rasche Antwort!
Habe eine DCF-Uhr mit BASCOM laufen.
Das Problem ist die Störunganzeige:
eine Unterbrechung des DCF-Signals
wird nicht sicher angezeigt.
Besitze BASCOM 1..11.9.3
Hook
Hallo Hook,
Kann mir jemand sagen, wie ich an die Library von albundy bezw. die Tipps von hrei rankomme?
Fast alles ist in diesem irre langen Thread zu finden:
https://www.roboternetz.de/phpBB2/viewtopic.php?t=18073
Gruß Dirk
Knickohr
01.01.2010, 02:18
Hallo Dirk,
ließt Du noch mit in diesem Beitrag ? Ich habe einen Bug in der lib gefunden, gerade eben ...
Das Jahr arbeitet offensichtlich nicht korrekt. Es ist auf 01.01.16 gesprungen. Ich verwende die Version 4.00 vom 25.11.2006. Oder hab ich ein Update verpennt ?
Ach ja, ein Gutes Neues Euch allen ;)
Thomas
Das Jahr arbeitet offensichtlich nicht korrekt. Es ist auf 01.01.16 gesprungen. Ich verwende die Version 4.00 vom 25.11.2006.
UUps. Muss ich mir ansehen!
Gruß Dirk
P.S.: Ich war zu beschäftigt, um den Jahreswechsel am uC zu verfolgen.
Knickohr
01.01.2010, 11:27
Hallo Dirk,
das Problem liegt wahrscheinlich in einer Zuweisung von oder in eine HEX-Variable.
1 und 0 für das Jahr 10 ergibt in einer HEX-Variablen ja 16
Nur so eine Vermutung, ich suche auch mal, ob ich selbst was finde. Von ASM hab ich Null Ahnung.
Thomas
Eisbaeeer
01.01.2010, 14:17
Prosit Neujahr!
Hab das selbe Problem. Meine DCF Variable der Softclock "_year" ist auch auf 16 gesprungen. Wäre auch an einer Lösung interessiert.
Grüße Eisbaeeer
Knickohr
01.01.2010, 14:59
Hallo zusammen,
kleiner Workaround und nur das, mehr ist es nicht !
If Dcfstatus.7 = 1 Then ' prüfe auf korrekten DCF77-Empfang
If Dcfstatus.5 = 1 And Dcfstatus.6 = 1 Then ' wenn OK, DCF77 disablen
Temp_byte = _year ' temporärer Workaround, da DCF77_4.lib fehlerhaft
If Temp_byte > 15 Then
Temp_byte = Temp_byte - 6
_year = Temp_byte
End If
Disable Timer4
Dcfstatus.7 = 0
End If
End If
Wird vermutlich die nächsten 10 Jahre damit funktionieren ;)
Thomas
Leute,
erster Kurz-Test heute:
An der Softclock liegts nicht. Die zählt (ohne DCF-Empfang!) sauber vom Jahr 2009 (31.12., 23:59:59) hoch zum 1.1.10, 00:00:00.
Da ich den Jahreswechsel verpasst habe, muss ich einen DCF-Encoder (damit kann ich jedes DCF-Protokoll vortäuschen) anstelle des Empfängers anschließen und den Jahreswechsel 2009-2010 simulieren.
Kann etwas dauern ...
Ich berichte weiter.
Gruß Dirk
Knickohr
01.01.2010, 18:02
Hallo Dirk,
mein Verdacht liegt bei der Decodierung des DCF-Signals. Da muß irgendwas schief gehen.
Wieso einen Encoder ? Du mußt doch einfach nur die Uhr falsch stellen und dann mit dem DCF-Empfänger neu synchonisieren lassen. Da siehste dann, das die Uhr immer wieder auf das Jahr 16 springt.
Der Jahreswechsel nach 2010 interessiert doch nicht mehr, der ist vorbei ;)
Thomas
So Leute,
der Fehler war, dass das Jahr nicht von BCD nach DEZ umgewandelt wurde. In den letzten 10 Jahren war das kein Problem. O:)
Hier die Lib fürs neue Jahrzehnt:
copyright = D. Ottensmeyer
comment = DCF77-Decoder und Softclock
libversion = 4.10
date = 01.01.2010
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,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]
Gruß Dirk
Knickohr
01.01.2010, 21:22
Hallo Dirk,
DANKE :)
War das wirklich alles ?
brlo dcf77_16
breq dcf77_12 ;letztes Bit MONAT
cpi Impulse,57
brne dcf77_16 ;nicht letztes Bit JAHR
Da habe ich heute Morgen auch schon drüber gestutzt ;) Nur wußte ich nicht, obs dann überhaupt noch funktioniert.
Thomas
Eisbaeeer
01.01.2010, 21:25
--- EDIT -----
Hab die Posts oben glatt übersehen oder wurden eben erst hinzugefügt. Werde die neue Lib ausprobieren.
Ja, BCD und DEC. Bin ich auch schon drübergestolpert.
Grüße Eisbaeeer
@Knickohr:
Ja, das war alles. Dadurch wird auch das Jahr noch durch die BCD-DEZ-Umwandlung gejagt. Alle anderen Werte müssen da schon durch.
@Eisbaeeer:
EDIT: Ok, viel Spaß beim Testen!
Gruß Dirk
Eisbaeeer
01.01.2010, 21:38
@Knickohr:
@Eisbaeeer:
Ganz ruhig! Ich bin doch da!
Gruß Dirk
Hi. jep, bin ganz gelassen. Großes Lob an deinen Code. Ist sehr übersichtlich geschrieben und durchaus nachvollziehbar. Alles kommentiert. Kann man sich als Vorbild nehmen!
Danke nochmal für deine Mühe!
Grüße Eisbaeeer
Knickohr
01.01.2010, 23:39
Jepp, funzt !
Danke nochmal.
Thomas
Eisbaeeer
02.01.2010, 14:46
Hallo
Bei mir findet er die Einsprungmarke dcf77_init nicht mehr. Ich hab die Lib über diese Einsprungmarke nach dem rn-wissen wiki damals programmiert.
Includiert sind ist die dcf77_softwareuhr.bas (wie im Anhang). Die LIB ist im Bascom eingespielt. Aufgerufen wird das ganze über den Timer:
'------[ Interrupt Routine DCF77 ]----------------------------------------------
Tim2_isr:
Timer2 = Startwert
Call Dcf77_init
Return
Spiele ich die "alte" lib ein, funktioniert der Aufruf der dcf77_init.
Sehr merkwürdig.
Grüße Eisbaeeer
Knickohr
02.01.2010, 15:04
Hallo Eisbär,
der Init passiert ganz am Anfang von Deinem Programm. Der Timer-Interrupt macht nur einen Call Dcf77
...
'Const Startwert = 61 ' für Timer 8-bit
Const Startwert = 40536 ' für Timer 16 bit
...
Declare Sub Dcf77
Declare Sub Dcf77_init
'Declare Sub Dcf77_soft
...
Config Timer4 = Timer , Prescale = 8 ' Timer für 40Hz (25ms) 8-bit
'Config Timer4 = Timer , Prescale = 1024 ' Timer für 40Hz (25ms) 16-bit
Timer4 = Startwert
'On Timer4 Timer_dcf77 ' Überlauf alle 25ms, funktioniert nicht !
On Ovf4 Timer_dcf77 ' Überlauf alle 25ms
...
Beginn: ' Wird angesprungen bei komplettem Reset
Disable Timer4 ' Timer für DCF77 noch disablen
Call Dcf77_init ' DCF77 initialisieren
...
Enable Timer4
...
Timer_dcf77: ' Timer zur DCF77-Decodierung
Timer4 = Startwert
Call Dcf77
Return
Thomas
Eisbaeeer
03.01.2010, 14:20
Hallo
Ich glaube es selber nicht. Den genauen Fehler habe ich nicht gefunden. Aber jetzt funktioniert die LIB. Beim code kopieren von dem Thread ist wohl irgendwo ein Fehler unterlaufen. Um den Fehler einzugrenzen hab ich die "alte" Lib hergenommen und nur die paar Zeilen ergänzt und siehe da, sie funktioniert wieder.
Ich hab die Dateien aber mit einem Programm verglichen. Kein Unterschied zu finden.
Viele Grüße Eisbaeeer
Knickohr
03.01.2010, 17:17
Hallo Eisbär,
ich hatte auch einen seltsamen Effekt ! Ich habs aber genau umgekehrt gemacht. Ich wollte die neuen Zeilen in die alte LIB kopieren, danach gings nicht mehr.
Nun gut, dann habe ich eben die neue LIB genommen und meine Anpassungen für den PIN und PORT neu gemacht. Alles OK; die LIB tut wieder seit Vorgestern Abend.
Thomas
Eisbaeeer
03.01.2010, 18:08
Ich hatte so ein Phänomen schon einmal. Das liegt meist an den PHP Code Srcipten der Foren. Könnte mal jemand die funktionierende LIB als Anhang hier posten. Der Code compiliert jetzt zwar bei mir, aber irgend wo ist noch der Hund drin. Ich bekomme bis dcfstatus.4 alle gesetzt, dcfstatus.6 , 6 kommt dann nicht.
Wäre mir eine Hilfe. Danke.
Knickohr
03.01.2010, 18:37
Aber klar doch, allerdings ist die LIB schon von mir auf meine Ports und Pins angepaßt worden ;)
Thomas
Eisbaeeer
03.01.2010, 19:44
Danke, funzt jetzt auch.
Grüße Eisbaeeer
@Knickohr
Kann man den doofen Array expected [DCF77BUFFER] noch irgendwie ausmerzen ? Ist doof, immer die Fehlermeldung im Compiler zu sehen.
Klar, indem man das Array in der Lib korrekt adressiert.
Ersetze "Loadadr DCF77Buffer,Z" mit "Loadadr DCF77Buffer(1),Z
und schon gibt es keine Fehlermeldung mehr. =D>
kufikugel
27.07.2010, 12:10
Hi,
ich habe da ein Problem wo ich hoffe das ihr mir helfen könnt. Ich benutze die super DCF77 libary die hier vorgestellt wurde. Funktioniert auch bestens. In der Anwendung die ich brauche kann ich die softclock nur Nachts mit DCF aktualisieren. Natürlich kommt es da ich keinen Quarz drann habe (so genau muss es nun auch nicht sein) zu ungenauigkeiten bis zum nächsten DCF Empfang.
Problem ist nur das es 10sec pro Stunde sind, was dann doch recht heftig ist (warum auch immer das so krass hier ist). Egal ob interner 8Mhz RC oder externer 8MHz Quarz. Wo bzw wie kann ich das denn ein wenig nachkorrigieren. Im Prinzip müsste ich doch den Timer nur etwas weniger Zählen lassen pro Umlauf??!!
Wäre super wenn mir da jemand helfen könnte,
Grüße und Danke,
Lars
EDIT: Ich passe einfach den Startwert an, richtig?? Ist mir gerade aufgefallen als ich nochmal über den code gelesen habe.
Knickohr
27.07.2010, 14:36
Hallo,
warum machst Du dann den 32kHz Uhrenquarz nicht auch n och dran und läßt die Uhr darüber laufen ?
Dann sind es in mehreren Tagen vielleicht mal eine Sekunde. Die DCF dient dann nur zum Einstellen der Softclock.
Thomas
kufikugel
27.07.2010, 16:07
Hi,
na ja hat zwei Gründe....erstens ist die Platine schon fertig und hat den Uhrenquarz natürlich nicht vorgesehen. Anderer Punkt ist das fast alle Pins belegt sind....sprich es in meinem Fall auch echt ungünstig wäre wenn ich die beiden Quarzpins wieder freigeben müsste. Wenn ich es verhindern kann würde ich es zumindest :D
Habe den Startwert erst um eins niedriger gemacht....da war die Uhr 10s zu langsam. Jetzt mache ich bei jedem Umlauf eimal 61 und einmal 60....dann läuft sie ziemlich genau. Bzw genau genug für meine Anwendung. Auf die Sekunde am Tag kommt es hier ja auch nicht an. Andere Möglichkeit wäre die Uhr auf den Timer1 zu machen wo ich genauer einstellen könnte......aber den brauche ich für andere Sachen.
Oder jemand noch eine andere idee außer den Startwert so zu modifizieren?
Grüße und Danke,
Lars
Hallo,
meine Uhr läuft an einem Tag mehrere Sekunden oder gar Minuten vor. Habe einen Uhrenquarz an dem Atmega 1280 angeschlossen (TOSC1 und TOSC2 bzw. Pin PG3 und PG4). Nur wie Nutze ich diesen? Was muss ich einstellen? Wenn ich in der include Datei nur statt DCF77-soft nur DCF77 einstelle, dann bekomme ich gar nichts mehr angezeigt. Habt verständnis dass ich diesen 20 Seiten Thread nicht durchgelesen habe und die Antwort irgendwo da drin ist.
peterfido
27.06.2011, 21:53
Uhrenquarz und DCF habe ich persönlich noch nicht auf einem Atmega verwendet. Ich nutze meist einen DS1307. Nicht nur wegen der batteriegepufferten Gangreserve. Allerdings weicht dieser trotz Uhrenquarz auch etwas ab (Vielleicht sollte ich nicht immer nur die Sonderangebote kaufen). Die DCF Routine fragt den DCF-PIN mehrmals pro Sekunde ab. Config Clock = Soft setzt nur die Variablen. Den Rest (die komplette Uhr) muß selbst programmiert werden. Ob es bei DCF auch so ist, weiß ich nicht. Ich nutze für DCF die Bascom internen Routinen. Wenn die Uhr etwas abweicht, hilft eine manuelle Timerkorrektur. Die Abweichung sollte aber stets gleich bleiben. Dies geht aber nicht über den internen Takt. Dafür benötigst Du einen Quarz oder Quarzoszillator.
Bei DCF sollte die Uhr aber öfter gestellt werden. So große Abweichungen sprechen für schlechten Empfang.
Bei mir stellt die sich jede Stunde. Nur habe ich gerade einen Einbauort, wo die Uhr nicht immer empfang hat. In der Nacht ist der Empfang gut am Tag eher Mäßig bis schlecht bis unmöglich. Deswegen benötige ich einen Uhrenquarz. Denn sonst geht die innerhalb eines Tages mehrere Minuten nach. Nur weis ich nicht wie ich den Uhrenquarz in der DCF77 Routine verwenden soll. Im Wiki steht von DCF77_soft ersetzen durch nur DCF77 aber dann zeigt bei mir die Uhr gar nichts mehr an.
peterfido
28.06.2011, 17:36
Da wird z.B. ein Schaltnetzteil oder Netzgerät den Empfang stören. Wenn die Uhr nachgeht, würde ich mit den Timereinstellungen / bzw. der Crystal-Angabe spielen. Wichtig ist externer Takt.
Ein Uhrenquarz ist schon an den Atmega (TOSC 1 und TOSC 2) angelötet. Den würde ich also gerne benutzen ;). Ich müsste nur Wissen, wie ich das Programm auf diesen einstellen kann...
Nein ich denke eher das Metallgehäuse in dem der Empfänger eingebaut ist.
peterfido
28.06.2011, 18:11
Ein Metallgehäuse für einen DCF Empfänger?? Im asyncronen Modus wird meist Timer2 genutzt.
Gib mal nach Config DCF folgendes ein:
Compare1A = Compare1A - 1
und teste die Genauigkeit. Ob das mit der hier beschriebenen Lib geht, weiß ich allerdings nicht. Ich nutze immer die Bascom internen Routinen.
Das ganhze Gerät (Also µC und Mosfets etc. und eben auch der DCF 77 Empfänger sind in einem Metallgehäuse gelandet.) Ich weis nicht die beste Idee :D
Hm müsst ich mal probieren. Aber wie gesagt. Wenn einer was dazu sagen könnte, der die Lib entwickelt hat, wäre ich sehr dankbar. Ich will nämlich unbedingt den Uhrenquarz verwenden. Der hat mich nen ganzen Euro gekostet :D Sonst ist der Umsonst da...
peterfido
29.06.2011, 07:01
Mosfets? DCF Empfänger sind empfindlich gegen Spannungsschwankungen. Eine per PWM gedimmte Displybeleuchtung kann da schon störend sein. Ich habe das so gelöst, dass der DCF Empfänger eine eigene Spannungsstabilisierung bekommen hat und über Schmitt Trigger an den µC. Seit dem läuft das zuverlässig. Um zu testen, ob der Uhrenquarz (bzw. dessen Schaltung) passt, würde ich einfach mit Config Clock = Soft eine "normale" Uhr programmieren und schauen, ob diese läuft. Da bekommst Du dann auch gleich die Abweichung mit.
Powered by vBulletin® Version 4.2.5 Copyright ©2024 Adduco Digital e.K. und vBulletin Solutions, Inc. Alle Rechte vorbehalten.