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
|