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