1 | ;Demoprogramm für 8-fach-PWM mit Tastensteuerung Up-Down.
|
2 |
|
3 | ;8 LEDs gegen Vcc an PortB (STK500)
|
4 | ;8 entprellte Tasten gegen GND für die einzelnen PWM-Kanäle an PortD
|
5 | ;1 "Shift-Taste" an PA6 gegen GND zum Wählen der Stellrichtung der Kanaltasten.
|
6 | ;Shift offen -> Kanaltasten zählen hoch,
|
7 | ;Shift betätigt -> Kanaltasten zählen runter.
|
8 | ;Der Zählumfang wird nach oben und unten begrenzt.
|
9 |
|
10 | .include "m8515def.inc"
|
11 |
|
12 | .equ clock = 8000000 ;Taktfrequenz
|
13 |
|
14 | .equ pwu = 99 ;PWM-Zählumfang
|
15 | .equ timerwert = -100 ;Timer-Startwert (Reload)
|
16 | .equ step=6 ;Schrittweite für Änderung pro Tastendruck
|
17 | .equ lep=portb ;Port für LEDs
|
18 | .equ tap=pinc ;Tastenport
|
19 | .equ ship=pind ;Port für Shift-Taste
|
20 | .equ shib=6 ;Bit für Shift-Taste
|
21 |
|
22 | .equ avt0=80 ;Startwert Anzeige-Vorteiler
|
23 |
|
24 |
|
25 | .def soll0 = r0 ;Sollwert Kanal 1
|
26 | .def soll1 = r1 ;Sollwert Kanal 2
|
27 | .def soll2 = r2 ;Sollwert Kanal 3
|
28 | .def soll3 = r3 ;Sollwert Kanal 4
|
29 | .def soll4 = r4 ;Sollwert Kanal 5
|
30 | .def soll5 = r5 ;Sollwert Kanal 6
|
31 | .def soll6 = r6 ;Sollwert Kanal 7
|
32 | .def soll7 = r7 ;Sollwert Kanal 8
|
33 | .def tsw = r8 ;Timer-Startwert
|
34 | .def sregtemp = r9 ;Sicherheitskopie SREG
|
35 | .def scan=r10 ;Scannwert Tastenport
|
36 | .def tz0=r11 ;Tasten-Prellzähler Bit0
|
37 | .def tz1=r12 ;Tasten-Prellzähler Bit1
|
38 | .def tas=r13 ;Tastenstatus (gültig)
|
39 | .def null=r14 ;immer 0
|
40 |
|
41 | .def temp = r16
|
42 | .def tfl=r17 ;Flags für Tasten, die gedrückt wurden
|
43 | .def pwz = r18 ;PWM-Zähler
|
44 | .def task=r19 ;Taskscheibe für diverse Aufgaben
|
45 | .def ri=r20 ;Richtung der Änderung
|
46 | .def max=r21 ;Maximum
|
47 | .def avt=r22 ;Anzeige-Vorteiler
|
48 | .def flags=r23 ;Steuerflags
|
49 | .equ aktuLCD=7 ;LCD aktualisieren
|
50 | .equ sri=6 ;Sweep-Richtung
|
51 | .def wl=r24 ;Working L
|
52 | .def wh=r25 ;Working H
|
53 |
|
54 |
|
55 | .cseg
|
56 | .org 0 ;Reset- und Interrupt-Vektoren AT-Mega 8515
|
57 | rjmp RESET ;Reset Handler
|
58 | rjmp nix;EXT_INT0 ;IRQ0 Handler
|
59 | rjmp nix;EXT_INT1 ;IRQ1 Handler
|
60 | rjmp nix;TIM1_CAPT ;Timer1 Capture Handler
|
61 | rjmp nix;TIM1_COMPA ;Timer1 Compare A Handler
|
62 | rjmp nix;TIM1_COMPB ;Timer1 Compare B Handler
|
63 | rjmp nix;TIM1_OVF ;Timer1 Overflow Handler
|
64 | rjmp TIM0_OVF ;Timer0 Overflow Handler
|
65 | rjmp nix;SPI_STC ;SPI Transfer Complete Handler
|
66 | rjmp nix;USART_RXC ;USART RX Complete Handler
|
67 | rjmp nix;USART_UDRE ;UDR0 Empty Handler
|
68 | rjmp nix;USART_TXC ;USART TX Complete Handler
|
69 | rjmp nix;ANA_COMP ;Analog Comparator Handler
|
70 | rjmp nix;EXT_INT2 ;IRQ2 Handler
|
71 | rjmp nix;TIM0_COMP ;Timer0 Compare Handler
|
72 | rjmp nix;EE_RDY ;EEPROM Ready Handler
|
73 | rjmp nix;SPM_RDY ;Store Program memory Ready Handler
|
74 | nix: ;unbenutzte Interrupts
|
75 | reti ;zurück...
|
76 |
|
77 | .include"LCDprint.inc" ;LCD-Ausgabefunktionen
|
78 | .include"LCD_2x16.inc" ;LCD-Routinen für 2-Zeilen-LCDs mit HD44780
|
79 |
|
80 | Reset:
|
81 |
|
82 | ldi wl,low(ramend) ;Stackpointer initialisieren
|
83 | out SPL,wl
|
84 | ldi wl,high(ramend)
|
85 | out SPH,wl
|
86 |
|
87 | clr null ;immer 0
|
88 |
|
89 | ldi wl, 0xFF ;Port A = Ausgang
|
90 | out DDRA, wl
|
91 |
|
92 | ldi temp, 0xff
|
93 | out lep-1,temp ;Ports B = Ausgang (DDRx=PORTx-1)
|
94 |
|
95 | ;out lep,temp ;LED aus
|
96 |
|
97 | out tap+2,temp ;Pull-Ups für Tasten einschalten (PORTx=PINx+2)
|
98 | ldi temp, 0x00
|
99 | out tap+1,temp ;Ports d = Eingang (DDRx=PINx+1)
|
100 |
|
101 | cbi ship+1,shib ;Shift-Tastenanschluss als Eingang
|
102 | sbi ship+2,shib ;Shift-PullUp einschalten
|
103 |
|
104 |
|
105 |
|
106 |
|
107 | clr soll0
|
108 | clr soll1
|
109 | clr soll2
|
110 | clr soll3
|
111 | clr soll4
|
112 | clr soll5
|
113 | clr soll6
|
114 | clr soll7
|
115 | clr tz0 ;Definierte Startbedingung
|
116 | clr tz1 ;für Tastenentprellung
|
117 | clr tas
|
118 | clr tfl
|
119 |
|
120 |
|
121 | ldi temp, 0x01
|
122 | out tccr0, temp ;Timertakt = 1:1
|
123 | ldi temp, 1<<toie0
|
124 | out timsk, temp ;Timer OVF freigeben
|
125 | ldi temp,timerwert+12 ;Timer-Startwert, korregiert mit Int-Aufruf12
|
126 | mov tsw,temp ;definieren
|
127 | out tcnt0,tsw ;und ausgeben
|
128 |
|
129 | ldi temp, 0; 50
|
130 | mov soll0, temp ;Naja, wenn es sein muss...
|
131 | ldi temp,1<<se ;Sleep-Mode (idle)
|
132 | out mcucr,temp ;freischalten
|
133 | ldi max,pwu ;Max-Wert für Begrenzung der Änderung
|
134 |
|
135 | rcall lcd_init ;LCD initialisieren
|
136 |
|
137 | sei
|
138 |
|
139 | ldi flags,1<<aktuLCD ;erstes Schreiben des LCDs anmelden
|
140 | ldi avt,avt0 ;Anzeige-Vorteiler auf Startwert setzen
|
141 |
|
142 |
|
143 | Haupt: ;Hauptschleife, Auswertung der Tastenflags
|
144 | ;und Jobflags die in der ISR gesetzt wurden und verändern
|
145 | ;der PWM-Werte der 8 Kanäle.
|
146 | sleep ;Schlafmodus, Wecken erfolgt durch Timer-Int.
|
147 |
|
148 | sbrc flags,aktuLCD ;muss LCD aktualisiert werden? - nein...
|
149 | rcall gibaus ;ja, Job aufrufen...
|
150 |
|
151 | tst tfl ;Ein Bit im Tastenflag gesetzt?
|
152 | breq haupt ;nein, keine Taste gedrückt gewesen... (schlafen gehen...)
|
153 | ldi ri,step ;ja, erstmal aufwärts zählen
|
154 | sbis ship,shib ;Shift-Taste gedrückt? (nein...)
|
155 | rjmp minus ;ja, zum Abwärtszählen...
|
156 | taste0:
|
157 |
|
158 | sbrs tfl,0 ;Taste 0?
|
159 | rjmp taste1 ;nein...
|
160 | add soll0,ri ;ja, ändern
|
161 |
|
162 |
|
163 | cp soll0,max ;Maxwert überschritten?
|
164 | brlo taste1 ;nein...
|
165 | mov soll0,max ;ja, auf Maxwert begrenzen
|
166 |
|
167 |
|
168 | taste1:
|
169 | sbrs tfl,1 ;Taste 1?
|
170 | rjmp taste2 ;nein...
|
171 | add soll1,ri ;ja, ändern
|
172 |
|
173 |
|
174 | cp soll1,max ;Maxwert überschritten?
|
175 | brlo taste2 ;nein...
|
176 | mov soll1,max ;ja, auf Maxwert begrenzen
|
177 | taste2:
|
178 | sbrs tfl,2 ;Taste 2?
|
179 | rjmp taste3 ;nein...
|
180 | add soll2,ri ;ja, ändern
|
181 | cp soll2,max ;Maxwert überschritten?
|
182 | brlo taste3 ;nein...
|
183 | mov soll2,max ;ja, auf Maxwert begrenzen
|
184 | taste3:
|
185 | sbrs tfl,3 ;Taste 3?
|
186 | rjmp taste4 ;nein...
|
187 | add soll3,ri ;ja, ändern
|
188 |
|
189 |
|
190 | cp soll3,max ;Maxwert überschritten?
|
191 | brlo taste4 ;nein...
|
192 | mov soll3,max ;ja, auf Maxwert begrenzen
|
193 | taste4:
|
194 | sbrs tfl,4 ;Taste 4?
|
195 | rjmp taste5 ;nein...
|
196 | add soll4,ri ;ja, ändern
|
197 |
|
198 |
|
199 | cp soll4,max ;Maxwert überschritten?
|
200 | brlo taste5 ;nein...
|
201 | mov soll4,max ;ja, auf Maxwert begrenzen
|
202 | taste5:
|
203 | sbrs tfl,5 ;Taste 5?
|
204 | rjmp taste6 ;nein...
|
205 | add soll5,ri ;ja, ändern,
|
206 | cp soll5,max ;Maxwert überschritten?
|
207 | brlo taste6 ;nein...
|
208 | mov soll5,max ;ja, auf Maxwert begrenzen
|
209 | taste6:
|
210 | sbrs tfl,6 ;Taste 6?
|
211 | rjmp taste7 ;nein...
|
212 | add soll6,ri ;ja, ändern
|
213 | cp soll6,max ;Maxwert überschritten?
|
214 | brlo taste7 ;nein...
|
215 | mov soll6,max ;ja, auf Maxwert begrenzen
|
216 | taste7:
|
217 | sbrs tfl,7 ;Taste 7?
|
218 | rjmp taste8 ;nein...
|
219 | add soll7,ri ;ja, ändern
|
220 | cp soll7,max ;Maxwert überschritten?
|
221 | brlo taste8 ;nein...
|
222 | mov soll7,max ;ja, auf Maxwert begrenzen
|
223 | taste8:
|
224 | clr tfl ;alle Tastenflags löschen
|
225 | rjmp haupt ;fertig, schlafen gehen...
|
226 | minus:
|
227 | sbrs tfl,0 ;Taste 0?
|
228 | rjmp minus1 ;nein...
|
229 | sub soll0,ri ;ja, ändern
|
230 | brcc minus1 ;Unterlauf ? (nein...)
|
231 | clr soll0 ;ja, auf 0 setzen
|
232 | minus1:
|
233 | sbrs tfl,1 ;Taste 1?
|
234 | rjmp minus2 ;nein...
|
235 | sub soll1,ri ;ja, ändern
|
236 | brcc minus2 ;Unterlauf ? (nein...)
|
237 | clr soll1 ;ja, auf 0 setzen
|
238 | minus2:
|
239 | sbrs tfl,2 ;Taste 2?
|
240 | rjmp minus3 ;nein...
|
241 | sub soll2,ri ;ja, ändern
|
242 | brcc minus3 ;Unterlauf ? (nein...)
|
243 | clr soll2 ;ja, auf 0 setzen
|
244 | minus3:
|
245 | sbrs tfl,3 ;Taste 3?
|
246 | rjmp minus4 ;nein...
|
247 | sub soll3,ri ;ja, ändern
|
248 | brcc minus4 ;Unterlauf ? (nein...)
|
249 | clr soll3 ;ja, auf 0 setzen
|
250 | minus4:
|
251 | sbrs tfl,4 ;Taste 4?
|
252 | rjmp minus5 ;nein...
|
253 | sub soll4,ri ;ja, ändern
|
254 | brcc minus5 ;Unterlauf ? (nein...)
|
255 | clr soll4 ;ja, auf 0 setzen
|
256 | minus5:
|
257 | sbrs tfl,5 ;Taste 5?
|
258 | rjmp minus6 ;nein...
|
259 | sub soll5,ri ;ja, ändern
|
260 | brcc minus6 ;Unterlauf ? (nein...)
|
261 | clr soll5 ;ja, auf 0 setzen
|
262 | minus6:
|
263 | sbrs tfl,6 ;Taste 6?
|
264 | rjmp minus7 ;nein...
|
265 | sub soll6,ri ;ja, ändern
|
266 | brcc minus7 ;Unterlauf ? (nein...)
|
267 | clr soll6 ;ja, auf 0 setzen
|
268 | minus7:
|
269 | sbrs tfl,7 ;Taste 7?
|
270 | rjmp minus8 ;nein...
|
271 | sub soll7,ri ;ja, ändern
|
272 |
|
273 |
|
274 |
|
275 |
|
276 |
|
277 |
|
278 |
|
279 | brcc minus8 ;Unterlauf ? (nein...)
|
280 | clr soll7 ;ja, auf 0 setzen
|
281 | minus8:
|
282 | clr tfl ;alle Tastenflags löschen
|
283 | rjmp haupt ;Hauptprogramm Endlosschleife
|
284 |
|
285 |
|
286 | gibaus: ;Unterprogramm zum Ausgeben der Werte
|
287 | cbr flags,1<<aktuLCD ;Jobflag löschen, wird ja jetzt erledigt
|
288 | locate 0,0 ;erste Position der ersten Zeile
|
289 | print8 r0 ;1. Wert
|
290 | print '%' ;Prozent-Zeichen
|
291 | print ' ' ;Leerzeichen
|
292 | print8 r1 ;2. Wert
|
293 | print '%' ;Prozent-Zeichen
|
294 | print ' ' ;Leerzeichen
|
295 | print8 r2 ;3. Wert
|
296 | print '%' ;Prozent-Zeichen
|
297 | print ' ' ;Leerzeichen
|
298 | print8 r3 ;4. Wert
|
299 | print '%' ;Prozent-Zeichen
|
300 | print ' ' ;Leerzeichen
|
301 | locate 1,0 ;erste Position der zweiten Zeile
|
302 | print8 r4 ;5. Wert
|
303 | print '%' ;Prozent-Zeichen
|
304 | print ' ' ;Leerzeichen
|
305 | print8 r5 ;6. Wert
|
306 | print '%' ;Prozent-Zeichen
|
307 | print ' ' ;Leerzeichen
|
308 | print8 r6 ;7. Wert
|
309 | print '%' ;Prozent-Zeichen
|
310 | print ' ' ;Leerzeichen
|
311 | print8 r7 ;8. Wert
|
312 | print '%' ;Prozent-Zeichen
|
313 | print ' ' ;Leerzeichen
|
314 | ;Sweep auf Kanal 7 zur Demonstration einer Automatik
|
315 | sbrs flags,sri ;Sweep-Richtung 'hoch'? - nein...
|
316 | inc soll7 ;ja, Sollwert erhöhen
|
317 | sbrc flags,sri ;Sweep-Richtung 'runter'? - nein...
|
318 | dec soll7 ;ja, Sollwert vermindern
|
319 | brne gibaus1 ;Null erreicht? - nein...
|
320 | cbr flags,1<<sri ;ja, Sweep-Richtung auf 'hoch' schalten
|
321 |
|
322 | gibaus1:
|
323 | mov wh,soll7 ;Kopie in oberes Register wegen CPI
|
324 | cpi wh,pwu ;PWM-Zählumfang erreicht?
|
325 | brne gibaus_e ;nein...
|
326 | sbr flags,1<<sri ;ja, Sweep-Richtung 'runter' schalten
|
327 |
|
328 | gibaus_e:
|
329 | ret ;fertig...
|
330 |
|
331 |
|
332 | Tim0_OVF: ;ISR Timer0-Überlauf
|
333 | in sregtemp, sreg ;Sreg sichern
|
334 | out tcnt0,tsw ;Timer auf Startwert setzen
|
335 | inc pwz ;PWM-Treppenzähler erhöhen
|
336 | cpi pwz, pwu ;PWM-Zählumfang erreicht?
|
337 | brne Time0_a ;nein... (die 3 Punkte bedeuten bei mir Sprung)
|
338 | clr pwz ;von vorn beginnen mit zählen
|
339 | Time0_a: ;Vergleich der einzelnen PWM-Werte mit dem PWM-Treppenzähler
|
340 | ;(Idee geklaut bei Peter Dannegger)
|
341 | cp pwz, soll7 ;Sollwert erreicht? (Ergebnis im Carry)
|
342 | rol temp ;Carry-Bits "einsammeln", dieses wird bis Bit7 durchgeschoben
|
343 | cp pwz, soll6
|
344 | rol temp ;Bit 6
|
345 | cp pwz, soll5
|
346 | rol temp ;Bit 5
|
347 | cp pwz, soll4
|
348 | rol temp ;Bit 4
|
349 | cp pwz, soll3
|
350 | rol temp ;Bit 3
|
351 | cp pwz, soll2
|
352 | rol temp ;Bit 2
|
353 | cp pwz, soll1
|
354 | rol temp ;Bit 1
|
355 | cp pwz, soll0
|
356 | rol temp ;Bit 0
|
357 | com temp ;invertieren da low-aktive LED im STK500
|
358 | out portB, temp ;Ausgabe
|
359 | inc task ;Taskscheibe erhöhen (Tastenabfrage erfolgt nur bei Task Nr. 0)
|
360 | ;andere Aufgaben können bei anderen Zählerständen aufgerufen werden
|
361 | ;dabei ist darauf zu achten, dass kein Durchlauf der ISR mehr als
|
362 | ;70 Takte dauert, da die ISR alle 100 Takte aufgerufen wird und
|
363 | ;der Aufruf (mit Reti) schon 10 Takte braucht.
|
364 | brne timertasks ;nur bei 0 Tasten abfragen...
|
365 | Tastenabfrage: ;Entprellroutine (geklaut bei Peter Dannegger...)
|
366 | in scan,tap ;Tastenport einlesen (gedrückt=L)
|
367 | com scan ;invertieren (gedrückt=H)
|
368 | eor scan,tas ;nur Änderungen werden H
|
369 | and tz0,scan ;Prellzähler unveränderter Tasten löschen (Bit0)
|
370 | and tz1,scan ;Prellzähler unveränderter Tasten löschen (Bit1)
|
371 | com tz0 ;L-Bit zählen 0,2,->1, 1,3,->0
|
372 | eor tz1,tz0 ;H-Bit zählen 0,2,->tz1 toggeln
|
373 | and scan,tz0 ;Änderungen nur dann erhalten, wenn im Prellzähler
|
374 | and scan,tz1 ;beide Bits gesetzt sind (Zählerstand 3)
|
375 | eor tas,scan ;erhaltene Änderungen toggeln alten (gültigen) Tastenstatus
|
376 | and scan,tas ;nur (neu) gedrückte Tastenbits bleiben erhalten
|
377 | or tfl,scan ;und zugehörige Bits setzen (gelöscht wird nach Abarbeitung)
|
378 | ;in "tas" steht jetzt der gültige Tastenzustand,
|
379 | ;in "tfl" die Flags der neu gedrückten, noch nicht abgearbeiteten Tasten...
|
380 | timertasks:
|
381 | cpi task,2 ;Beispiel für Verzweigung nach Taskscheibe
|
382 | brne timerfertig ;bei falscher Tasknummer Überspringen...
|
383 | dec avt ;Anzeige-Vorteiler runter
|
384 | brne timerfertig ;unten? nein, weg hier...
|
385 | ldi avt,avt0 ;ja, Startwert laden
|
386 | sbr flags,1<<aktuLCD ;Flag setzen, um LCD zu aktualisieren
|
387 |
|
388 | timerfertig:
|
389 | out sreg, sregtemp ;Sreg wiederherstellen
|
390 | reti ;ISR fertig
|