PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : einpaar Fragen zur Uhrzeit-Programmierung



Adam
02.12.2004, 14:53
Hallo!
Ich habe einen ATMega, an dessen Ports schon ziemlich vieles hängt (8 Fühler,4Relais,LCD) für die weitere Steuerung bräuchte ich die aktuelle Uhrzeit.
1.frage wie kann ich die Uhr selbst programmieren? sprich wie muss ich den prescaler einstellen, dass er genau 1 sec. beträgt? (16Mhz Quarz)
2.frage, sollte ich evtl. einen zweiten co-µC verwenden, oder ginge das auch noch auf dem einen µC? und wie groß sind die Ungenauigkeiten. Das Gerät wird im non-stop modus betrieben ...

Danke Vorab!

peterguy
02.12.2004, 15:13
Hi Adam,

ich kenne mich mit den Atmels nicht aus, aber falls Deiner eine I2C-Bus-Schnittstelle besitzt, könntest Du den PCF 8583 von Philips benutzen.
Den gibts z.B. bei Reichelt für kleines Geld.
Die Genauigkeit hängt vom verwendeten Quarz ab(der PCF 8583 benötigt einen Eigenen mit ~32kHz). Wenns ganz exakt sein muss, kannst Du ja noch ein DCF77-Funkuhr-Modul (Conrad 10€) verwenden.

Gruß

Peter

Adam
02.12.2004, 15:21
und wie kann ich das Signal des DCF77 Moduls verarbeiten? Denn das "datenblatt" ist etwas mager, was diese Informationen angeht ...

fzehner
02.12.2004, 16:50
Das DCF77 Modul ist der reine Empfänger mit Verstärker. Von der PTB wird jede Sekunde (bis auf die 59.) ein Impuls von 100 ms oder 200 ms Länge erzeugt. Mit den Impulslängen werden Uhrzeit, Datum etc. codiert. Diese Arbeit musst Du noch selber machen.

RCO
02.12.2004, 16:54
Nur zur Abschreckung:


'---------------------------------------------------------------------------------------------------------
' (c) 2001 Roman Foltyn 29.12.2001
'---------------------------------------------------------------------------------------------------------
' DCF1.BAS Version 1.01
' DCF-77 Signal auf INT1 Pin 13 (P3.3) Impulse Low Activ [Conrad Empfänger + Inverter]
' Port 3.7 Low => Piepser ein (Volle stunde Pipser) 5 pipse letzte bei 00:00 lang 0.3 sek
'---------------------------------------------------------------------------------------------------------
'
' V1.01 3.01.2002 10ms Zähler koriegiert 0.99 sek zum 1s ,softwate uhr variable initialisiert
' Bei keine DCF signall nach 2,5 sek XTL meldung Beide DCF Zähler begrenz bis 250
' Wenn keine DCF empfang parity war auch OK jetz wen kalender werte=0 dan auch keine synchro
' Fehler bei KW1 (negative Temp2) Beseitigt.
'---------------------------------------------------------------------------------------------------------
$crystal = 11059200
$large
Config Lcd = 16 * 2 'configure lcd display
Cursor Off
'---- Software Uhr Variablen -----------------------------------------------------------------------------
Dim Shsek As Byte , Ssek As Byte , Smin As Byte , Sstd As Byte , Etag As Byte
Dim Stag As Byte , Swta As Byte , Smon As Byte , Sjah As Byte
'---- DCF77 Dekoder Variablen ----------------------------------------------------------------------------
Dim Pointer As Byte , Dmin As Byte , Dstd As Byte, 'DCF Variable
Dim Dtag As Byte , Dwta As Byte , Dmon As Byte , Djah As Byte
Dim Dcf(60) As Byte 'array für dcf empfangene impulse
Dim Dcfs As Byte 'Variable für zeit zwischen zwei impulse von DCF empfänger
Dim Dcfl As Byte 'Variable für DCF impuls dauer in 10ms schritten
Dim Dcferm As Byte 'Parity error minuten
Dim Dcfers As Byte 'Parity error stunden
Dim Dcferd As Byte 'Parity errordatum
Dim Dcferr As Byte 'Parity error Globall
Dim I As Byte 'diverse temporare variablen
Dim Temp1 As Byte
Dim Wert As Byte
Dim Par As Byte
'--- Speicher NUR FÜR Piepstone - ---------------------------------------------------------------------
Dim Pipsen As Byte 'merker für erzeugte pipston - eliminiert doppel ton bei DCF synchronisation
'--- Speicher NUR FÜR KW und Jahrestag BERECHNUNG --------------------------------------------------------
Dim Jtag As Integer , Schalt As Byte
Dim Temp2 As Integer
Dim Temp3 As Integer
Dim Temp4 As Byte
Dim Kw As Byte
'---------------------------------------------------------------------------------------------------------
'---------------------------------------------------------------------------------------------------------
Dcf(0) = 1 'Variablen initialisierung
Dcf(10) = 0
Dcf(20) = 1
Pointer = 0
Dcferr = 1
Shsek = 0
Ssek = 0
Smin = 0
Sstd = 0
Swta = 0
Stag = 0
Smon = 0
Sjah = 0
'Interrupt Configuration ---------------------------------------------------------------------------------
Config Timer2 = Timer , Gate = Internal , Mode = 0 'Reload 16 Bit Modus
On Int1 Int1_int
Set Tcon.2 'flanken steuerung
On Timer2 Timer_2_int
Load Timer2 , 9216 '9216 für 11.0592MHz 10 mS takt (Xtal/12/9216=>10ms)
Enable Interrupts 'enable interrupt
Enable Int1 'enable int1
Enable Timer2 'enable timer2
Priority Set Timer2 'highest priority
Start Timer2 'Timer starten




'################################################# ################################################## ######
'--- Programm Anfang -------------------------------------------------------------------------------------
'################################################# ################################################## ######
Cls
Upperline
Lcd "DCF-77 UHR V1.01"
Lowerline
Lcd "(c) Roman Foltyn"
Wait 2
'____ Hauptprogramm __________________________________________________ ____________________________________
Do
If Shsek = 0 Then Gosub Displayuhr 'einmall pro sekunde ausgabe auf display
Loop
End



'################################################# ################################################## ######
'Unterprogramme _-----------------------------------------------------------------------------------------
'Timer 2 Interrupt Routine (10ms) ------------------------------------------------------------------------
'bearbeitubgs zeit bei volle minute 1,13ms bei jede aufruf 140µs
'---------------------------------------------------------------------------------------------------------
Timer_2_int:
Incr Dcfs
If Dcfs > 250 Then Dcfs = 250 'Zähler begrenzen bis 250
If P3.3 = 0 Then Incr Dcfl 'Dcfl impuls Länge zahler in 10ms step
If Dcfl > 250 Then Dcfl = 250 'Zähler begrenzen bis 250
'---- Software Uhr ---------------------------------------------------------------------------------------
Incr Shsek '10 ms addieren
If Shsek = 100 Then 'und bei 1 sekunde ssek addieren
Shsek = 0
Incr Ssek
End If

If Ssek = 60 Then
Ssek = 0
Incr Smin
End If
If Smin = 60 Then
Smin = 0
Incr Sstd
End If
If Sstd = 24 Then
Sstd = 0
Incr Stag
Incr Swta
End If
Etag = 32 'berechnung monat ende für softuhr
Schalt = Sjah Mod 4
If Smon = 2 Then 'Februar bei schaltjahr berechnen
If Schalt = 0 Then
Etag = 30
Else
Etag = 29
End If
End If
If Smon = 2 Then Etag = 29
If Smon = 4 Then Etag = 31
If Smon = 6 Then Etag = 31
If Smon = 9 Then Etag = 31
If Smon = 11 Then Etag = 31
If Stag = Etag Then
Stag = 1
Incr Smon
End If
If Smon = 13 Then
Smon = 1
Incr Sjah
End If
'-- ACHTUNG NECHSTE ROUTINEN (JAHRESTAG-, KW-, UND PIEPSTONE ROUTINEN) KÖNNEN ENTFÄLEN ! ---------------
'-------------------------------------------------------------------------------------------------------
'---- Berechnung jahrestages und KW (bei keine synchronisation Jtag=0)----------------------------------
'-------------------------------------------------------------------------------------------------------
If Ssek = 0 Then
If Schalt = 0 Then '31.29.31.30.31.30.31.31.30.31.30.31
If Smon = 1 Then Jtag = Stag '0
If Smon = 2 Then Jtag = 31 + Stag '31
If Smon = 3 Then Jtag = 60 + Stag '31.29.
If Smon = 4 Then Jtag = 91 + Stag '31.29.31.
If Smon = 5 Then Jtag = 121 + Stag '31.29.31.30.
If Smon = 6 Then Jtag = 152 + Stag '31.29.31.30.31.
If Smon = 7 Then Jtag = 182 + Stag '31.29.31.30.31.30.
If Smon = 8 Then Jtag = 213 + Stag '31.29.31.30.31.30.31.
If Smon = 9 Then Jtag = 244 + Stag '31.29.31.30.31.30.31.31
If Smon = 10 Then Jtag = 274 + Stag '31.29.31.30.31.30.31.31.30.
If Smon = 11 Then Jtag = 305 + Stag '31.29.31.30.31.30.31.31.30.31.
If Smon = 12 Then Jtag = 335 + Stag '31.29.31.30.31.30.31.31.30.31.30.
Else
If Smon = 1 Then Jtag = Stag '0
If Smon = 2 Then Jtag = 31 + Stag '31
If Smon = 3 Then Jtag = 59 + Stag '31.28.
If Smon = 4 Then Jtag = 90 + Stag '31.28.31.
If Smon = 5 Then Jtag = 120 + Stag '31.28.31.30.
If Smon = 6 Then Jtag = 151 + Stag '31.28.31.30.31.
If Smon = 7 Then Jtag = 181 + Stag '31.28.31.30.31.30.
If Smon = 8 Then Jtag = 212 + Stag '31.28.31.30.31.30.31.
If Smon = 9 Then Jtag = 243 + Stag '31.28.31.30.31.30.31.31
If Smon = 10 Then Jtag = 273 + Stag '31.28.31.30.31.30.31.31.30.
If Smon = 11 Then Jtag = 304 + Stag '31.28.31.30.31.30.31.31.30.31.
If Smon = 12 Then Jtag = 334 + Stag '31.28.31.30.31.30.31.31.30.31.30.
End If
Temp2 = Jtag - Swta
If Temp2 < 0 Then Temp2 = 0 'Bei negativen werten problemm
Temp3 = Temp2 / 7 'Volle wochen seit jahres anfang
Kw = Temp3
Temp3 = Temp3 * 7 'genaue tagesanzahl für volle wochen
Temp4 = Temp2 - Temp3 'Tage in erste KW neues jahr (>4) oder letzte KW altes jahr (<5)
If Temp4 > 4 Then 'wenn tages in jahresanfangswoche >4 dann erste KW in neue Jahr
Kw = Kw + 2 'addieren erste woche und aktuelle woche
End If
If Temp4 < 5 Then 'wenn Tages in jahresanfangswoche <5 dann alle diese tage in letzte KW altes Jahr
Kw = Kw + 1
End If
If Schalt = 0 Then
Temp2 = Jtag - Swta 'wenn in altes jahr letzte woche noch bis mittwoch dann 1 KW
If Temp2 > 362 Then Kw = 1
Else
Temp2 = Jtag - Swta 'wenn in altes jahr letzte woche noch bis mittwoch dann 1 KW
If Temp2 > 361 Then Kw = 1 'letzte Jahres tage können auch in neue Jahr 1 woche eintretten
End If
End If
'Jtag => Jahrestag ab Jahresanfang
'Kw => Berechnete KW (Kalender Woche)


'---------------------------------------------------------------------------------------------------------
'--- PIPSTONE BEI VOLLE STUNDE 56 bis 59 Kurz und bei 00 Lang -------------------------------------------
'---------------------------------------------------------------------------------------------------------
If Ssek > 55 And Ssek < 60 Or Ssek = 0 Then
If Ssek = 0 Then
If Smin = 0 Then
If Shsek > 0 And Shsek < 30 Then
If Pipsen = 0 Then
P3.7 = 0
Pipsen = 1 'blokiert null sekunden piepsen (Bei DCF übernahme)
End If
Else
P3.7 = 1
End If
End If
Else
If Smin = 59 Then
If Shsek > 0 And Shsek < 10 Then
P3.7 = 0
Pipsen = 0 'schaltet null skunden piepsen wieder an
Else
P3.7 = 1
End If
End If
End If
Else
P3.7 = 1 'Bei andere falle Piepston abschalten
End If
'---------------------------------------------------------------------------------------------------------
Return

'---------------------------------------------------------------------------------------------------------
'---- Interrupt1 Routine (DCF77 Empfanger INPUT LOW=>125 bis131ms INPUT HIGH=>227 bis 229ms --------------
'---- Interrupt Dauer 51 µs und bei DCF Decodieren (Volle minute) 8,5ms ----------------------------------
'---------------------------------------------------------------------------------------------------------

Int1_int:
If Dcfs < 202 And Dcfs > 196 Then 'Minutensprung finden und DCF Dekodieren
'ACHTUNG bei andere empfänger eventuell anpassen
If Dcfl > 17 Then 'Signall low oder high in DCF Array speichern
Dcf(60) = 1 'wert von parity Date "58"bit noch speichern
Else
Dcf(60) = 0
End If
Shsek = 0
Ssek = 0
Gosub Dcfdecode 'DCF signall decodieren
Pointer = 0
End If
Incr Pointer
'Kleiner 170ms => LOW Grösser 170ms => High
If Dcfl > 17 Then 'Signall low oder high in DCF Array speichern
Dcf(pointer) = 1
Else
Dcf(pointer) = 0
End If
Dcfs = 0
Dcfl = 0
Return
'---------------------------------------------------------------------------------------------------------
'--- DCF77 DEKODIER SOFTWARE ----------------------------------------------------------------------------
'---------------------------------------------------------------------------------------------------------
Dcfdecode:
Dmin = 0 'DCF minuten info
Dstd = 0 'DCF Stunden info
Dtag = 0 'DCF Tag info
Dwta = 0 'DCF Wochen Tag info
Dmon = 0 'DCF Monat info
Djah = 0 'DCF Jahr info
Dcferm = 0 'Minuten Patity error löschen
Dcfers = 0 'Stunden Patity error löschen
Dcferd = 0 'Datum Patity error löschen
Par = 0 'Parity=0
For I = 1 To 8 'scann Array für minuten
Pointer = I + 22
If Dcf(pointer) = 1 Then
If I = 1 Then
Dmin = Dmin + 1
Par = Par + 1
End If
If I = 2 Then
Dmin = Dmin + 2
Par = Par + 1
End If
If I = 3 Then
Dmin = Dmin + 4
Par = Par + 1
End If
If I = 4 Then
Dmin = Dmin + 8
Par = Par + 1
End If
If I = 5 Then
Dmin = Dmin + 10
Par = Par + 1
End If
If I = 6 Then
Dmin = Dmin + 20
Par = Par + 1
End If
If I = 7 Then
Dmin = Dmin + 40
Par = Par + 1
End If
If I = 8 Then
Par = Par + 1
End If
End If
Dcferm = Par Mod 2 'parity minuten test
Next I
Par = 0
For I = 1 To 7 'scann Array für Stunden
Pointer = I + 30
If Dcf(pointer) = 1 Then
If I = 1 Then
Dstd = Dstd + 1
Par = Par + 1
End If
If I = 2 Then
Dstd = Dstd + 2
Par = Par + 1
End If
If I = 3 Then
Dstd = Dstd + 4
Par = Par + 1
End If
If I = 4 Then
Dstd = Dstd + 8
Par = Par + 1
End If
If I = 5 Then
Dstd = Dstd + 10
Par = Par + 1
End If
If I = 6 Then
Dstd = Dstd + 20
Par = Par + 1
End If

If I = 7 Then
Par = Par + 1
End If
End If
Dcfers = Par Mod 2 'parity stunden test
Next I

Par = 0
For I = 1 To 23 'scann Array für Tag bis Jahr
Pointer = I + 37
If Dcf(pointer) = 1 Then
If I = 1 Then
Dtag = Dtag + 1
Par = Par + 1
End If
If I = 2 Then
Dtag = Dtag + 2
Par = Par + 1
End If
If I = 3 Then
Dtag = Dtag + 4
Par = Par + 1
End If
If I = 4 Then
Dtag = Dtag + 8
Par = Par + 1
End If
If I = 5 Then
Dtag = Dtag + 10
Par = Par + 1
End If
If I = 6 Then
Dtag = Dtag + 20
Par = Par + 1
End If
If I = 7 Then
Dwta = Dwta + 1
Par = Par + 1
End If
If I = 8 Then
Dwta = Dwta + 2
Par = Par + 1
End If
If I = 9 Then
Dwta = Dwta + 4
Par = Par + 1
End If
If I = 10 Then
Dmon = Dmon + 1
Par = Par + 1
End If
If I = 11 Then
Dmon = Dmon + 2
Par = Par + 1
End If
If I = 12 Then
Dmon = Dmon + 4
Par = Par + 1
End If
If I = 13 Then
Dmon = Dmon + 8
Par = Par + 1
End If
If I = 14 Then
Dmon = Dmon + 10
Par = Par + 1
End If
If I = 15 Then
Djah = Djah + 1
Par = Par + 1
End If
If I = 16 Then
Djah = Djah + 2
Par = Par + 1
End If
If I = 17 Then
Djah = Djah + 4
Par = Par + 1
End If
If I = 18 Then
Djah = Djah + 8
Par = Par + 1
End If
If I = 19 Then
Djah = Djah + 10
Par = Par + 1
End If
If I = 20 Then
Djah = Djah + 20
Par = Par + 1
End If
If I = 21 Then
Djah = Djah + 40
Par = Par + 1
End If
If I = 22 Then
Djah = Djah + 80
Par = Par + 1
End If
If I = 23 Then
Par = Par + 1
End If
End If
Dcferd = Par Mod 2 'parity test für letzte daten block
Next I
Dcferr = Dcferm + Dcfers 'Globale Parity error erzeugen
Dcferr = Dcferr + Dcferd

If Djah = 0 Then Return 'bei keine empfang parity ist auch OK aber
If Dwta = 0 Then Return 'DCF signall ist auch faisch
If Dmon = 0 Then Return
If Dtag = 0 Then Return
If Dcferr = 0 Then 'wenn daten ok dann softuhr setzen
Shsek = 0 '0.01s und sekunden synchronisieren
Ssek = 0
Smin = Dmin 'Alle DCF dekodierte werte in softuhr übernemen
Sstd = Dstd
Stag = Dtag
Swta = Dwta
Smon = Dmon
Sjah = Djah
End If
Return




'---------------------------------------------------------------------------------------------------------
'--- LCD DISPLAY ANZEIGE ROUTINE --- KANN DURCH USER BELIEBIG GEENDERT WERDEN ----------------------------
'---------------------------------------------------------------------------------------------------------
Displayuhr: 'softuhr anzeigen
If Dcfs > 240 Then Dcferr = 1 'wenn keine impulse von DCF empfanger auch Parity error setzen

Upperline 'uhr zeit zeigen
If Sstd < 10 Then
Lcd "0" ; Sstd ; ":" ;
Else
Lcd Sstd ; ":" ;
End If
If Smin < 10 Then
Lcd "0" ; Smin ; ":" ;
Else
Lcd Smin ; ":" ;
End If
If Ssek < 10 Then
Lcd "0" ; Ssek ;
Else
Lcd Ssek ;
End If
'Wochentag decodieren
If Swta = 0 Then 'wenn noch keine daten dann Synchro
Lcd " SYNCHRO";
End If
If Swta = 1 Then
Lcd " MO";
End If
If Swta = 2 Then
Lcd " DI";
End If
If Swta = 3 Then
Lcd " MI";
End If
If Swta = 4 Then
Lcd " DO";
End If
If Swta = 5 Then
Lcd " FR";
End If
If Swta = 6 Then
Lcd " SA";
End If
If Swta = 7 Then
Lcd " SO";
End If
If Dcferr = 0 Then
Lcd " DCF "; 'DCF OK
Else
Lcd " XTL "; 'Wenn keine DCF synchro dann Quarz UHR Modus
End If
Lowerline
If Stag < 10 Then
Lcd "0" ; Stag ; "." ;
Else
Lcd Stag ; "." ;
End If
If Smon < 10 Then
Lcd "0" ; Smon ; "." ;
Else
Lcd Smon ; "." ;
End If
If Sjah < 10 Then
Lcd "200" ; Sjah ;
Else
Lcd "20" ; Sjah ;
End If
If Jtag > 0 Then
If Kw > 9 Then
Lcd " KW" ; Kw ;
Else
Lcd " KW0" ; Kw ;
End If
Else
Lcd " QUARZ"
End If
Return


Hier übrigens ein Thread der zufällig "dcf77-empfang mit bascom...?" heißt:
https://www.roboternetz.de/phpBB2/viewtopic.php?t=2991

und hier der Interessante Link: http://www.mcselec.com/an_122.htm

Viel Spaß ;-)

MFG Moritz

Adam
02.12.2004, 17:02
ok ... so genau muss es dann nun wieder auch nicht sein :]
wie kann ich denn nun ohne das Modul die Uhrzeit erzeugen? Mit Interrupt, das ist klar, aber wie stelle ich es so ein, dass ein Takt genau 1sec. dauert?

RCO
02.12.2004, 17:06
Lies dir den Thread mal durch, so schlimm ist es glaub ich garnicht ;-)
Kann man da nicht ansonsten mit interrupt arbeiten? Es würde auch reichen, eine DCF-Antenne zu nehmen, und das Signal nicht zu decodieren, sondern nur als Tatkgeber zu benutzen, Die Zeit müsste man dann einmal einstellen, und die Antenne an den Interrupt hängen, oder?

MFG Moritz

Dino Dieter
02.12.2004, 17:51
Hallo

Schau mal hier rein. Ist gut erklärt dort.

http://www.mikrocontroller.net/forum/read-4-57760.html#new

MFG
Dieter

churchi
02.12.2004, 19:56
Ich weiß zwar nicht ob noch die Ports frei sind und der Timer noch verfügbar, aber am einfachsten löst man sowas find ich immer noch mit einem Uhrenquarz.
Der Uhrenquarz als Zeitgeber für den Timer (an den Timer0 glaub ich kann der Uhrenquarz direkt angeschlossen werden).
Mit einem Prescaler von 256 kommt dann der Interrupt immer genau nach 1s.
Diese genaue Sekunde kann man dann nicht nur für die Uhrzeit nehmen...

Wenn man jedoch eine genaue Uhrzeit braucht, dann ist ein DCF-Funkempfänger natürlich die 1. Wahl.

Adam
02.12.2004, 20:09
also die t0 und t1 anschlüße sind noch frei, dann könnte ich das doch mit der Methode machen, die in dem o.g. Link beschrieben ist. Den Prescaler entsprechend berechnen, das er nach 1 sec. ein Interrupt auslöst in dem sec++ gerechnet wird. Und dadraus eben die akt. Uhrzeit (die einmal vorgegeben wird)

churchi
02.12.2004, 20:13
also entweder nimmst du einen Uhrenquarz oder die oben im Link beschriebene Möglichkeit.
Eine Art müsste genügen - beide gleichzeitig zu implementieren währ overkill

01.04.2005, 07:43
ich habe mich auch mit der DCF-77-uhr beschäftigt - falls es dir hilft lege ich mein programm als anlage bei...

http://www.mikrocontroller.net/attachment.php/171098/DCF_Alarm.bas

Grüsse Andy

vajk
11.02.2006, 13:09
Hab meinen ursprünglichen Beitrag zum DCF77-Thema hierher: https://www.roboternetz.de/phpBB2/viewtopic.php?p=157342#157342 verschoben, da er nun wirklich nichts mit Basic zu tun hatte (Hatte übersehen, in welchem Forumszweig ich mich befunden habe)
Alles Gute,
Vajk

gandalf
12.02.2006, 00:24
ich habe mich auch mit der DCF-77-uhr beschäftigt - falls es dir hilft lege ich mein programm als anlage bei...

http://www.mikrocontroller.net/attachment.php/171098/DCF_Alarm.bas

Grüsse Andy

Sieht relativ groß aus. läßt sich das mit der Freeware von Bascom noch brennen ?