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 | .nolist ;List der Include-Datei unterdrücken
|
11 | .include "m8515def.inc"
|
12 | .list ;Programm listen
|
13 | .listmac ;Makros listen
|
14 | .equ clock = 8000000 ;Taktfrequenz 8Mhz
|
15 | ;.equ clock = 16000000 ;Taktfrequenz 8Mhz
|
16 |
|
17 |
|
18 |
|
19 | .equ pwu = 50 ;PWM-Zählumfang
|
20 | .equ timerwert = -100 ;Timer-Startwert (Reload)-100
|
21 | .equ step=5 ; 6 ;Schrittweite für Änderung pro Tastendruck
|
22 | .equ lep=portb ;Port für LEDs
|
23 | .equ tap=pinc ;Tastenport
|
24 | .equ ruck = 4 ;Taste zurück
|
25 | .equ dimplus = 3 ;Taste dimmen plus
|
26 | .equ dimminus = 2 ;Taste dimmen minus
|
27 | .equ chanplus = 1 ;Taste kanal hoch
|
28 | .equ chanminus = 0 ;Taste kanal runter
|
29 | .equ alltast=(1<<ruck)|(1<<dimplus)|(1<<dimminus)|(1<<chanplus)|(1<<chanminus) ;Maske aller Tasten
|
30 |
|
31 | .equ avt0=20 ;Startwert Anzeige-Vorteiler
|
32 |
|
33 |
|
34 | .def soll0 = r0 ;Sollwert Kanal 1
|
35 | .def soll1 = r1 ;Sollwert Kanal 2
|
36 | .def soll2 = r2 ;Sollwert Kanal 3
|
37 | .def soll3 = r3 ;Sollwert Kanal 4
|
38 | .def soll4 = r4 ;Sollwert Kanal 5
|
39 | .def soll5 = r5 ;Sollwert Kanal 6
|
40 | .def soll6 = r6 ;Sollwert Kanal 7
|
41 | .def soll7 = r7 ;Sollwert Kanal 8
|
42 | .def tsw = r8 ;Timer-Startwert
|
43 | .def sregtemp = r9 ;Sicherheitskopie SREG
|
44 | .def scan=r10 ;Scannwert Tastenport
|
45 | .def tz0=r11 ;Tasten-Prellzähler Bit0
|
46 | .def tz1=r12 ;Tasten-Prellzähler Bit1
|
47 | .def tas=r13 ;Tastenstatus (gültig)
|
48 | .def null=r14 ;immer 0
|
49 |
|
50 | ;********************************************
|
51 |
|
52 | ;********************************************
|
53 | .def temp = r16
|
54 | .def tfl=r17 ;Flags für Tasten, die gedrückt wurden
|
55 | .def pwz = r18 ;PWM-Zähler
|
56 |
|
57 | .def task=r19 ;Taskscheibe für diverse Aufgaben
|
58 | .def ri=r20 ;Richtung der Änderung
|
59 | .def max=r21 ;Maximum
|
60 |
|
61 |
|
62 |
|
63 |
|
64 |
|
65 | .def avt=r22 ;Anzeige-Vorteiler
|
66 | .def flags=r23 ;Steuerflags
|
67 | .equ aktuLCD=7 ;7 ;LCD aktualisieren
|
68 |
|
69 | .def wl=r24 ;Working L
|
70 | .def wh=r25 ;Working H
|
71 |
|
72 |
|
73 |
|
74 | .equ lcdcontroller1=4 ;Flag für Controller 1
|
75 | .equ lcdcontroller2=6 ;Flag für Controller 2
|
76 |
|
77 |
|
78 |
|
79 |
|
80 |
|
81 | .cseg
|
82 | ;.org 0 ;Reset- und Interrupt-Vektoren Mega 8535
|
83 | .org 0 ;Reset- und Interrupt-Vektoren AT-Mega 8515
|
84 | rjmp RESET ;Reset Handler
|
85 | rjmp nix;EXT_INT0 ;IRQ0 Handler
|
86 | rjmp nix;EXT_INT1 ;IRQ1 Handler
|
87 | rjmp nix;TIM1_CAPT ;Timer1 Capture Handler
|
88 | rjmp nix;TIM1_COMPA ;Timer1 Compare A Handler
|
89 | rjmp nix;TIM1_COMPB ;Timer1 Compare B Handler
|
90 | rjmp nix;TIM1_OVF ;Timer1 Overflow Handler
|
91 | rjmp TIM0_OVF ;Timer0 Overflow Handler
|
92 | rjmp nix;SPI_STC ;SPI Transfer Complete Handler
|
93 | rjmp nix;USART_RXC ;USART RX Complete Handler
|
94 | rjmp nix;USART_UDRE ;UDR0 Empty Handler
|
95 | rjmp nix;USART_TXC ;USART TX Complete Handler
|
96 | rjmp nix;ANA_COMP ;Analog Comparator Handler
|
97 | rjmp nix;EXT_INT2 ;IRQ2 Handler
|
98 | rjmp nix;TIM0_COMP ;Timer0 Compare Handler
|
99 | rjmp nix;EE_RDY ;EEPROM Ready Handler
|
100 | rjmp nix;SPM_RDY ;Store Program memory Ready Handler
|
101 | nix: ;unbenutzte Interrupts
|
102 | reti ;zurück...
|
103 |
|
104 |
|
105 |
|
106 |
|
107 |
|
108 |
|
109 | .include"LCDprint.inc" ;LCD-Ausgabefunktionen
|
110 | .include"LCD_4x27.inc" ;LCD-Routinen für 4-Zeilen-LCDs mit HD44780
|
111 |
|
112 |
|
113 |
|
114 |
|
115 |
|
116 |
|
117 | Reset:
|
118 |
|
119 | ldi wl,low(ramend) ;Stackpointer initialisieren
|
120 | out SPL,wl
|
121 | ldi wl,high(ramend)
|
122 | out SPH,wl
|
123 |
|
124 | clr null ;immer 0
|
125 |
|
126 | ldi wl, 0xFF ;Port A = Ausgang
|
127 | out DDRA, wl ;Display
|
128 |
|
129 | ldi temp, 0xFF ;Port E = Ausgang
|
130 | out DDRE, temp
|
131 |
|
132 |
|
133 | ldi temp, 0xff
|
134 | out lep-1,temp ;Ports B = Ausgang (DDRx=PORTx-1)
|
135 |
|
136 |
|
137 | ;out lep,temp ;LED aus
|
138 |
|
139 | ldi wl, alltast ;pull-ups
|
140 | out tap+2,wl ;für tasten einschalten
|
141 |
|
142 |
|
143 | ldi R16, 0x00 ; PORTD Eingang
|
144 | out DDRD, R16
|
145 |
|
146 | sbi portd,0 ; pullupwid.
|
147 | sbi portd,1 ; pullupwid.
|
148 |
|
149 |
|
150 | ;***********************************************
|
151 |
|
152 | ;************************************************
|
153 |
|
154 | clr soll0
|
155 | clr soll1
|
156 | clr soll2
|
157 | clr soll3
|
158 | clr soll4
|
159 | clr soll5
|
160 | clr soll6
|
161 | clr soll7
|
162 | clr tz0 ;Definierte Startbedingung
|
163 | clr tz1 ;für Tastenentprellung
|
164 | clr tas
|
165 | clr tfl
|
166 |
|
167 |
|
168 |
|
169 | ;TIMER0
|
170 | ldi temp, 0x01
|
171 | out tccr0, temp ;Timertakt = 1:1
|
172 | ldi temp, 1<<toie0
|
173 | out timsk, temp ;Timer OVF freigeben
|
174 | ldi temp,timerwert+12 ;Timer-Startwert, korregiert mit Int-Aufruf12
|
175 | mov tsw,temp ;definieren
|
176 | out tcnt0,tsw ;und ausgeben
|
177 |
|
178 |
|
179 |
|
180 | ldi temp, 0 ;50
|
181 | mov soll0, temp ;Naja, wenn es sein muss...
|
182 | ldi temp,1<<se ;Sleep-Mode (idle)
|
183 | out mcucr,temp ;freischalten
|
184 | ldi max,pwu ;Max-Wert für Begrenzung der Änderung
|
185 |
|
186 |
|
187 |
|
188 |
|
189 |
|
190 | rcall lcd_init ;LCD initialisieren
|
191 |
|
192 |
|
193 |
|
194 |
|
195 | sei ;INTERRUPST FREIGEBEN
|
196 |
|
197 |
|
198 | tastaus: ;Tasten puffer leeren und mainloop
|
199 | clr tfl ;Tastenflags löschen
|
200 | rjmp mainloop1
|
201 |
|
202 | ;Hauptschleife, Auswertung der Tastenflags
|
203 |
|
204 |
|
205 | sbrc flags,aktuLCD ;muss LCD aktualisiert werden? - nein...
|
206 |
|
207 |
|
208 | mainloop1:
|
209 |
|
210 | andi tfl,alltast ;nur benutzte Tasten prüfen
|
211 | rjmp menu ;Tastendruck auswerten...
|
212 |
|
213 |
|
214 |
|
215 | menu:
|
216 |
|
217 | M0:
|
218 | sbrC tfl,chanplus ;kanal hoch Taste? nein...
|
219 | RJMP channel1 ;ja...
|
220 |
|
221 | M1:
|
222 | sbrC tfl,chanplus ;kanal hoch Taste? nein...
|
223 | RJMP channel2 ;ja...
|
224 |
|
225 | M2:
|
226 | sbrc tfl,chanplus ;kanal hoch Taste? nein...
|
227 | RJMP channel3 ;ja...
|
228 |
|
229 | M3:
|
230 | sbrc tfl,chanplus ;kanal hoch Taste? nein...
|
231 | RJMP channel4 ;ja...
|
232 | ;cbr tfl,(1<<chanplus)
|
233 | cbr tfl,alltast ;alle Tasten sind erledigt
|
234 | rjmp tastaus
|
235 | ;***********************************************************************
|
236 |
|
237 |
|
238 | channel1:
|
239 | locate 0,0
|
240 | printf CHAN1
|
241 | CC1:
|
242 | ldi ri,step ;ja, erstmal aufwärts zählen
|
243 | sbrs tfl,dimplus ;Taste ?
|
244 | rjmp m0 ;nein...
|
245 | add soll0,ri ;ja, ändern
|
246 | cp soll0,max ;Maxwert überschritten?
|
247 | brlo FF3 ;nein...
|
248 | mov soll0,max ;ja, auf Maxwert begrenzen
|
249 | FF3:
|
250 | ;cbr tfl,(1<<dimplus)
|
251 | rjmp tastaus
|
252 |
|
253 | channel2:
|
254 | locate 0,0
|
255 | printf CHAN2
|
256 | CC2:
|
257 | ldi ri,step ;ja, erstmal aufwärts zählen
|
258 | sbrs tfl,dimplus ;Taste ?
|
259 | rjmp m1 ;nein...
|
260 | add soll1,ri ;ja, ändern
|
261 | cp soll1,max ;Maxwert überschritten?
|
262 | brlo FF4 ;nein...
|
263 | mov soll1,max ;ja, auf Maxwert begrenzen
|
264 | FF4:
|
265 | ;cbr tfl,(1<<dimplus)
|
266 | rjmp tastaus
|
267 |
|
268 |
|
269 | channel3:
|
270 | locate 0,0
|
271 | printf CHAN3
|
272 | CC3:
|
273 | ldi ri,step ;ja, erstmal aufwärts zählen
|
274 | sbrs tfl,dimplus ;Taste ?
|
275 | rjmp m2 ;nein...
|
276 | add soll2,ri ;ja, ändern
|
277 | cp soll2,max ;Maxwert überschritten?
|
278 | brlo FF5 ;nein...
|
279 | mov soll2,max ;ja, auf Maxwert begrenzen
|
280 | FF5:
|
281 | ;cbr tfl,(1<<dimplus)
|
282 | rjmp tastaus
|
283 |
|
284 | channel4:
|
285 | locate 0,0
|
286 | printf CHAN4
|
287 | CC4:
|
288 | ldi ri,step ;ja, erstmal aufwärts zählen
|
289 | sbrs tfl,dimplus ;Taste ?
|
290 | rjmp m3 ;nein...
|
291 | add soll3,ri ;ja, ändern
|
292 | cp soll3,max ;Maxwert überschritten?
|
293 | brlo FF6 ;nein...
|
294 | mov soll3,max ;ja, auf Maxwert begrenzen
|
295 | FF6:
|
296 | cbr tfl,(1<<dimplus)
|
297 | rjmp tastaus
|
298 |
|
299 |
|
300 |
|
301 |
|
302 |
|
303 |
|
304 |
|
305 |
|
306 | Tim0_OVF: ;ISR Timer0-Überlauf
|
307 | in sregtemp, sreg ;Sreg sichern
|
308 | out tcnt0,tsw ;Timer auf Startwert setzen
|
309 | inc pwz ;PWM-Treppenzähler erhöhen
|
310 | cpi pwz, pwu ;PWM-Zählumfang erreicht?
|
311 | brne Time0_a ;nein... (die 3 Punkte bedeuten bei mir Sprung)
|
312 | clr pwz ;von vorn beginnen mit zählen
|
313 | Time0_a: ;Vergleich der einzelnen PWM-Werte mit dem PWM-Treppenzähler
|
314 | ;(Idee geklaut bei Peter Dannegger)
|
315 | cp pwz, soll7 ;Sollwert erreicht? (Ergebnis im Carry)
|
316 | rol temp ;Carry-Bits "einsammeln", dieses wird bis Bit7 durchgeschoben
|
317 | cp pwz, soll6
|
318 | rol temp ;Bit 6
|
319 | cp pwz, soll5
|
320 | rol temp ;Bit 5
|
321 | cp pwz, soll4
|
322 | rol temp ;Bit 4
|
323 | cp pwz, soll3
|
324 | rol temp ;Bit 3
|
325 | cp pwz, soll2
|
326 | rol temp ;Bit 2
|
327 | cp pwz, soll1
|
328 | rol temp ;Bit 1
|
329 | cp pwz, soll0
|
330 | rol temp ;Bit 0
|
331 | ;com temp ;invertieren da low-aktive LED im STK500
|
332 | out portB, temp ;Ausgabe
|
333 | inc task ;Taskscheibe erhöhen (Tastenabfrage erfolgt nur bei Task Nr. 0)
|
334 | ;andere Aufgaben können bei anderen Zählerständen aufgerufen werden
|
335 | ;dabei ist darauf zu achten, dass kein Durchlauf der ISR mehr als
|
336 | ;70 Takte dauert, da die ISR alle 100 Takte aufgerufen wird und
|
337 | ;der Aufruf (mit Reti) schon 10 Takte braucht.
|
338 | brne timertasks ;nur bei 0 Tasten abfragen...
|
339 | Tastenabfrage: ;Entprellroutine (geklaut bei Peter Dannegger...)
|
340 |
|
341 | sbis PIND, 0 ;überspringe nächsten Befehl, falls Taster1 nicht
|
342 | rcall LEDon ;springe Unterprogramm an;
|
343 | sbis PIND, 1 ;1 ;überspringe nächsten Befehl, falls Taster1 gedrückt
|
344 | rcall LEDoff ;springe Unterprogramm aus
|
345 |
|
346 | in xl,tap ;Tastenport einlesen (gedrückt=L)
|
347 | com xl ;invertieren (gedrückt=H)
|
348 | eor xl,tas ;nur Änderungen werden H
|
349 | and tz0,xl ;Prellzähler unveränderter Tasten löschen (Bit0)
|
350 | and tz1,xl ;Prellzähler unveränderter Tasten löschen (Bit1)
|
351 | com tz0 ;L-Bit zählen 0,2,->1, 1,3,->0
|
352 | eor tz1,tz0 ;H-Bit zählen 0,2,->tz1 toggeln
|
353 | and xl,tz0 ;Änderungen nur dann erhalten, wenn im Prellzähler
|
354 | and xl,tz1 ;beide Bits gesetzt sind (Zählerstand 3)
|
355 | eor tas,xl ;erhaltene Änderungen toggeln alten (gültigen) Tastenstatus
|
356 | and xl,tas ;nur (neu) gedrückte Tastenbits bleiben erhalten
|
357 | or tfl,xl ;und zugehörige Bits setzen (gelöscht wird nach Abarbeitung)
|
358 |
|
359 |
|
360 | timertasks:
|
361 | cpi task,2 ;Beispiel für Verzweigung nach Taskscheibe
|
362 | brne timerfertig ;bei falscher Tasknummer Überspringen...
|
363 | dec avt ;Anzeige-Vorteiler runter
|
364 | brne timerfertig ;unten? nein, weg hier...
|
365 | ldi avt,avt0 ;ja, Startwert laden
|
366 | sbr flags,1<<aktuLCD ;Flag setzen, um LCD zu aktualisieren
|
367 |
|
368 |
|
369 |
|
370 |
|
371 | timerfertig:
|
372 |
|
373 |
|
374 | out sreg, sregtemp ;Sreg wiederherstellen
|
375 | reti ;ISR fertig
|
376 |
|
377 |
|
378 |
|
379 |
|
380 |
|
381 | chan1: .db "KANAL 1 ",0
|
382 | chan2: .db "KANAL 2 ",0
|
383 | chan3: .db "KANAL 3 ",0
|
384 | chan4: .db "KANAL 4 ",0
|