PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : 8 Bit stand alone PWM auf 16 Bit aufgebohrt



The Man
19.10.2008, 08:56
Hallo zusammen,

ich hab gestern mal ein bisschen expeimentiert. Und zwar hatte ich das allgemein bekannte Problem, dass man für RGB drei PWM Kanäle braucht, aber z.B. der Mega8 nur zwei 16 Bit hat. (ich brauch zwingend drei).
Zwei laufen einfach auf dem Compare Units des Timer 1.

Als Eingabe habe ich zwei Spannungsteiler. Der eine Wert wandert direkt in das OCR2 Register. Der andere ist im Prinzip ein Dimmwert.

Hab jetzt aus dem 8 Bit des Timer 2 einen 16 er gemacht. Der Timer 2 ist so aufgesetzt, dass er im fast PWM läuft und bei comparematch den OC2 Pin Low schaltet. Trotzdem lasse ich den zugehörigen Interrupt ausführen.
In der ISR wir eine Variable einfach nur hochgezählt, die naturgemäß bei 255 überläuft. Diese Variable wird mit dem Dimmwert verglichen. Ist sie gleich oder größer, wird das Datenrichtungsbit vom OC2 Pin auf Input gesetzt. Ist sie kleiner, auf Ausgang.

Außerdem habe ich eingaut, das im Prinzip "vorrausschauend" gearbeitet wird. Das Kommentiere ich im Code.

Im Ergebnis ist das natürlich kein echtes 16 Bit PWM, weil die einzelnen 8 Bit PWM´s hintereinander ablaufen. Aber für LED Anwendungen ist das gehupft wie gesprungen.

mfg,
The Man



.include"m8def.inc"

.org 0x0000
rjmp reset
.org OC2addr ; OCR2 Interrupt Vector Address
rjmp hitvalue
reset:
ldi r16,HIGH(RAMEND)
out SPH,r16
ldi r16,LOW(RAMEND)
out SPL,r16
ldi r16,0b00000000
out DDRB,r16
out PORTB,r16
ldi r16,0b10000000
out TIMSK,r16
ldi r16,0b01101001
out TCCR2, r16; fast PWM,
ldi r16,255
out ICR1H,r16
out ICR1L,r16
ldi r16,255
out OCR1AL,r16
ldi r16,0b10100010
out TCCR1A,r16; clear on match, compare output, fast PWM => ICR1A = Top
ldi r16,0b00011001
out TCCR1B,r16; fast PWM => ICR1A = Top, prescaler = 1
sei

main:
;**********************
;Erfassung Dimmwert
;
ldi r16,0b00100000
out ADMUX,r16
ldi r16,0b11010101
out ADCSRA,r16
warten0:
in r16,ADCSRA
sbrs r16,4
rjmp warten0
in r18,ADCH ;DIMMER
ori r18,1
;**********************

ldi r16,0b00100011
out ADMUX,r16
ldi r16,0b11010101
out ADCSRA,r16
warten3:
in r16,ADCSRA
sbrs r16,4
rjmp warten3
in r21,ADCH
out OCR2,r21

;*********************************
;die gehen an die Comapre Units des Timer 1
;
ldi r16,0b00100001
out ADMUX,r16
ldi r16,0b11010101
out ADCSRA,r16
warten1:
in r16,ADCSRA
sbrs r16,4
rjmp warten1
in r19,ADCH

mul r18,r19
out OCR1AH,r1
out OCR1AL,r0

ldi r16,0b00100010
out ADMUX,r16
ldi r16,0b11010101
out ADCSRA,r16
warten2:
in r16,ADCSRA
sbrs r16,4
rjmp warten2
in r20,ADCH

mul r20,r18
out OCR1BH,r1
out OCR1BL,r0
;*********************************
rjmp main

hitvalue:

out DDRB,r27
inc r25;
;***************************
;hier wird die Bitkodierung des DDRB für den nächsten Durchgang
; vorrausberechnet
mov r26,r25;
inc r26;<<<<=== VORALLEM HIER!!!
cp r26,r18;
brlo ok;
ldi r27,0b00000110;
rjmp nicht_ok;
ok:;
ldi r27,0b00001110;
nicht_ok:;
;***************************
reti

Besserwessi
19.10.2008, 10:01
Die Lösung ist schon gar nicht schlecht, und unterscheidet sich eigentlich nicht von echtem 16 Bit PWM. Alternativ könnte man auch als 8 Bit PWM
zwischen den High Byte und dem Highbyte+1 umschalten. Das gibt dann kein normales PWM aber im Mittel das gleiche.

Bei der Umsetzung ist allerdings noch ein Fehler drin: die Interruptsroutine sichert nicht den Prozessor status. Dadurch kann es im Hauptprogramm zu ziehmlich seltsamen Effekten kommen. Eventuell sollte man auch die anderen benutzten Register auf den Stack retten. Das ist aber in ASM optional, denn man kann auch einfach ein paar Register für die Interrupts reservieren.

Bei einigen Werten könnte es immer noch zu kleinen Fehlern kommen ( <255). Auch ist man darauf angewiesen das der 8 Bit PWM den OCR-wert Puffert. Soweit ich weiss wird das nicht bei allen Chips/Timern gemacht.

The Man
19.10.2008, 10:40
Hi,

was meinst du mit Fehlern <255 ? Wenn der ADC < 255 ? Ich mache ohnehin nur eine 8 Bit Wandlung.

Meinst du, ich schreibe abwechselnd das High und Lowbyte der Multiplikation in das OCR2?

Greez

Besserwessi
19.10.2008, 13:58
Bei kleinen Werten klapt es tatsächlich. Da sollte es keine Probleme geben. Das Problem mit den Statusregister sollte man aber schon ernst nehmen. Bei dem Kurzen Hauptprogramm hier geht es wohl noch gut weil man da ohne SREG auskommt. Das ist aber eher die Ausnahmen.

Hanni
28.11.2008, 12:26
Eine Anmerkung:

Bit Monster ala 0b00110010 lassen sich ohne Datenblatt nur schwer nachvollziehen. Besser wäre es die zu ladenden Bits direkt zu benennen.

Grüße,
Hanni