main.asm


1
;
2
; Schaltuhr.asm
3
;
4
; Created: 11.03.2017 08:23:35
5
; Author : BERND
6
;
7
.include "m8def.inc"
8
 
9
.def temp1 = r16
10
.def temp2 = r17
11
.def temp3 = r18
12
.def Flag  = r19
13
.def Counter = r20
14
.def SubCount = r21
15
.def Sekunden = r22
16
.def Minuten  = r23
17
.def Stunden  = r24
18
19
.org 0x0000
20
           rjmp    main             ; Reset Handler
21
.org OC1Aaddr
22
           rjmp    timer1_compare   ; Timer Compare Handler
23
24
.include "LCD-Routine.asm"
25
26
main:  ldi  temp1,0xFF
27
    out  DDRB,temp1
28
29
        ldi     temp1, HIGH(RAMEND)
30
        out     SPH, temp1
31
        ldi     temp1, LOW(RAMEND)  ; Stackpointer initialisieren
32
        out     SPL, temp1
33
34
        ldi temp1, 0xFF    ; Port D = Ausgang
35
        out DDRD, temp1     
36
37
        rcall   lcd_init
38
        rcall   lcd_clear
39
 
40
                                    ; Vergleichswert 
41
        ldi     temp1, high( 40000 - 1 )
42
        out     OCR1AH, temp1
43
        ldi     temp1, low( 40000 - 1 )
44
        out     OCR1AL, temp1
45
                                    ; CTC Modus einschalten
46
                                    ; Vorteiler auf 1
47
        ldi     temp1, ( 1 << WGM12 ) | ( 1 << CS10 )
48
        out     TCCR1B, temp1
49
 
50
        ldi     temp1, 1 << OCIE1A  ; OCIE1A: Interrupt bei Timer Compare
51
        out     TIMSK, temp1
52
 
53
        clr     Minuten             ; Die Uhr auf 0 setzen
54
        clr     Sekunden
55
        clr     Stunden
56
        clr     SubCount
57
        clr     Flag                ; Flag löschen
58
59
        sei
60
loop:
61
        cpi     flag,0
62
        breq    loop                ; Flag im Interrupt gesetzt?
63
        ldi     flag,0              ; Flag löschen
64
  
65
        rcall   lcd_clear           ; das LCD löschen
66
        mov     temp1, Stunden      ; und die Stunden ausgeben
67
        rcall   lcd_number
68
        ldi     temp1, ':'          ; zwischen Stunden und Minuten einen ':'
69
        rcall   lcd_data
70
        mov     temp1, Minuten      ; dann die Minuten ausgeben
71
        rcall   lcd_number
72
        ldi     temp1, ':'          ; und noch ein ':'
73
        rcall   lcd_data
74
        mov     temp1, Sekunden     ; und die Sekunden
75
        rcall   lcd_number
76
77
        rjmp    loop
78
 
79
timer1_compare:                     ; Timer 1 Output Compare Handler
80
81
        push    temp1               ; temp 1 sichern
82
        in      temp1,sreg          ; SREG sichern
83
84
        inc     SubCount            ; Wenn dies nicht der 100. Interrupt
85
        cpi     SubCount, 100    ; ist, dann passiert gar nichts
86
        brne    end_isr
87
                                    ; Überlauf
88
        clr     SubCount            ; SubCount rücksetzen
89
        inc     Sekunden            ; plus 1 Sekunde
90
        cpi     Sekunden, 60        ; sind 60 Sekunden vergangen?
91
        brne    Ausgabe        ; wenn nicht kann die Ausgabe schon    ; gemacht werden      
92
    
93
                                   ; Überlauf
94
    
95
    clr     Sekunden            ; Sekunden wieder auf 0 und dafür
96
        inc     Minuten            ; plus 1 Minute
97
    cpi    Minuten,1
98
    breq  Kanal1ein
99
    cpi    Minuten,2
100
    breq  Kanal1aus
101
weiter: cpi     Minuten, 60         ; sind 60 Minuten vergangen ?
102
        brne    Ausgabe             ; wenn nicht, -> Ausgabe
103
    
104
                                    ; Überlauf
105
    
106
        clr     Minuten             ; Minuten zurücksetzen und dafür
107
        inc     Stunden             ; plus 1 Stunde
108
        cpi     Stunden, 24         ; nach 24 Stunden, die Stundenanzeige
109
        brne    Ausgabe             ; wieder zurücksetzen
110
111
                                    ; Überlauf
112
        clr     Stunden             ; Stunden rücksetzen
113
114
Ausgabe:
115
        ldi     flag,1              ; Flag setzen, LCD updaten
116
117
118
end_isr:
119
120
        out     sreg,temp1          ; sreg wieder herstellen
121
        pop     temp1
122
        reti                        ; das wars. Interrupt ist fertig
123
124
; Eine Zahl aus dem Register temp1 ausgeben
125
126
lcd_number:
127
        push    temp2               ; register sichern,
128
                                    ; wird für Zwsichenergebnisse gebraucht     
129
        ldi     temp2, '0'         
130
lcd_number_10:                
131
        subi    temp1, 10           ; abzählen wieviele Zehner in
132
        brcs    lcd_number_1        ; der Zahl enthalten sind
133
        inc     temp2
134
        rjmp    lcd_number_10
135
lcd_number_1:
136
        push    temp1               ; den Rest sichern (http://www.mikrocontroller.net/topic/172026)
137
        mov     temp1,temp2         ; 
138
        rcall   lcd_data            ; die Zehnerstelle ausgeben
139
        pop     temp1               ; den Rest wieder holen
140
        subi    temp1, -10          ; 10 wieder dazuzählen, da die
141
                                    ; vorhergehende Schleife 10 zuviel
142
                                    ; abgezogen hat
143
                                    ; das Subtrahieren von -10
144
                                    ; = Addition von +10 ist ein Trick
145
                                    ; da kein addi Befehl existiert
146
        ldi     temp2, '0'          ; die übrig gebliebenen Einer
147
        add     temp1, temp2        ; noch ausgeben
148
        rcall   lcd_data
149
150
        pop     temp2               ; Register wieder herstellen
151
     
152
  ret  
153
    
154
Kanal1ein:
155
    cpi  Counter, 1
156
    ldi temp1, 255  ;breq LED_off
157
    Out  PORTB,temp1
158
  rjmp  weiter
159
Kanal1aus:
160
    cpi Counter, 2
161
    ldi temp1, 0
162
    Out PORTB, temp1   
163
  rjmp  weiter