1 | .include "m8def.inc"
|
2 |
|
3 | .def temp1 = r16
|
4 | .def temp2 = r17
|
5 | .def temp3 = r18
|
6 | .def flag = r19
|
7 |
|
8 | .def SubCount = r21
|
9 | .def Sekunden = r22
|
10 | .def Minuten = r23
|
11 | .def Stunden = r24
|
12 |
|
13 | .org 0x0000
|
14 | rjmp main ; Reset Handler
|
15 | .org OVF0addr
|
16 | rjmp timer0_overflow ; Timer Overflow Handler
|
17 |
|
18 | .include "f:\lcd-routines.asm"
|
19 |
|
20 | main:
|
21 | ldi temp1, HIGH(RAMEND)
|
22 | out SPH, temp1
|
23 | ldi temp1, LOW(RAMEND) ; Stackpointer initialisieren
|
24 | out SPL, temp1
|
25 |
|
26 | rcall lcd_init
|
27 | rcall lcd_clear
|
28 |
|
29 |
|
30 | ldi temp1, (1<<CS02) | (1<<CS00) ; Teiler 1024
|
31 | out TCCR0, temp1
|
32 |
|
33 | ldi temp1, 1<<TOIE0 ; TOIE0: Interrupt bei Timer Overflow
|
34 | out TIMSK, temp1
|
35 |
|
36 | clr Minuten ; Die Uhr auf 0 setzen
|
37 | clr Sekunden
|
38 | clr Stunden
|
39 | clr SubCount
|
40 | clr Flag ; Merker löschen
|
41 |
|
42 | sei
|
43 |
|
44 | loop:
|
45 | cpi flag,0
|
46 | breq loop ; Flag im Interrupt gesetzt?
|
47 | ldi flag,0 ; flag löschen
|
48 |
|
49 | rcall lcd_clear ; das LCD löschen
|
50 | mov temp1, Stunden ; und die Stunden ausgeben
|
51 | rcall lcd_number
|
52 | ldi temp1, ':' ; zwischen Stunden und Minuten einen ':'
|
53 | rcall lcd_data
|
54 | mov temp1, Minuten ; dann die Minuten ausgeben
|
55 | rcall lcd_number
|
56 | ldi temp1, ':' ; und noch ein ':'
|
57 | rcall lcd_data
|
58 | mov temp1, Sekunden ; und die Sekunden
|
59 | rcall lcd_number
|
60 |
|
61 | rjmp loop
|
62 |
|
63 | timer0_overflow: ; Timer 0 Overflow Handler
|
64 |
|
65 | push temp1 ; temp 1 sichern
|
66 | in temp1,sreg ; SREG sichern
|
67 | push temp1
|
68 |
|
69 | inc SubCount ; Wenn dies nicht der 15. Interrupt
|
70 | cpi SubCount, 15 ; ist, dann passiert gar nichts
|
71 | brne end_isr
|
72 |
|
73 | ; Überlauf
|
74 | clr SubCount ; SubCount rücksetzen
|
75 | inc Sekunden ; plus 1 Sekunde
|
76 | cpi Sekunden, 60 ; sind 60 Sekunden vergangen?
|
77 | brne Ausgabe ; wenn nicht kann die Ausgabe schon
|
78 | ; gemacht werden
|
79 |
|
80 | ; Überlauf
|
81 | clr Sekunden ; Sekunden wieder auf 0 und dafür
|
82 | inc Minuten ; plus 1 Minute
|
83 | cpi Minuten, 60 ; sind 60 Minuten vergangen ?
|
84 | brne Ausgabe ; wenn nicht, -> Ausgabe
|
85 |
|
86 | ; Überlauf
|
87 | clr Minuten ; Minuten zurücksetzen und dafür
|
88 | inc Stunden ; plus 1 Stunde
|
89 | cpi Stunden, 24 ; nach 24 Stunden, die Stundenanzeige
|
90 | brne Ausgabe ; wieder zurücksetzen
|
91 |
|
92 | ; Überlauf
|
93 | clr Stunden ; Stunden rücksetzen
|
94 |
|
95 | Ausgabe:
|
96 | ldi flag,1 ; Flag setzen, LCD updaten
|
97 |
|
98 | end_isr:
|
99 |
|
100 | pop temp1
|
101 | out sreg,temp1 ; sreg wieder herstellen
|
102 | pop temp1
|
103 | reti ; das wars. Interrupt ist fertig
|
104 |
|
105 | ; Eine Zahl aus dem Register temp1 ausgeben
|
106 |
|
107 | lcd_number:
|
108 | push temp2 ; register sichern,
|
109 | ; wird für Zwsichenergebnisse gebraucht
|
110 | ldi temp2, '0'
|
111 | lcd_number_10:
|
112 | subi temp1, 10 ; abzählen wieviele Zehner in
|
113 | brcs lcd_number_1 ; der Zahl enthalten sind
|
114 | inc temp2
|
115 | rjmp lcd_number_10
|
116 | lcd_number_1:
|
117 | push temp1 ; den Rest sichern (http://www.mikrocontroller.net/topic/172026)
|
118 | mov temp1,temp2 ;
|
119 | rcall lcd_data ; die Zehnerstelle ausgeben
|
120 | pop temp1 ; den Rest wiederherstellen
|
121 | subi temp1, -10 ; 10 wieder dazuzählen, da die
|
122 | ; vorhergehende Schleife 10 zuviel
|
123 | ; abgezogen hat
|
124 | ; das Subtrahieren von -10
|
125 | ; = Addition von +10 ist ein Trick
|
126 | ; da kein addi Befehl existiert
|
127 | ldi temp2, '0' ; die übrig gebliebenen Einer
|
128 | add temp1, temp2 ; noch ausgeben
|
129 | rcall lcd_data
|
130 |
|
131 | pop temp2 ; Register wieder herstellen
|
132 | ret
|