The Man
21.06.2008, 13:09
Hallo da,
ich bin wie viele andere an einem Wecker dran. Der Kerncode für die
Uhrzeiterfassung steht und ich dachte ich mach den mal Publik.
Funktionsweise:
Der Mega8 läuft mit 4 MHz.
Ich fahre über den Timer1 den InterruptA , wenn Timer1 = 40000, dass
entspricht 10ms. Für die selbstständige Zeitnahme werden daraus die Takte Sekunden, Minuten und Stunden generriert.
Das DCF Modul hängt OHNE Interrupt an PINB 0
und das messen der Pulslängen passiert parallel zur internen Takterzeugung. Das verhindert, das das Programm durch Interruppte vom DCF Modul durcheinandermommt und weiterhin weitere Zeitkritische Prozesse möglich beleiben.
Als Herzstück des Progammes dient das Register "status_reg" in dessen Bitkodierung sich der Status des Progammes wiederfindet.
.def status_reg = r18
;BIT 0 zeigt an, ob PINB0 während der ISR HIGH war, dann = 1
;BIT 1 warten auf dcf Anfang =1 => erste lange Pause war da
;Bit 2 zweite lange Pause war da
;BIT 3 wird auf rising edge 1
;BIT 4 wird in dcf_einholen gesetzt, wenn 59 Bits da. enable für dcf_auswerten
;BIT 5 Signal wird ignoriert, bis 1
;BIT 6
;BIT 7 warten auf 2 komplette Signale, enable zum testen der Minuten, ob korrekt
Das Programm loggt sich über das warten auf eine Pause von mindestens 180ms auf den Start der Sequenz ein.
Nur so viel:
An Fehlerbhandlung habe ich zwei Mechanismen.
Das auftreten einer zweiten langen Pause signalisiert, dass ein weiterer Datensatz eingegangen sein muss. Ist die gezählte Bitzahl = 59, wird das Bitmuster ausgewertet. Stimmt das nicht, wird eine Fehlerroutine aufgerufen, in der alle Prozessrelevanten Register genullt werden. Bis auf die interne Zeitzählung natürlich.
Die intern ermittelte Zeitzählung kann nur überschrieben werden, wenn zwei Minutenabfolgen sich nur um 1 unterscheiden oder im Fall des Stundenwecjsels um 59.
Auf eine verbale Erklärung wie das Proramm genau Funktioniert verzichte ich hier. Ich werde dann mal zusehen, dass ich Flussdiagramme erstelle.
Edit:
wobei, ich merke, grade, dass ich keine .odt Dateien hochladen kann...
.include "m8def.inc"
.def tmp = r16
.def tmp2 = r17
.def status_reg = r18
;BIT 0 zeigt an, ob PINB,0 während der ISR HIGH war, dann = 1
;BIT 1 warten auf dcf Anfang =1 => erste lange Pause war da
;Bit 2 zweite lange Pause war da
;BIT 3 wird auf rising edge 1
;BIT 4 wird in dcf_einholen gesetzt, wenn 59 Bits da. enable für dcf_auswerten
;BIT 5 Signal wird ignoriert, bis 1
;BIT 6
;BIT 7 warten auf 2 komplette Signale, enable zum testen der Minuten, ob korrekt
.def pw_kurz = r19; Pulslänge der Highpegel
.def pw_lang = r20; Pulslänge der Lowpegel
.def bit_counter = r21
.def dcf_shift_reg = r24
.def sreg_save = r25
.equ dcf_BIT_counter = 104
.equ eins = 1
.equ zwei = 2
.equ vier = 4
.equ acht = 8
.equ zehn = 10
.equ zwanzig = 20
.equ vierzig = 40
.org 0x000
rjmp reset
.org OC1Aaddr
rjmp timer1_int
.org OC1Baddr
rjmp timer1b_int
;*****************************************
;*****************************************
; Pointer Z
;
; ms = RAM 100
; sc = RAM 101
; min = RAM 102
; stunde = RAM 103
; dcf_BIT_counter = RAM 104 (0 bis 8 für Bytecounter)
; dcf_min = RAM 113
; dcf_min_alt = RAM 114
; dcf_stu = RAM 115
;******************************************
;******************************************
; Pointer Y
; dcf BIT 0-7 = RAM 105
; dcf BIT 8-15 = RAM 106
; dcf BIT 16-23 = RAM 107
; dcf BIT 24-31 = RAM 107
; dcf BIT 32-39 = RAM 108
; dcf BIT 40-47 = RAM 109
; dcf BIT 48-55 = RAM 110
; dcf BIT 56-59 = RAM 111
reset:
;Stack wird bei Interrupts benötigt!
ldi tmp,HIGH(RAMEND)
out SPH,tmp
ldi tmp,LOW(RAMEND)
out SPL,tmp
ldi tmp,0xFF
out DDRD,tmp
ldi tmp,0
ldi r28,105
ldi r29,0
ldi r31,0
ldi r30,100
st Z+,tmp
st Z+,tmp
st Z+,tmp
st Z+,tmp
st Z,tmp
ldi r30,100
ldi tmp,0
out DDRC,tmp
ldi tmp,0b00110000
out PORTC,tmp
ldi tmp,0
out DDRB,tmp
ldi tmp,0
out PORTB,tmp
ldi tmp,0b00011000
out TIMSK,tmp
ldi tmp,0b00000001
out OCR1BH,tmp
ldi tmp,0b11111010 ;InterupptB wenn Timer1 = 201
out OCR1BL,tmp
ldi tmp,0b10011100
out OCR1AH,tmp
ldi r17,0b01000000 ; InterupptA wenn Timer1 = 40000
out OCR1AL,r17
ldi tmp,0b00000000
out TCCR1A,tmp
ldi tmp,0b11001001 ;Prescaler Timer1 = 1, enable Int, A und B
out TCCR1B,tmp
ldi r17,0
ldi status_reg,0
ldi r28,105
ldi dcf_shift_reg,0
st Y+,dcf_shift_reg
st Y+,dcf_shift_reg
st Y+,dcf_shift_reg
st Y+,dcf_shift_reg
st Y+,dcf_shift_reg
st Y+,dcf_shift_reg
st Y+,dcf_shift_reg
st Y,dcf_shift_reg
ldi r28,105
ldi bit_counter,0
sei
main:
;**********************************
; Funktion dcf_einholen wird aufgerufen, wenn
; pw_kurz > 4 und am ISR Anfang keinSignal da war
; pw_kurz wird in dcf_einholen gelöscht
;pw_kurz kann nur erhöht werden, wenn
;lange Pause da war => keine Abfrage von
;Bit 1 im status_reg nötig
cpi pw_kurz,5
brlo dcf_nicht_einholen
sbrc status_reg,0b00000000;
rjmp dcf_nicht_einholen
rcall dcf_einholen
;**********************************
; out PORTD,r28
dcf_nicht_einholen:
sbrs status_reg,0b00000001
rjmp nicht_auswerten;ertste Pause muss da gewesen sein, um dcf_auswerten aufzurufen
sbrs status_reg,0b00000010
rjmp nicht_auswerten;zweite Pause muss da gewesen sein, um dcf_auswerten aufzurufen
sbrc status_reg,0b00000100; ist Aufruf von dcf_auswerten in Abhängigkeit
; der zweiten langen Pause freigegeben, aber keine 59 Bits da, wird fehlerroutine
; aufgerufen
rjmp auswerten
rcall fehlerroutine ;Freigabe von dcf_einholen => 59 Bits da
rjmp nicht_auswerten
auswerten:
rcall dcf_auswerten
nicht_auswerten:
rjmp main
fehlerroutine:
;rücksetzten aller Prozessrelevanten Register
ldi status_reg,0
ldi r28,105
st Y,status_reg
ldi r30,104
st Z,status_reg
ldi r30,100
ldi pw_kurz,0
ldi pw_lang,0
ret
dcf_einholen:
/*
1.) prüft Pulsweite auf >< 160 ms
2.) erhöht Y Pointer, wenn ein Byte voll ist
3.) speichert bei "überlauf" von bit_counter=8 bit_counter = 0 ab
*/
ldi r30,dcf_BIT_counter
ld tmp,Z
ld dcf_shift_reg,Y;
lsr dcf_shift_reg
cpi pw_kurz,16; 1.) prüft Pulsweite auf >< 160 ms
brlo log_null
ori dcf_shift_reg,0b10000000
log_null:
st Y,dcf_shift_reg
sbrs tmp,0b00000011
rjmp vollmachen
ldi tmp,0
st Z,tmp
inc r28
ldi dcf_shift_reg,0
vollmachen:
ldi pw_kurz,0
ldi r30,100
inc bit_counter
cpi bit_counter,59
brne mehr1
ori status_reg,0b00010000;Freigabe von dcf_auswerten
ldi bit_counter,0
mehr1:
ret
dcf_auswerten:
ldi r30,dcf_BIT_counter
ldi tmp,0
st Z,tmp
ori status_reg,0b10000000
andi status_reg,0b11101011; löschen der Freigabe von lange Pause_war_da
; und Aufruf von dcf_auswerten
/*
wertet die Bitmuster in RAM 107 bis 109 in Minuten und Stunden aus
*/
;***************************
; Minuten
ldi r28,107
ld tmp,Y
inc r28;lädt von 107 dann inc zu 108
ldi r22,0
ldi tmp2,1
sbrc tmp,0b00000101
add r22,tmp2
ldi tmp2,2
sbrc tmp,0b00000110
add r22,tmp2
ldi tmp2,4
sbrc tmp,0b00000111
add r22,tmp2
ld tmp,Y
inc r28;lädt von 108 dann inc zu 109
ldi tmp2,8
sbrc tmp,0b00000000
add r22,tmp2
ldi tmp2,10
sbrc tmp,0b00000001
add r22,tmp2
ldi tmp2,20
sbrc tmp,0b00000010
add r22,tmp2
ldi tmp2,40
sbrc tmp,0b00000011
add r22,tmp2
ldi r30,113
st Z,r22
ldi r30,115
ldi r22,0
;***************************
;***************************
; Stunde
ldi tmp2,eins
sbrc tmp,0b00000101
add r22,tmp2
ldi tmp2,2
sbrc tmp,0b00000110
add r22,tmp2
ldi tmp2,4
sbrc tmp,0b00000111
add r22,tmp2
ld tmp,Y ;lädt von 109
ldi tmp2,8
sbrc tmp,0b00000000
add r22,tmp2
ldi tmp2,10
sbrc tmp,0b00000001
add r22,tmp2
ldi tmp2,20
sbrc tmp,0b00000010
add r22,tmp2
st Z,r22
ldi r22,0
ldi r30,100
;***************************
; nullen der Ramstellen
ldi r28,105
ldi dcf_shift_reg,0
st Y+,dcf_shift_reg
st Y+,dcf_shift_reg
st Y+,dcf_shift_reg
st Y+,dcf_shift_reg
st Y+,dcf_shift_reg
st Y+,dcf_shift_reg
st Y+,dcf_shift_reg
st Y,dcf_shift_reg
ldi r28,105
ret
timer1b_int:
in sreg_save,SREG
sbrs status_reg,0b00000111
rjmp wigger0
;************************************************* *****
; Uhrzeit gültig, wenn die neue Minute 1 größer als die
; alte ist, oder 59 kleiner bei Stundenwechsel
;Minuten und Stunden werden nur überschrieben, wenn
;korrekte Minutenfolge erkannt wurde
ldi r30,113
ld tmp,Z ;min neu
ldi r30,114
ld tmp2,Z;min alt
ldi r30,114
st Z,tmp ;neu wird zu alt für den folgenden Vergleich
cp tmp2,tmp
breq fehler
brsh min_uberlauf
sub tmp,tmp2
cpi tmp,1
brne fehler
rjmp sig_erfasst
min_uberlauf:
sub tmp2,tmp ; alt - neu
cpi tmp2,59
brne fehler
sig_erfasst:
;************************************************* *****
ldi r30,102
ld tmp2,Z
ldi r30,113
ld tmp,Z
;*************************
;überschreiben der Minute
ldi r30,102
mov tmp2,tmp
st Z,tmp2
;*************************
;*************************
;überschreiben der Stunde
ldi r30,115
ld tmp,Z
ldi r30,103
st Z,tmp
;*************************
fehler:
wigger0:
out SREG,sreg_save
reti
timer1_int:
in sreg_save,SREG
sbrs status_reg,0b00000101
rjmp ignore
;****************************
; setzt Bit 0 in status_reg, wenn Signal da (PINB_0 HIGH) ist
; setzte Bit 3 in status_reg auf rising edge
sbis PINB,0
rjmp kein_signal_an_pinb0
sbrs status_reg,0b00000000
ori status_reg,0b00001000
ori status_reg,0b00000001
rjmp signal_da
kein_signal_an_pinb0:
andi status_reg,0b11111110
signal_da:
;**************************
;***************************
; ausführen wenn kein Signal
; hier wird die Zeit zwischen zwei Highpegeln gemessen,
; um die lange Pause zu erfassen
sbrc status_reg,0b00000000
rjmp warten_auf_pause
; wenn Bit 0 nin status_reg = 0, dann kein Signal
inc pw_lang
cpi pw_lang,120
brlo warten_auf_pause
ldi r22,0
ldi pw_lang,0
sbrc status_reg,0b00000001
rjmp zweite_lange_Pause
ori status_reg,0b00000010
rjmp warten_auf_pause
zweite_lange_Pause:
ori status_reg,0b00000100
rjmp war_keins_da
warten_auf_pause:
war_keins_da:
;***************************
;***************************
;ausführen, wenn zu ISR Anfang Signal HIGH war und
;lange Pause da war (Einloggen auf Sequenzanfang)
sbrs status_reg,0b00000000
rjmp warten_auf_signal
sbrs status_reg,0b00000001
rjmp warten_auf_signal
inc pw_kurz
ldi pw_lang,0;sonst würden sich die kleinen Pausen aufsummieren
warten_auf_signal:
sbrc status_reg,0b00000000
ldi pw_lang,0
sbrs status_reg,0b00000011
rjmp fix
ldi r30,dcf_BIT_counter
ld tmp,Z
inc tmp
st Z,tmp
andi status_reg,0b11110111
fix:
ignore:
ldi r30,101
ld tmp,Z
cpi tmp,10
brlo wait_for_sig
sbic PINB,0
sbr status_reg,0b00100000;
wait_for_sig:
;****************** Zählen der ms RAM 100
ldi r30,100
ld tmp,Z
inc tmp
st Z,tmp
cpi tmp,100
brlo mehr
ldi tmp,0
st Z+,tmp
;******************
;****************** Zählen der sec RAM 101
ld tmp,Z
inc tmp
st Z,tmp
cpi tmp,60
brlo mehr
ldi tmp,0
st Z,tmp
inc r30
;******************
;****************** Zählen der min RAM 102
ld tmp,Z
inc tmp
out portd,tmp
st Z,tmp
cpi tmp,60
brlo mehr
ldi tmp,0
st Z,tmp
inc r30
;******************
;****************** Zählen der Stunde RAM 103
ld tmp,Z
inc tmp
st Z,tmp
cpi tmp,25
ldi tmp,0
st Z,tmp
;******************
mehr:
ldi r30,100
out SREG,sreg_save
reti
mfg,
The Man
ich bin wie viele andere an einem Wecker dran. Der Kerncode für die
Uhrzeiterfassung steht und ich dachte ich mach den mal Publik.
Funktionsweise:
Der Mega8 läuft mit 4 MHz.
Ich fahre über den Timer1 den InterruptA , wenn Timer1 = 40000, dass
entspricht 10ms. Für die selbstständige Zeitnahme werden daraus die Takte Sekunden, Minuten und Stunden generriert.
Das DCF Modul hängt OHNE Interrupt an PINB 0
und das messen der Pulslängen passiert parallel zur internen Takterzeugung. Das verhindert, das das Programm durch Interruppte vom DCF Modul durcheinandermommt und weiterhin weitere Zeitkritische Prozesse möglich beleiben.
Als Herzstück des Progammes dient das Register "status_reg" in dessen Bitkodierung sich der Status des Progammes wiederfindet.
.def status_reg = r18
;BIT 0 zeigt an, ob PINB0 während der ISR HIGH war, dann = 1
;BIT 1 warten auf dcf Anfang =1 => erste lange Pause war da
;Bit 2 zweite lange Pause war da
;BIT 3 wird auf rising edge 1
;BIT 4 wird in dcf_einholen gesetzt, wenn 59 Bits da. enable für dcf_auswerten
;BIT 5 Signal wird ignoriert, bis 1
;BIT 6
;BIT 7 warten auf 2 komplette Signale, enable zum testen der Minuten, ob korrekt
Das Programm loggt sich über das warten auf eine Pause von mindestens 180ms auf den Start der Sequenz ein.
Nur so viel:
An Fehlerbhandlung habe ich zwei Mechanismen.
Das auftreten einer zweiten langen Pause signalisiert, dass ein weiterer Datensatz eingegangen sein muss. Ist die gezählte Bitzahl = 59, wird das Bitmuster ausgewertet. Stimmt das nicht, wird eine Fehlerroutine aufgerufen, in der alle Prozessrelevanten Register genullt werden. Bis auf die interne Zeitzählung natürlich.
Die intern ermittelte Zeitzählung kann nur überschrieben werden, wenn zwei Minutenabfolgen sich nur um 1 unterscheiden oder im Fall des Stundenwecjsels um 59.
Auf eine verbale Erklärung wie das Proramm genau Funktioniert verzichte ich hier. Ich werde dann mal zusehen, dass ich Flussdiagramme erstelle.
Edit:
wobei, ich merke, grade, dass ich keine .odt Dateien hochladen kann...
.include "m8def.inc"
.def tmp = r16
.def tmp2 = r17
.def status_reg = r18
;BIT 0 zeigt an, ob PINB,0 während der ISR HIGH war, dann = 1
;BIT 1 warten auf dcf Anfang =1 => erste lange Pause war da
;Bit 2 zweite lange Pause war da
;BIT 3 wird auf rising edge 1
;BIT 4 wird in dcf_einholen gesetzt, wenn 59 Bits da. enable für dcf_auswerten
;BIT 5 Signal wird ignoriert, bis 1
;BIT 6
;BIT 7 warten auf 2 komplette Signale, enable zum testen der Minuten, ob korrekt
.def pw_kurz = r19; Pulslänge der Highpegel
.def pw_lang = r20; Pulslänge der Lowpegel
.def bit_counter = r21
.def dcf_shift_reg = r24
.def sreg_save = r25
.equ dcf_BIT_counter = 104
.equ eins = 1
.equ zwei = 2
.equ vier = 4
.equ acht = 8
.equ zehn = 10
.equ zwanzig = 20
.equ vierzig = 40
.org 0x000
rjmp reset
.org OC1Aaddr
rjmp timer1_int
.org OC1Baddr
rjmp timer1b_int
;*****************************************
;*****************************************
; Pointer Z
;
; ms = RAM 100
; sc = RAM 101
; min = RAM 102
; stunde = RAM 103
; dcf_BIT_counter = RAM 104 (0 bis 8 für Bytecounter)
; dcf_min = RAM 113
; dcf_min_alt = RAM 114
; dcf_stu = RAM 115
;******************************************
;******************************************
; Pointer Y
; dcf BIT 0-7 = RAM 105
; dcf BIT 8-15 = RAM 106
; dcf BIT 16-23 = RAM 107
; dcf BIT 24-31 = RAM 107
; dcf BIT 32-39 = RAM 108
; dcf BIT 40-47 = RAM 109
; dcf BIT 48-55 = RAM 110
; dcf BIT 56-59 = RAM 111
reset:
;Stack wird bei Interrupts benötigt!
ldi tmp,HIGH(RAMEND)
out SPH,tmp
ldi tmp,LOW(RAMEND)
out SPL,tmp
ldi tmp,0xFF
out DDRD,tmp
ldi tmp,0
ldi r28,105
ldi r29,0
ldi r31,0
ldi r30,100
st Z+,tmp
st Z+,tmp
st Z+,tmp
st Z+,tmp
st Z,tmp
ldi r30,100
ldi tmp,0
out DDRC,tmp
ldi tmp,0b00110000
out PORTC,tmp
ldi tmp,0
out DDRB,tmp
ldi tmp,0
out PORTB,tmp
ldi tmp,0b00011000
out TIMSK,tmp
ldi tmp,0b00000001
out OCR1BH,tmp
ldi tmp,0b11111010 ;InterupptB wenn Timer1 = 201
out OCR1BL,tmp
ldi tmp,0b10011100
out OCR1AH,tmp
ldi r17,0b01000000 ; InterupptA wenn Timer1 = 40000
out OCR1AL,r17
ldi tmp,0b00000000
out TCCR1A,tmp
ldi tmp,0b11001001 ;Prescaler Timer1 = 1, enable Int, A und B
out TCCR1B,tmp
ldi r17,0
ldi status_reg,0
ldi r28,105
ldi dcf_shift_reg,0
st Y+,dcf_shift_reg
st Y+,dcf_shift_reg
st Y+,dcf_shift_reg
st Y+,dcf_shift_reg
st Y+,dcf_shift_reg
st Y+,dcf_shift_reg
st Y+,dcf_shift_reg
st Y,dcf_shift_reg
ldi r28,105
ldi bit_counter,0
sei
main:
;**********************************
; Funktion dcf_einholen wird aufgerufen, wenn
; pw_kurz > 4 und am ISR Anfang keinSignal da war
; pw_kurz wird in dcf_einholen gelöscht
;pw_kurz kann nur erhöht werden, wenn
;lange Pause da war => keine Abfrage von
;Bit 1 im status_reg nötig
cpi pw_kurz,5
brlo dcf_nicht_einholen
sbrc status_reg,0b00000000;
rjmp dcf_nicht_einholen
rcall dcf_einholen
;**********************************
; out PORTD,r28
dcf_nicht_einholen:
sbrs status_reg,0b00000001
rjmp nicht_auswerten;ertste Pause muss da gewesen sein, um dcf_auswerten aufzurufen
sbrs status_reg,0b00000010
rjmp nicht_auswerten;zweite Pause muss da gewesen sein, um dcf_auswerten aufzurufen
sbrc status_reg,0b00000100; ist Aufruf von dcf_auswerten in Abhängigkeit
; der zweiten langen Pause freigegeben, aber keine 59 Bits da, wird fehlerroutine
; aufgerufen
rjmp auswerten
rcall fehlerroutine ;Freigabe von dcf_einholen => 59 Bits da
rjmp nicht_auswerten
auswerten:
rcall dcf_auswerten
nicht_auswerten:
rjmp main
fehlerroutine:
;rücksetzten aller Prozessrelevanten Register
ldi status_reg,0
ldi r28,105
st Y,status_reg
ldi r30,104
st Z,status_reg
ldi r30,100
ldi pw_kurz,0
ldi pw_lang,0
ret
dcf_einholen:
/*
1.) prüft Pulsweite auf >< 160 ms
2.) erhöht Y Pointer, wenn ein Byte voll ist
3.) speichert bei "überlauf" von bit_counter=8 bit_counter = 0 ab
*/
ldi r30,dcf_BIT_counter
ld tmp,Z
ld dcf_shift_reg,Y;
lsr dcf_shift_reg
cpi pw_kurz,16; 1.) prüft Pulsweite auf >< 160 ms
brlo log_null
ori dcf_shift_reg,0b10000000
log_null:
st Y,dcf_shift_reg
sbrs tmp,0b00000011
rjmp vollmachen
ldi tmp,0
st Z,tmp
inc r28
ldi dcf_shift_reg,0
vollmachen:
ldi pw_kurz,0
ldi r30,100
inc bit_counter
cpi bit_counter,59
brne mehr1
ori status_reg,0b00010000;Freigabe von dcf_auswerten
ldi bit_counter,0
mehr1:
ret
dcf_auswerten:
ldi r30,dcf_BIT_counter
ldi tmp,0
st Z,tmp
ori status_reg,0b10000000
andi status_reg,0b11101011; löschen der Freigabe von lange Pause_war_da
; und Aufruf von dcf_auswerten
/*
wertet die Bitmuster in RAM 107 bis 109 in Minuten und Stunden aus
*/
;***************************
; Minuten
ldi r28,107
ld tmp,Y
inc r28;lädt von 107 dann inc zu 108
ldi r22,0
ldi tmp2,1
sbrc tmp,0b00000101
add r22,tmp2
ldi tmp2,2
sbrc tmp,0b00000110
add r22,tmp2
ldi tmp2,4
sbrc tmp,0b00000111
add r22,tmp2
ld tmp,Y
inc r28;lädt von 108 dann inc zu 109
ldi tmp2,8
sbrc tmp,0b00000000
add r22,tmp2
ldi tmp2,10
sbrc tmp,0b00000001
add r22,tmp2
ldi tmp2,20
sbrc tmp,0b00000010
add r22,tmp2
ldi tmp2,40
sbrc tmp,0b00000011
add r22,tmp2
ldi r30,113
st Z,r22
ldi r30,115
ldi r22,0
;***************************
;***************************
; Stunde
ldi tmp2,eins
sbrc tmp,0b00000101
add r22,tmp2
ldi tmp2,2
sbrc tmp,0b00000110
add r22,tmp2
ldi tmp2,4
sbrc tmp,0b00000111
add r22,tmp2
ld tmp,Y ;lädt von 109
ldi tmp2,8
sbrc tmp,0b00000000
add r22,tmp2
ldi tmp2,10
sbrc tmp,0b00000001
add r22,tmp2
ldi tmp2,20
sbrc tmp,0b00000010
add r22,tmp2
st Z,r22
ldi r22,0
ldi r30,100
;***************************
; nullen der Ramstellen
ldi r28,105
ldi dcf_shift_reg,0
st Y+,dcf_shift_reg
st Y+,dcf_shift_reg
st Y+,dcf_shift_reg
st Y+,dcf_shift_reg
st Y+,dcf_shift_reg
st Y+,dcf_shift_reg
st Y+,dcf_shift_reg
st Y,dcf_shift_reg
ldi r28,105
ret
timer1b_int:
in sreg_save,SREG
sbrs status_reg,0b00000111
rjmp wigger0
;************************************************* *****
; Uhrzeit gültig, wenn die neue Minute 1 größer als die
; alte ist, oder 59 kleiner bei Stundenwechsel
;Minuten und Stunden werden nur überschrieben, wenn
;korrekte Minutenfolge erkannt wurde
ldi r30,113
ld tmp,Z ;min neu
ldi r30,114
ld tmp2,Z;min alt
ldi r30,114
st Z,tmp ;neu wird zu alt für den folgenden Vergleich
cp tmp2,tmp
breq fehler
brsh min_uberlauf
sub tmp,tmp2
cpi tmp,1
brne fehler
rjmp sig_erfasst
min_uberlauf:
sub tmp2,tmp ; alt - neu
cpi tmp2,59
brne fehler
sig_erfasst:
;************************************************* *****
ldi r30,102
ld tmp2,Z
ldi r30,113
ld tmp,Z
;*************************
;überschreiben der Minute
ldi r30,102
mov tmp2,tmp
st Z,tmp2
;*************************
;*************************
;überschreiben der Stunde
ldi r30,115
ld tmp,Z
ldi r30,103
st Z,tmp
;*************************
fehler:
wigger0:
out SREG,sreg_save
reti
timer1_int:
in sreg_save,SREG
sbrs status_reg,0b00000101
rjmp ignore
;****************************
; setzt Bit 0 in status_reg, wenn Signal da (PINB_0 HIGH) ist
; setzte Bit 3 in status_reg auf rising edge
sbis PINB,0
rjmp kein_signal_an_pinb0
sbrs status_reg,0b00000000
ori status_reg,0b00001000
ori status_reg,0b00000001
rjmp signal_da
kein_signal_an_pinb0:
andi status_reg,0b11111110
signal_da:
;**************************
;***************************
; ausführen wenn kein Signal
; hier wird die Zeit zwischen zwei Highpegeln gemessen,
; um die lange Pause zu erfassen
sbrc status_reg,0b00000000
rjmp warten_auf_pause
; wenn Bit 0 nin status_reg = 0, dann kein Signal
inc pw_lang
cpi pw_lang,120
brlo warten_auf_pause
ldi r22,0
ldi pw_lang,0
sbrc status_reg,0b00000001
rjmp zweite_lange_Pause
ori status_reg,0b00000010
rjmp warten_auf_pause
zweite_lange_Pause:
ori status_reg,0b00000100
rjmp war_keins_da
warten_auf_pause:
war_keins_da:
;***************************
;***************************
;ausführen, wenn zu ISR Anfang Signal HIGH war und
;lange Pause da war (Einloggen auf Sequenzanfang)
sbrs status_reg,0b00000000
rjmp warten_auf_signal
sbrs status_reg,0b00000001
rjmp warten_auf_signal
inc pw_kurz
ldi pw_lang,0;sonst würden sich die kleinen Pausen aufsummieren
warten_auf_signal:
sbrc status_reg,0b00000000
ldi pw_lang,0
sbrs status_reg,0b00000011
rjmp fix
ldi r30,dcf_BIT_counter
ld tmp,Z
inc tmp
st Z,tmp
andi status_reg,0b11110111
fix:
ignore:
ldi r30,101
ld tmp,Z
cpi tmp,10
brlo wait_for_sig
sbic PINB,0
sbr status_reg,0b00100000;
wait_for_sig:
;****************** Zählen der ms RAM 100
ldi r30,100
ld tmp,Z
inc tmp
st Z,tmp
cpi tmp,100
brlo mehr
ldi tmp,0
st Z+,tmp
;******************
;****************** Zählen der sec RAM 101
ld tmp,Z
inc tmp
st Z,tmp
cpi tmp,60
brlo mehr
ldi tmp,0
st Z,tmp
inc r30
;******************
;****************** Zählen der min RAM 102
ld tmp,Z
inc tmp
out portd,tmp
st Z,tmp
cpi tmp,60
brlo mehr
ldi tmp,0
st Z,tmp
inc r30
;******************
;****************** Zählen der Stunde RAM 103
ld tmp,Z
inc tmp
st Z,tmp
cpi tmp,25
ldi tmp,0
st Z,tmp
;******************
mehr:
ldi r30,100
out SREG,sreg_save
reti
mfg,
The Man