8pwm1.asm


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