1 | ;****************************************************************************************
|
2 | ;* *
|
3 | ;* Testprogramm variable PWM *
|
4 | ;* *
|
5 | ;* Controller: 8515 Clock = 4 MHz *
|
6 | ;* *
|
7 | ;* *
|
8 | ;* Stand: 25.5.03 *
|
9 | ;* *
|
10 | ;* PWM Variabel,Frequenz variabel *
|
11 | ;* *
|
12 | ;* Rechenroutine zur Bestimmumg des Puls / Pausenverhältnisses aus *
|
13 | ;* gewählter Frequenz und Ansteuerung Port B über Drehimpulsgeber. *
|
14 | ;* *
|
15 | ;* do: Grenzwertberchnung *
|
16 | ;* *
|
17 | ;* *
|
18 | ;* *
|
19 | ;****************************************************************************************
|
20 |
|
21 |
|
22 | .include "C:\vmlab\include\4414def.inc"
|
23 | .list
|
24 |
|
25 |
|
26 | .def stat = r13 ;Statusregister Hauptprogramm
|
27 | .def addlo = r16 ;Hilfsregister addition Timersektion
|
28 | .def fahrt = r17 ;Register fuer Fahrtstufe
|
29 |
|
30 | .def workh = r20 ;Speicherregister Hauptprogramm
|
31 | .def workl = r21 ;Speicherregister Timersektion
|
32 |
|
33 | .def temp1 = r18 ;mehrzweck
|
34 | .def temp2 = r19 ;mehrzweck
|
35 | .def temp3 = r24 ;mehrzweck
|
36 | .def temp4 = r25 ;mehrzweck
|
37 | .def lpause = r26 ;lowbyte pause
|
38 | .def hpause = r27 ;highbyte pause
|
39 | .def lpuls = r28 ;lowbyte impuls
|
40 | .def hpuls = r29 ;highbyte impuls
|
41 |
|
42 | .def drem16ul = r14 ;remainder lowbyte
|
43 | .def drem16uh = r15 ;remainder highbyte
|
44 | .def dres16ul = r16 ;Ergebniss division lowbyte
|
45 | .def dres16uh = r17 ;Ergebniss division highbyte
|
46 | .def dd16ul = r16 ;divident lowbyte
|
47 | .def dd16uh = r17 ;divident highbyte
|
48 | .def dv16ul = r18 ;divisor lowbyte
|
49 | .def dv16uh = r19 ;divisor highbyte
|
50 |
|
51 |
|
52 | .def mc16ul = r16 ;multiplicand lowbyte
|
53 | .def mc16uh = r17 ;multiplicand highbyte
|
54 | .def mp16ul = r18 ;multiplier lowbyte
|
55 | .def mp16uh = r19 ;multiplier highbyte
|
56 | .def m16u0 = r18 ;Ergebniss byte 0 (LSB)
|
57 | .def m16u1 = r19 ;Ergebniss byte 1
|
58 | .def m16u2 = r20 ;Ergebniss byte 2
|
59 | .def m16u3 = r21 ;Ergebniss byte 3 (MSB)
|
60 |
|
61 | .def cnt = r22 ;Counter für Rechenroutinen
|
62 |
|
63 | .equ startwert= 23 ;PWM auf 95% Pausenzeit festlegen
|
64 | .equ frequenz = 6240 ;Dezimalwert für Frequenz
|
65 | .equ step = 1
|
66 |
|
67 |
|
68 | rjmp initial ;Controler initialisieren
|
69 | reti ;externer Interrupt0, noch frei
|
70 | reti
|
71 | reti ;capture Interrupt, noch frei
|
72 | rjmp timer1compa ;Timer1 Compare A Interrupt
|
73 | reti
|
74 | reti
|
75 | rjmp t1_ovfl ;Counter 0 Überlauf, Erkennung Drehimpulsgeber
|
76 | reti
|
77 | reti
|
78 | reti
|
79 | reti
|
80 | reti
|
81 |
|
82 |
|
83 | initial:
|
84 |
|
85 | ldi workh,high(ramend)
|
86 | out sph,workh
|
87 | ldi workh,low(ramend)
|
88 | out spl,workh
|
89 | ldi workh,$20 ;PD5 ist Ausgang PWM Signal, Rest ist Eingang
|
90 | out ddrd,workh
|
91 | ldi workh,$df
|
92 | out portd,workh ;Eingänge Port D Pullups aktiviert
|
93 | clr workh
|
94 | out ddrb,workh ;port b ist eingang
|
95 | ser workh
|
96 | out portb,workh ;Pullups Port b aktiviert
|
97 | out ddrc,workh ;Port C ist Ausgang
|
98 |
|
99 | ldi workh,$42
|
100 | out timsk,workh ;Timer / Counter 0 Interruptfreigabe
|
101 | ldi workh,$fe
|
102 | out tcnt0,workh ;Timerzählregister auf 255 setzen
|
103 | ldi workh,$07
|
104 | out tccr0,workh ;Timer 0 = Countermode, steigende Flanke an PB 0
|
105 |
|
106 | sei
|
107 | ;---------------------------------------------------------------------------------
|
108 | ;I Hauptprogramm I
|
109 | ;---------------------------------------------------------------------------------
|
110 |
|
111 |
|
112 | main:
|
113 |
|
114 | ;----------- 1.Berechnung prozentualer Anteil P/P - Grundwert
|
115 |
|
116 |
|
117 |
|
118 | ;1.division, Faktor errechnen und Ergebniss in r16 und r17
|
119 |
|
120 | ldi dd16ul,low(frequenz)
|
121 | ldi dd16uh,high(frequenz)
|
122 | ldi dv16ul,low(24)
|
123 | ldi dv16uh,high(24)
|
124 | rcall calc1
|
125 | sts $0065,dres16ul
|
126 | sts $0064,dres16uh
|
127 |
|
128 |
|
129 | ;2. Multiplikation, Ergebniss Pausenzeit in m16u0 - m16u3
|
130 |
|
131 | ldi mp16ul,low(startwert) ;Multiplikator lowbyte
|
132 | ldi mp16uh,high(startwert) ;Multiplikator highbyte
|
133 | rcall calc2
|
134 |
|
135 | ;3. Pulszeit errechnen, PWM starten
|
136 |
|
137 | mov lpause,m16u0 ;lowbyte Pause nach lpause schieben
|
138 | mov hpause,m16u1 ;highbyte Pause nach hpause schieben
|
139 | rcall calc3
|
140 |
|
141 | ;4. unteren Grenzwert berechnen
|
142 |
|
143 | ldi mp16ul,low(1)
|
144 | ldi mp16uh,high(1)
|
145 | rcall calc2
|
146 | sts $0066,m16u1
|
147 | sts $0067,m16u0
|
148 | rcall calc3
|
149 | sts $0068,hpuls
|
150 | sts $0069,lpuls
|
151 |
|
152 | ;5. oberen Grenzwert berechnen
|
153 |
|
154 | ldi mp16ul,low(23)
|
155 | ldi mp16uh,high(23)
|
156 | rcall calc2
|
157 | sts $006a,m16u1
|
158 | sts $006b,m16u0
|
159 | rcall calc3
|
160 | sts $006c,hpuls
|
161 | sts $006d,lpuls
|
162 |
|
163 |
|
164 | ldi workh,$01
|
165 | sts $0070,workh ;speicherstelle Fahrtstufe
|
166 |
|
167 | rcall startpwm ;Grundwerte Pause setzen
|
168 |
|
169 | loop:
|
170 | lds hpause,$60 ;aktueller wert Pause (highbyte)
|
171 | lds lpause,$61 ;aktueller wert Pause (lowbyte)
|
172 | lds hpuls,$62 ;aktueller wert Impuls (highbyte)
|
173 | lds lpuls,$63 ;aktueller wert Impuls (lowbyte)
|
174 | lds temp1,$0070
|
175 | out portc,temp1
|
176 | rjmp loop
|
177 |
|
178 |
|
179 |
|
180 |
|
181 |
|
182 |
|
183 | ;---------------------------------------------------------------------------------
|
184 | ;I PWM Interrupt Routine I
|
185 | ;---------------------------------------------------------------------------------
|
186 |
|
187 | startpwm:
|
188 |
|
189 | sts $0060,hpause
|
190 | sts $0061,lpause
|
191 | sts $0062,hpuls
|
192 | sts $0063,lpuls
|
193 |
|
194 | out ocr1ah,hpause ;speichern high byte PAUSE (toff) ocr1a
|
195 | out ocr1al,lpause ;speichern low byte PAUSE (toff) ocr1a
|
196 | ldi workh,$c0
|
197 | out tccr1a,workh ;nach 1. Comp.A Interrupt ->1
|
198 | ldi workh,$02 ;T/C1 clock = Systemclock/8
|
199 | out tccr1b,workh ;Start T/C1
|
200 |
|
201 |
|
202 | ldi workh,$42
|
203 | out timsk,workh ;set Comp. A Interrupt (+ Timer 0 Interrupt)
|
204 |
|
205 | sei
|
206 |
|
207 | ret
|
208 |
|
209 | ;------------------------------ Interruptroutine PWM ----------------------------
|
210 |
|
211 |
|
212 | timer1compa:
|
213 |
|
214 | in stat,sreg ;retten sreg
|
215 | ;clr workh
|
216 | ;out gimsk,workh ;int1 sperren
|
217 | com lpuls
|
218 | com hpuls ;1er Komplement bilden hpuls
|
219 | com lpause ;lpause invertieren
|
220 | com hpause ;hpause negieren
|
221 |
|
222 | in workl,tccr1a ;T/C1 control register A
|
223 | sbrs workl,com1a0 ;Befehl überspringen wenn com1a0 =1
|
224 |
|
225 | rjmp tc1 ;springen wenn com1a0 = 0
|
226 |
|
227 | cbr workl,1<<com1a0 ;next interrupt oc1a -> 0
|
228 | out tccr1a,workl ;speichern tccr1a
|
229 | in addlo,ocr1al ;holen low byte ocr1a
|
230 | sub addlo,lpuls ;und addieren low byte ton
|
231 | in workl,ocr1ah ;high byte ocr1a
|
232 | sbc workl,hpuls ;addieren high byte ton
|
233 |
|
234 | rjmp intende
|
235 |
|
236 |
|
237 | tc1:
|
238 |
|
239 | sbr workl,1<<com1a0 ;next interrupt oc1a -> 1
|
240 | out tccr1a,workl ;neuen Wert zurückspeichern
|
241 | in addlo,ocr1al ;hole low byte ocr1a
|
242 | sub addlo,lpause ;addiere low byte toff
|
243 | in workl,ocr1ah ;nächstes byte ocr1
|
244 | sbc workl,hpause ;und addieren high byte toff
|
245 |
|
246 |
|
247 |
|
248 | intende:
|
249 |
|
250 | out ocr1ah,workl ;speichern neues high byte ocr1a
|
251 | out ocr1al,addlo ;speichern neues low byte ocr1a
|
252 | out sreg,stat ;SREG wiederherstellen
|
253 | reti
|
254 |
|
255 | ; Ende PWM Routine
|
256 |
|
257 | ;---------------------------------------------------------------------------------
|
258 | ;I Drehgeber-Interruptroutine I
|
259 | ;---------------------------------------------------------------------------------
|
260 |
|
261 |
|
262 | t1_ovfl:
|
263 |
|
264 | in temp3,sreg ;SREG sichern
|
265 | push workh
|
266 | lds fahrt,$0070 ;aktuellen Wert Fahrtsufe holen
|
267 | in workh,pinb ;Bitmuster Eingang Port B holen
|
268 | sbrs workh,1 ;Bit an PB1 = H ?
|
269 | rjmp down ;wenn ja, dann nach "down"
|
270 | ldi workh,low(step) ;Wert für Schrittweite holen
|
271 | add fahrt,workh ;Schrittweite addieren und in "Fahrt" speichern
|
272 | rcall ogrenzwert ;Zur Routine "oberer Grenzwert erreicht?"
|
273 | rjmp end_t0int
|
274 |
|
275 | down:
|
276 | subi fahrt,step ;Wert für Fahrtstufe verringern
|
277 | rcall ugrenzwert ;Zur Routine "unterer Grenzwert erreicht?"
|
278 | sts $0070,fahrt ;Wert für Fahrtstufe in SRAM sichern
|
279 | rjmp end_t0int
|
280 |
|
281 |
|
282 | ogrenzwert:
|
283 | ldi workh,$17 ;maxwert 24 für oberen Grenzwert
|
284 | cp fahrt,workh ;Fahrtstufe mit Grenzwert vergleichen
|
285 | brsh setmax ;wenn gleich oder größer, maxwert festlegen
|
286 | ret ;sonst zurück
|
287 |
|
288 | setmax:
|
289 | ldi fahrt,$17 ;maxwert ist 230
|
290 | ret
|
291 |
|
292 |
|
293 | ugrenzwert:
|
294 | ldi workh,$00 ;unterer Grenzwert = 0
|
295 | cp fahrt,workh ;Fahrtstufe mit Grenzwert vergleichen
|
296 | breq setmin ;wenn = erreicht, Wert festlegen
|
297 | ret
|
298 |
|
299 | setmin:
|
300 | ldi fahrt,$01 ;minwert Fahrtstufe ist 1
|
301 | ret
|
302 |
|
303 | end_t0int:
|
304 | sts $0070,fahrt ;neuen Wert für Fahrtstufe in SRAM sichern
|
305 | rcall fahrtstufe
|
306 | ldi workh,$ff
|
307 | out tcnt0,workh ;Counter-Register auf 255 setzen
|
308 | pop workh
|
309 | out sreg,temp3
|
310 | reti
|
311 |
|
312 | fahrtstufe:
|
313 | ldi temp1,$02
|
314 | out timsk,temp1
|
315 | lds mc16ul,$65 ;Konstante aus "calc1" lowbyte aus SRAM holen
|
316 | lds mc16uh,$64 ;Konstante aus "calc1" highbyte aus SRAM holen
|
317 | lds mp16ul,$70 ;Wert für Fahrtstufe lowbyteaus SRAM holen
|
318 | ldi mp16uh,$00 ;highbyte Fahrtstufe auf 0 setzen
|
319 | rcall calc2 ;Multiplikation aufrufen
|
320 | sts $0063,m16u0 ;Ergebniss lowbyte Pulsdauer in SRAM sichern
|
321 | sts $0062,m16u1 ;Ergebniss highbyte Pulsdauer in SRAM sichern
|
322 | mov lpuls,m16u0 ;lowbyte Pulsdauer nach lpuls schieben
|
323 | mov hpuls,m16u1 ;highbyte Pulsdauer nach hpuls schieben
|
324 | rcall calc4 ;Subtraktion Frequenz-Pulsdauer aufrufen
|
325 | sts $0060,hpause ;Ergebniss highbyte Pausendauer in SRAM sichern
|
326 | sts $0061,lpause ;Ergebniss lowbyte Pausendauer in SRAM sichern
|
327 | ldi temp1,$42
|
328 | out timsk,temp1
|
329 | ret
|
330 |
|
331 | ;---------------------------------------------------------------------------------
|
332 | ;I Rechenroutinen I
|
333 | ;---------------------------------------------------------------------------------
|
334 |
|
335 |
|
336 | ;--------------- 16 / 16bit Division
|
337 |
|
338 | calc1:
|
339 | div16u:
|
340 | clr drem16ul ;Hilfsregister lowbyte lschen
|
341 | sub drem16uh,drem16uh ;Hilfsregister highbyte und carry lschen
|
342 | ldi cnt,17 ;Schleifenzhler initialisieren
|
343 |
|
344 |
|
345 | d16u_1:
|
346 | rol dd16ul ;lowbyte dividend links schieben
|
347 | rol dd16uh ;highbyte dividend links schieben
|
348 | dec cnt ;Schleifenzhler um 1 runterzhlen
|
349 | brne d16u_2
|
350 | ret
|
351 |
|
352 | d16u_2:
|
353 | rol drem16ul ;lowbyte dividend im Hilfsregister schieben
|
354 | rol drem16uh ;highbyte dividend im Hilfsregister schieben
|
355 | sub drem16ul,dv16ul ;lowbyte divisor von temp1 abziehen
|
356 | sbc drem16uh,dv16uh ;highbyte divisor von temp2 abziehen
|
357 | brcc d16u_3 ;wenn Ergebniss negativ, springen nach "bertrag"
|
358 | add drem16ul,dv16ul
|
359 | adc drem16uh,dv16uh
|
360 | clc
|
361 | rjmp d16u_1
|
362 |
|
363 | d16u_3:
|
364 | sec
|
365 | rjmp d16u_1
|
366 |
|
367 |
|
368 | ;--------------- 16 * 16bit Multiplikation
|
369 |
|
370 | calc2:
|
371 |
|
372 | clr m16u3
|
373 | clr m16u2
|
374 | ldi cnt,16
|
375 | lsr mp16uh
|
376 | ror mp16ul
|
377 | m16u_1:
|
378 | brcc noadd8
|
379 | add m16u2,mc16ul
|
380 | adc m16u3,mc16uh
|
381 |
|
382 | noadd8:
|
383 | ror m16u3
|
384 | ror m16u2
|
385 | ror m16u1
|
386 | ror m16u0
|
387 | dec cnt
|
388 | brne m16u_1
|
389 |
|
390 | ret
|
391 |
|
392 | ;--------------- 16 - 16bit Subtraktion
|
393 |
|
394 | calc3:
|
395 | ldi workh,low(frequenz) ;lowbyte von Sollfrequenz holen
|
396 | sub workh,lpause ;lowbyte von Pausenzeit abziehen
|
397 | mov lpuls,workh ;Wert nach lowbyte Impuls schieben
|
398 | ldi workh,high(frequenz) ;highbyte von Sollfrequenz holen
|
399 | sbc workh,hpause ;Pausenzeit mit Uebertrag subtrahieren
|
400 | mov hpuls,workh ;Wert nach highbyte Impuls schieben
|
401 |
|
402 | ret
|
403 |
|
404 |
|
405 | calc4:
|
406 | ldi workh,high(frequenz) ;lowbyte von Sollfrequenz holen
|
407 | sub workh,hpuls ;lowbyte von Pausenzeit abziehen
|
408 | mov hpause,workh ;Wert nach lowbyte Impuls schieben
|
409 | ldi workh,low(frequenz) ;highbyte von Sollfrequenz holen
|
410 | sbc workh,lpuls ;Pausenzeit mit Uebertrag subtrahieren
|
411 | mov lpause,workh ;Wert nach highbyte Impuls schieben
|
412 |
|
413 | ret
|