|
|
Programm |
|
|
|
|
|
|
|
dESµ DCF 77 - Funkuhrempfänger |
|
|
|
|
|
|
|
DCF77.INC das Funkuhrmodul |
|
|
|
|
|
|
|
|
|
|
|
Dieser Treiber decodiert das eingespeiste, digitale und nicht invertierte, TTL Funksignal eines DCF-Empfängers. Dieses Signal muss auf einem Torbit des MC 8051-Derivats angeschlossen werden. Welches Torbit benutzt werden soll muss im Kopf des Programms eingetragen werden. Die Stelle wurde farblich hervorgehoben. |
|
|
|
|
|
|
|
; DCF77.INC
; ---------- Version 300895 (für Funkuhr DCF77)
; (c)04 Schwarzer, www.GoBlack.de
; Das Programm decodiert Signale von DCF77 -Empfängern, die
; ein nicht invertiertes, digitales TTL-Zeitsignal erzeugen,
; das den Normen der PTB -Braunschweig entspricht.
; Das Programm ist in der vorliegenden Form mit dem
; dESy DCF77 Empfängermodell einsetzbar.
; Die Treiberprogramme dieser Datei müssen der Harware
; angepaßt werden. Es sind folgende Parameter einzustellen.
; - Der Timer des MC 8051-Systems, der zur Erzeugung des 10
; mSec-Referenz -IRQ- Signals benutzt werden soll. Es
; können Timer 0 oder 1 benutzt werden.
$SET (TIMER = 0) ; zu verwendender Timer
; - Der Toreingang, auf dem das ZeitSignal eingespeist
; wird. (Es können alle freien Bit der EingangsTore des
; MC8051- Systems benutzt werden)
DCFTor BIT P1.7 ; BitEingang des DCF-Signals
; - Der Signalzustand, bei dem das ZeitSignal zur Anzeige
; einer abgelaufenen Sekunde aktiv ist. Es kann bei log 0
; oder 1 aktiv sein.
$SET (DCFaktiv = 1) ; aktiver Signalpegel dESy DFC77
; - Einige Status-Zustände der Uhr können auf Leuchtdioden
; ausgegeben werden hierzu wird Tor P1 benutzt.
; Erklärung zu den Signalen siehe Z1Flg.
Z1Flg EQU P1 ; Statuszustände
; Abhängig von der Taktfrequenz des Microcontrollers muß
; der Nachladewert des Timers gesetzt werden. Beide Timer,
; T0 und T1, werden im Modus 2 betrieben,
; (16Bit Vorwärtszähler). Es wird also vom Nachlade-
; wert bis 0 hochgezählt. Die Timer zählen mit fosz/12,
; der internen Takfrequenz des MC 80515
; Daraus folgt für 12MHz/12 der Wert -10.000 = D8F0h für
; 10mSec
mS10_H EQU 0D8h ; MSB des 10 mSec -Timer Nachladewertes
mS10_L EQU 0F0h ; LSB des 10 mSec -Timer Nachladewertes
; Für den verwendeten Timer wird die höchste IRQ-Priorität
; eingestellt. Die Prioritäten der anderen IRQ's
; verschieben sich dadurch von der Voreinstellung um eine
; Ebene nach unten.
; Definitionen für die Wochentagnummer in <dTagNum>
; Die empfangene Nummer für den Namen des Wochentages
; entspricht folgendem Schema. Die Zahl in TagNum
; bedeutet ...
; 0 - den Startzustand des Programms
; 1 - Montag 2 - Dienstag 3 - Mittwoch 4 - Donnerstag
; 5 - Freitag 6 - Sonnabend 7 - Sonntag
; DATA MODULE -----------------------------------------
;DatenSegment mit 13 Bytes
DCF77_DATA SEGMENT DATA
;DatenSegment Bitadres.bar
DCF77_DATABA SEGMENT DATA BITADDRESSABLE
;BitSegment mit 22 Bits
DCF77_BIT SEGMENT BIT
; Die Anzeigeregister <dx> enthalten die auszugebende
; Zeitinformation, auch wenn die Uhr ohne DCF-Signal
; arbeitet. Die EinleseRegister <ix> enthalten die DCF-
; Angaben. Diese werden in die Anzeigeregister über-
; tragen. Die Informationen liegen in beiden Register-
; arten im BCD-Format vor. Die Abfolgeder <di> und <dx>
; Register darf nicht geändert werden. (indirekte
; Adressierung über R0)
RSEG DCF77_DATA
dSEK: DS 1 ; AnzeigeRegister: Sekunden
dMIN: DS 1 ; Minuten
dSTD: DS 1 ; Stunden
dTAG: DS 1 ; Tag
dTagNam: DS 1 ; Nr des TagNamens
dMON: DS 1 ; Monat
dJAHR: DS 1 ; Jahr
iMIN: DS 1 ; EinleseRegister: Minuten
iSTD: DS 1 ; Stunden
iTAG: DS 1 ; Tag
iTagNam: DS 1 ; Nr des TagNamens
iMON: DS 1 ; Monat
iJAHR: DS 1 ; Jahr
RSEG DCF77_BIT
; Betriebsflaggen des Programms: Diese Flaggen werden im
; Programm benutzt und geändert. Der Benutzer kann sie
; abfragen, sollte sie jedoch nicht ändern.
InfoBit: DBIT 1 ; 0: empfangenes InformationsBit = 0
; 1: empfangenes Informationsbit = 1
PBit: DBIT 1 ; Paritätsbit bei Zeit/Datum Infos
DCFalt: DBIT 1 ; vorheriger Zustand des DCF-Signals
Look_s59: DBIT 1 ; 0: Einlesen der decodierten Zeit
; 1: nach der 59. Sekunde suchen
Sync_RES: DBIT 1 ; 1: Zeit wurde nach RESET mindestens
; einmal synchronisiert
; BenutzerInformationsFlaggen: Diese Flaggen werden im
; Programm gesetzt und stehen dem Benutzer zur Verfügung.
; Das Benutzerprogramm sollte sie nach Auswertung der
; Information mit 'clr BITx' löschen.
SecFlg: DBIT 1 ; 1: ganze Sekunde erreicht
MinFlg: DBIT 1 ; 1: ganze Minute erreicht
StdFlg: DBIT 1 ; 1: ganze Stunde erreicht
Blink_4Hz: DBIT 1 ; 4 Hz Flagge für z.B. Alarm
Blink_2Hz: DBIT 1 ; 2 Hz Flagge "
; ZustandsFlaggen: Dies Flaggen signalisiern Betriebs-
; zustände des Programms. Sie werden vom Programm gesetzt
; und gelöscht. Der Benutzer kann sie z.B. mit LED
; anzeigen lassen.
RSEG DCF77_DATABA
Z2Flg: DS 1
ACT EQU Z1Flg.0 ; 1: DFC77-Uhr wird angezeigt
; 1/0: blinkt wenn nicht synchron
ST0 EQU Z1Flg.7 ; 1: 100mSec-InfoBit erkannt
; => log 0
ST1 EQU Z1Flg.6 ; 1: 200mSec-InfoBit erkannt
; => log 1
ST2 EQU Z1Flg.5 ; 1: ImpulsweitenFehler bei
; 100/200 mSec Bit
ST3 EQU Z1Flg.4 ; 1: 1 Sec Impulsabstand
ST4 EQU Z1Flg.3 ; 1: 2-Sec Impulsabstand
; => Minute um
ST5 EQU Z1Flg.2 ; 1: ImpulsabstandFehler bei
; 1/2 Sec
ANTE BIT Z2Flg.7 ; 0: Betriebs- 1: Reserveantenne
AMEZ BIT Z2Flg.6 ; 1: Ankünd. 1Std vor Wechsel
; MEZ/MESZ/MEZ
MESZ BIT Z1Flg.1 ; 1: MESZ -Mitteleurop Sommerzeit
MEZ BIT Z2Flg.4 ; 1: MEZ -Mitteleurop Normalzeit
ASSEC BIT Z2Flg.3 ; 1: Ankünd. 1Std vor
; Einfüg.Schaltsekunde
DCFTIME BIT Z2Flg.0 ; 1: DCF77 -UhrZeit wird angezeigt
; 0: Uhrzeit wird vom Programm
; erzeugt
; CODE MODULE -------------------------------------------
$IF (TlMER =0) ; wenn Timer 0 gewählt wurde
TMOD_CLR EQU 11110001b ; F1h durch 'anl'
; Gate, C/T, M1 werden 0
TMOD_SET EQU 00000001b ; 01h durch 'orl'
; M0 wird 1
TLx EQU TL0 ; Adresse: Zählregister LOW
THx EQU TH0 ; " HIGH
ETx EQU ET0 ; Bitadr: Freigabe Timer IRQ
IP0m EQU 00000010b ; höchste Priorität für den Timer
IP1m EQU 00000010b ; "
TRx EQU TR0 ; Bitadr: Timer starten
$ELSE ; wenn Timer 1 gewählt wurde
TMOD_CLR EQU 00011111b ; 1Fh durch 'anl'
; Gate, C/T, M1 werden 0
TMOD_SET EQU 00010000b ; 10h durch 'orl
; M0 wird 1
TLx EQU TL1 ; Adresse: Zählregister LOW
THx EQU TH1 ; " HIGH
ETx EQU ET1 ; Bitadr: Freigabe Timer IRQ
IP0m EQU 00001000b ; höchste Priorität für den Timer
IP1m EQU 00001000b ; "
TRx EQU TR1 ; BitAdr: Timer starten
$ENDIF
USING 2 ; Registerbank 2 -Belegung
; ----------------------------------------
; R0: Datenregister-Zeiger
; R1: Schleifenzähler, Schiebezähler
; R2: 10mSec-Zähler bis Sekunde
; R3: enthält momentane Sekunde (Zähler)
; R4: Sekundenzähler bis Minute
; R5: nicht benutzt
; R6: nicht benutzt
; R7: nicht benutzt
DCF77_PROG SEGMENT CODE
RSEG DCF77_PROG
|
|
; -------------------------------------------------------
; Name: DCF77_Init
; Typ: Unterprogramm
; -------------------------------------------------------
; Das Unterprogramm initialisiert den DCF77-Interrupt-
; treiber. Es muß vom Hauptprogramm einmal aufgerufen
; werden. Danach wird mit der Verarbeitungdes DCF-
; Eingangssignals über die IRQ -Service-Routine
; 'DCF77_Irq' begonnen. Es führt die folgend genannten
; Funktionen aus:
; - Timer für 10mSec_IRQ initialisieren
; - 10mSec_IRQ Priorität setzen und freigeben
; - Betriebsbits der DCF77-Uhr initialisieren
; - Zeitregister löschen
; - Registerbank 2 initialisieren
; Übergaben: keine
; Rückgaben: TMOD, TLx, THx, ETx, TRx, IP0, IP1
; Ändert: dSEK, dMIN, dSTD, dTagNam, dTAG, dMON, dJAHR
; DCFalt, Look_s59, SecFlg, MinFlg, StdFlg
; DCFTIME, Sync_RES.
; Unterprogramme: keine
; Stacknutzung: 4 Bytes
DCF77_Init: push ACC ; Akku und Flags sichern
push PSW
mov PSW, #10h ; Registerbank 2 setzen
anl TMOD, #TMOD_CLR ; Timer: 16-Bit-Timer
orl TMOD, #TMOD_SET ; Interner Takt
mov TLx, #mS10_L ; Wert für 10 mSec
mov THx, #mS10_H ; Interrupt laden
setb ETx ; Freigabe Timer IRQ
mov IP0, IP0m ; Priorität Timer IRQ
mov IP1, IP1m ; setzen
setb EAL ; Freigabe aller IRQ
setb TRx ; Start des Timers
$IF (DCF_INF= 0)
setb DCFalt ; Steuerbit löschen bei 0-aktiv
$ELSE
clr DCFalt ; Steuerbit löschen bei 1-aktiv
$ENDIF
setb Look_s59 ; nach der 59.Sekunde suchen
clr SecFlg ; Sekunde erreicht Flag löschen
clr MinFlg ; Minute erreicht Flag löschen
clr StdFlg ; Stunde erreicht Flag löschen
clr DCFTIME ; interne Uhr erzeugt die Zeit
clr ACT
clr Sync_RES ; noch nicht nach RESET synchron
clr A
mov R0, #dSEK
mov R1, #7
DELE: mov @R0, A ; Zeitregister <dSEK> bis
inc R0 ; <dJAHR> löschen
djnz R1, DELE
mov R2, A ; Zählregister der Regist.bank 2
mov R3, A ; löschen
mov R4, A
pop PSW ; Flaggenregister und Akku
pop ACC ; wieder herstellen
ret ; Initialisierung beendet
|
|
|
; -------------------------------------------------------
; Name: DCF77_Irq
; Typ: IRQ -ServiceProgramm
; -------------------------------------------------------
; Über 'DCF77_Irq' wird alle 10 mSec das DCF77-Signal
; abgetastet und entsprechend verarbeitet. Das Programm
; führt folgende Funktionen aus
; - Timer für den nächsten 10 mSec_IRQ vorbereiten
; - 10 mSec-Zähler zur Erkennung einer Sekunde erhöhen
; - DCF-Signal abtasten und Signalwechsel erkennen
; - Impulsdauer und Impulsabstand messen
; - Synchronisation mit dem DCF77-Signal,
; - setzen von Blinkbits 2 und 4 Hz sowie von Steuerbits
; nach vollen Sekunden, Minuten und Stunden
; Übergaben: DCFTor, DCFalt
; Rückgaben: Zeitregister, Betriebsflaggen,
; Benutzerflaggen, Zustandsflaggen
; Ändert: Zeitregister, Betriebsflags, Benutzerflags,
; Zustandsflags, RegBank2: R0, R1, R2, R3, R4
; TLx, THx, TRx, EAL
; Unterprogramme: DCF_Uhr, Uhr
; Stacknutzung: 7 Bytes
DCF77_Irq: push ACC ; die benutzten Prozessor-
push B ; register retten
push PSW
push DPH
push DPL
mov PSW, #10h ; Registerbank 2 setzen
; Neuladen des Timers für den 10 mSec_IRQ. (Die Addition
; von Werten zum Timer ergibt eine Laufzeitverkürzung,
; da Vorwärtszähler)
clr EAL ; alle aktiven IRQ sperren
clr TRx ; Timer: STOP
mov A, #mS10_L+6; Startwert
; TLx= LSB(-10000+6) 1
add A, TLx ; mom.Wert TLx + Startwert
; TLx 1
mov TLx, A ; = neuer Wert TLx. 1
mov A, #mS10_H ; Startwert
; THx= MSB(-10000+6) 1
addc A, THx ; mom.Wert THx + Startwert
; THx + C
mov THx, A ; = neuer Wert Thx. 1
setb TRx ; Timer: START
setb EAL ; alle aktiven IRQ freigeben
; Sekunden-Zähler erhöhen
inc R4
inc R2 ; 10 mSec-Zähler erhöhen
cjne R2, #25,INC1
sjmp INC5 ; Aufrufe zur Erzeugung von
INC1: cjne R2, #50,INC2
sjmp INC4 ; 2Hz und 4Hz -Signalen
INC2: cjne R2, #75,INC3
clr ST0
clr ST1
sjmp INC5
INC3: cjne R2, #100,WCH ; Sekunde erreicht ?
mov R2, #0 ; 10 mSec-Zähler löschen und
call Uhr ; die Sekunde auf Zeitreg.
; addieren
INC4: jb DCFTIME, inc41
cpl ACT
inc41: setb Blink_2Hz ; für AlarmFunktionen
; verwendbar
INC5: setb Blink_4Hz ; der Benutzer setzt die
; Flaggen zurück
; Abfrage ob ein Wechsel des Signalpegels
; im DCF77-Signal stattfand
WCH: clr A
mov C, DCFalt ; alt Wert des Signals nach C
rlc A ; C --> ACC.0
mov C, DCFTor ; neu Wert des Signals nach C
$IF (DCFaktiv= 1)
cpl C ; wenn 1 aktiv auf 0 setzen
$ENDIF
mov DCFalt, C ; neuen Wert speichern
rlc A ; C --> ACC.0 ACC0 --> ACC1
jz LOW_LOW ; Alt: LOW Neu: LOW
cjne A, #03h,NxtTst
jmp HIG_HIG ; Alt: HIGH Neu: HIGH
NxtTst: cjne A, #02h,LOW_HIG ; 0 -> 1 -Übergang
jmp HIG_LOW ; 1 -> 0 -Übergang
; 0 -> 0 und 1 -> 1 Übergänge
LOW_LOW:
HIG_HIG: jmp NormalExit ; Zähler Impulszeit erhöhen
; 0 -> 1 Übergang
LOW_HIG: clr C ; wegen subb
mov A, R4 ; untere Toleranz 100 mSec
subb A, #6 ; < 60mSec
jc ImpErr ; Sprung bei Fehler
mov A, R4 ; oberen Toleranz 100 mSec
subb A, #13 ; > 130mSec
jnc LHI ; Sprung bei Fehler
call Imp100 ; .. Bit anzeigen
jb Look_s59, ExJmp ; beiSuche nach 59.Sec= 1
clr InfoBit ; iMPULSiNFORMATION 0
; verarbeiten
sjmp ADDUP
LHI: mov A, R4 ; untere Toleranz 200 mSec
subb A, #15 ; < 160 mSec
jc ImpErr ; Sprung bei Fehler
mov A, R4 ; oberen Toleranz 200 mSec
subb A, #23 ; >230mSec
jnc ImpErr ; Sprung bei Fehler
call Imp200 ; .. Fehler anzeigen
jb Look_s59, ExJmp ; beiSuche nach 59.Sec= 1
setb InfoBit ; iMPULSiNFORMATION 1
; verarbeiten
ADDUP: mov A, R3 ; Input -SekundenZähler+1
add A, #1
da A ; wegen BCD Zählung
mov R3, A
call DCF_Uhr ; Sekunden InfoBits
jnc ExJmp
call dParErr ; ein ParitätsFehler
sjmp FehlerExit
ExJmp: sjmp NormalExit
ImpErr: call dImpwErr ; FehlerBit Impulsdauer set
sjmp FehlerExit
; 1 -> 0 Übergang
HIG_LOW: clr C ; wegen subb
mov A, R4 ; untere Toleranzgrenze 1 Sec
subb A, #93 ; < 930 mSec
jc ImpaErr ; Sprung bei Fehler
mov A, R4 ; obere Toleranzgrenze 1 Sec
subb A, #107 ; >1070 mSec
jnc MIN59 ; Sprung bei Fehler
call Imp1000
sjmp M62
MIN59: mov A, R4 ; untere Toleranzgrenze 2 Sec
subb A, #193 ; <1930 mSec
jc ImpaErr ; Sprung bei Fehler
mov A, R4 ; obere Toleranzgrenze 2 Sec
subb A, #207 ; > 2070 mSec
jnc ImpaErr ; Sprung bei Fehler
call Imp2000
jb Look_s59, M60 ; wenn suche nach 59.Sec= 1
mov dSEK, #0 ; Display Register aktualis.
mov dMIN, iMIN ; die Input-Register werden
; in die
mov dSTD, iSTD ; Display Register übertragen
mov dTagNam,iTagNam
mov dTAG, iTAG
mov dMON, iMON
mov dJAHR, iJAHR
setb SecFlg ; Sekunde erreicht Flag set
setb MinFlg ; Minute erreicht Flag set
mov A, dMIN
cjne A, #0, WTR1
setb StdFlg ; Stunde erreicht Flag set
WTR1: setb DCFTIME ; Zeit wird von DFC-Uhr
; erzeugt
setb ACT
setb Sync_RES
mov R2, #00H ; 10mSec-Zähler bis Sekunde
; löschen
sjmp M61
M60: clr Look_s59 ; Suche nach 59.Sec abbrechen
M61: mov R3, #99h ; Einlese-Sekundenzähler
; setzen BCD
M62: mov R4, #00h ; Zähler für Impulsmessung
sjmp NormalExit
ImpaErr: call dImpaErr ; Impulsabstand-FehlerBIT
; setzen
mov R4, #00h ; Zähler für Impulsmessung
; löschen
; Ende des IRQ -ServiceProgramms
FehlerExit: clr DCFTIME ; interne Uhr muß die Zeit
; erzeugen
call SetLED
setb Look_s59 ; Suche nach 59.Sek beginnen
NormalExit: pop DPL ; gesicherte Register wieder
pop DPH ; einsetzen
pop PSW
pop B
pop ACC
reti ; Rückkehr DCF77-Irq -Handler
|
|
|
|
; -------------------------------------------------------
; Bearbeiten der ZustandsFlaggen. Sind St0 bis St5
; TorBits, können, die Zustände zu Testzwecken angezeigt
; werden.
Imp100: setb ST0 ; 100 mSEC-InfoBit erkannt
clr ST1
clr ST2
sjmp SetLED
Imp200: clr ST0 ; 200 mSEC-InfoBit erkannt
setb ST1
clr ST2
sjmp SetLED
dImpwErr: clr ST0 ; Fehler in der Impulsdauer
clr ST1
setb ST2
sjmp SetLED
dParErr: setb ST0 ; ParitätsFehler od.Sekunde=20
setb ST1
clr ST2
sjmp SetLED
Imp1000: setb ST3 ; 1 SEC-Impulsabstand erkannt
clr ST4
clr ST5
sjmp SetLED
Imp2000: clr ST3 ; 2 SEC-Impulsabstand erkannt
setb ST4
clr ST5
sjmp SetLED
dImpaErr: clr ST3 ; InfoBit-AbstandsFehler
clr ST4
setb ST5
SetLED: ret
|
|
|
|
; Name: DCF_Uhr
; Typ: Unterprogramm IRQ -Server
; Das Unterprogramm DCF_Uhr sammelt die Informationen der
; Sekundenimpulse und setzt sie zu der gesendeten Zeit,
; dem Datum, und den WochentagAngaben zusammen. Die
; fertigen Angaben werden auf ihre Parität geprüft und in
; die InputRegister <iMIN> bis <iJAHR> übertragen.
; Bei Paritätsfehlern oder einem Fehler im Startbit gibt
; das Programm C= 1 zurück. Andernfalls ist C= 0
; Übergaben: InfoBit, R3
; Rückgaben: EinleseRegister, Zustandsflaggen, C
; Ändert: EinleseRegister, Zustandsflaggen,
; A, PSW, R0, R1, PBit
; Unterprogramme: keine
; Stacknutzung: 0 Byte
DCF_Uhr: cjne R3, #00h, s15
sjmp Sec00 ; s00 Start neue Infoübertrag.
s15: cjne R3, #15h, s151
sjmp SecAnt ; s15 Flag Antenne setzen
s151: jc s60 ; s<15 nicht weiter abfragen
cjne R3, #16h, s17
sjmp SecAMez ; s16 Flag Ankünd. MEZ/MESZ
s17: cjne R3, #17h, s18
sjmp SecMesz ; s17 Flag MESZ einrichten
s18: cjne R3, #18h, s19
sjmp SecMez ; s18 Flag MEZ einzichten
s19: cjne R3, #19h, s20
sjmp SecASS ; s19 Flag Ankünd. Schaltsek.
s20: cjne R3, #20h, s21
sjmp Sec20 ; s20 StartBit InfoBytes
s21: cjne R3, #21h, s28
sjmp SecISt0 ; s21 Start der Minuten
S28: cjne R3, #28h, s29
sjmp SecPar ; s28 Parität d.Minuten
S29: cjne R3, #29h, s35
sjmp SecISt1 ; s29 Start des Stunden
s35: cjne R3, #35h, s36
sjmp SecPar ; s35 Parität d.Stunden
s36: cjne R3, #36h, s42
sjmp SecISt1 ; s36 Start der TagNr
s42: cjne R3, #42h, s45
sjmp SecISt1 ; s42 Start der TagName
s45: cjne R3, #45h, s50
sjmp SecISt1 ; s45 Start der MonatNr
s50: cjne R3, #50h, s58
sjmp SecISt1 ; s50 Start der JahrNr
s58: cjne R3, #58h,SecNrm
sjmp SecPar ; s58 Parität d.Datum
s60: sjmp SecExit
; Sekunde 00 (Zeitstart)
Sec00: clr A
mov R0, #iMIN
mov R1, #06H ; alle EingabeReg. löschen
Sec0L: mov R0, A
inc R0
djnz R1, Sec0L
sjmp SecExit
; Sekunde 15
; (Antennenbit 1: Betriebsantenne 0: Reserveantenne)
SecAnt: mov C, InfoBit
mov ANTE, C
sjmp SecExit
; Sekunde 16
; (Ankündigung MEZ/MESZ 1: 1Std vor jeweiligem Wechsel)
SecAMez: mov C, InfoBit
mov AMEZ, C
sjmp SecExit
; Sekunde 17 (ZonenzeitBit 1 ist 1: wenn MESZ)
SecMesz: mov C, InfoBit
mov MESZ, C
sjmp SecExit
; Sekunde 18 (ZonenzeitBit 2 ist 1: wenn MEZ)
SecMez: mov C, InfoBit
mov MEZ, C
sjmp SecExit
; Sekunde 19
; (Ankündigung Schaltsekunde 1: 1Std vor der Schaltsek.)
SecASS: mov C, InfoBit
mov ASSEC, C
sjmp SecExit
; Sekunde 20 (Startbit der Zeit/Datum-Übertragung immer 1)
Sec20: jnb InfoBit, SecErr ; war nicht das Startbit
mov R0, #iMIN-1 ; R0 zeigt auf Eing.Register
clr PBit ; Paritybit löschen
sjmp SecExit
; Sekunden mit Prüfbit bearbeiten
; (das sind Sekunde 28, 35, 58)
SecPar: jnb InfoBit, SecPaj ; Parität = InfoBit = 0
cpl PBit ; ermittelte Parität invert.
SecPaj: jb PBit, SecErr ; PBit=1 : Paritätsfehler
sjmp SecExit
; Sekunden mit erstem Bit einer InformationsFolge
; bearbeiten
SecISt1: mov A, @R0 ; zuletzt bearb. Register
SecIsL: clr C ; mit Nullen auffüll.da alle
rrc A ; Informat.eingetroffen sind
djnz R1, SecIsL
mov @R0, A ; diese Register speichern
SecISt0: inc R0 ; neues EingabeRegister setzen
mov R1, #8 ; Schiebe-Zähler neu setzen
; Normale Sekunden bearbeiten
SecNrm: mov A, @R0 ; R0 zeigt auf Eing.Reg. X
mov C, InfoBit ; InfoBit 0 od.1 zum Carry
jnc SecNrj ; wenn 0 nach SecNrj
cpl PBit ; wenn 1 zum ParityBit add.
SecNrj: rrc A ; Carry von rechts zum Akku
mov @R0, A ; A zum InputRegister X
dec R1 ; Zähler für Schiebeop.-1
SecExit: clr C ; Empfang ohne Fehler
ret
SecErr: setb C ; Fehler b.Startb.od.Parität
ret
|
|
|
|
; Name: Uhr
; Typ: UNTERPROGRAMM
; Das Programm wird im Sekundenrythmus aufgerufen, wenn
; der DCF77 -Empfang ausgefallen ist. Es schreibt dann
; wie bei einer Uhr Zeit und Datum fort.
; Die Zeit- und Datuminformationen werden im BCD-Format
; gespeichert. Ebenso die Nummer des Tagesnamen
; Übergaben: Zeitregister
; Rückgaben: Zeitregister, SecFlg, MinFlg, StdFlg
; Änderungen: Zeitregister,
; SecFlg, MinFlg, StdFlg, A, B, PSW
; Unterprogramme: keine
; Stacknutzung: 0 Byte
Uhr: mov A, dSEK ; Sekunde ..
add A, #1 ; .um 1 erhöhen
da A ; .zu BCD-Zahl machen
mov dSEK, A ; .und speichern
setb SecFlg ; .Sekunde erreicht Flag setzen
cjne A, #60h, UhrEnd ; -60 Sekunden vergangen ?
mov dSEK, #0 ; .Sekunde auf 0 setzen ..
setb MinFlg ; .Minute erreicht Flag setzen
mov A, dMIN ; Minute ..
add A, #1 ; .um 1 erhöhen
da A ; .zu BCD-Zahl machen
mov dMIN, A ; .und speichern
cjne A, #60h, UhrEnd ; -60 Minuten vergangen ?
mov dMIN, #0 ; .Minute auf 0 setzen
setb StdFlg ; .Stunde erreicht Flag setzen
mov A, dSTD ; Stunden ..
add A, #1 ; .um 1 erhöhen
da A ; .zu BCD-Zahl machen
mov dSTD, A ; .und speichern
cjne A, #24h, UhrEnd ; -24 Stunden vergangen ?
mov dSTD, #0 ; .Stunde auf 0 setzen
mov A, dTagNam ; Kennummer des Tages
inc A ; .um 1 erhöhen
mov dTagNam, A ; .und speichern
cjne A, #08h, UhrDat ; .größer als 8
mov dTagNam, #1 ; .dann 1 (Montag setzen)
UhrDat: mov A, dTAG ; Tag ..
add A, #1 ; .um 1 erhöhen
da A ; .zu BCD-Zahl machen
mov dTAG, A ; .und speichern
mov A, dMON ; .Monat holen
cjne A, #02h, Uhr2 ; -Monat Februar ?
mov A, dJAHR ; .prüfen ob Schaltjahr vor-
mov B, #04h ; liegt
div AB ; Division durch 4,
; wenn Rest=0
mov A, B ; .dann Schaltjahr
jnz Uhr1 ; .kein Schaltjahr
mov A, #30h ; .Schaltjahr Tage Februar+1
sjmp Uhr3
Uhr1: mov A, #29h ; .normale Tagzahl für Feb.
sjmp Uhr3
Uhr2: mov A,#TAGpM-Uhr3-1 ; für die Monate außer Feb.
add A, dMON ; Zahl der Tage/Monat+1 aus der
movc A, @A+PC ; TAGpM-Tabelle in den A laden
Uhr3: cjne A, dTAG, UhrEnd ; -MonatsEnde erreicht ?
mov dTAG, #1
mov A, dMON ; .Monat+1 und speichern
add A, #1
da A
mov dMON, A
cjne A, #13h, UhrEnd ; .nach 12.Monat
mov dMON, #1
mov A, dJAHR ; Jahr+1 und speichern
add A, #1
da A
mov dJAHR, A
UhrEnd: ret
TAGpM: DB '2)2121221212' ; Anzahl der Tage im
; Monat + 1 (als ASCII-
; Zeichen angegeben)
|
|
.de