PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : PWM Modulation



frank65
13.06.2010, 15:06
Hallo Zusammen,
ich hab da eine Herausforderung und komme nicht weiter. Hier die
Aufgabe:
Ein Microcontroller mit einer Taktfrequenz von 8MHz. Beschreiben Sie ein
Programm, um einen Aktuatorwert als PWM moduliertes Signal über einen
Digital-Port auszugeben.
Angaben:
- Aktuatorwert integer im Intervall [0...255]
- PMW Frequenz = 1ms
- Pulsdauer maximal, 1/2 Taktperiode.
Wie packe ich ein solches Problem, bzw. Programm an? Kann mir eventuell
jemand auf die Sprünge helfen

Vielen Dank für die Mühe.
Frank

Siro
13.06.2010, 19:31
Habe ich nicht wirklich verstanden.
PWM Frequenz = 1ms ???
Seit wann werden Frequenzen in ms angegeben ? soll das 1 KHz bedeuten ?
Pulsdauer maximal 1/2 Taktperiode ??
halber Takt wovon ? von 8 Mhz ?? Das ist wirklich eine Herausforderung, für denjenigen der es verstehen soll.

JoeBlack
14.06.2010, 01:02
So wie ich die Aufgabe verstehe soll Dein Programm nachher pro ms einen Impuls abgeben der maximal eine halbe ms lang ist.
Mit der programtechnischen Umsetzung habe ich mich noch nicht näher auseinander gesetzt aber soviel ich weiss kannst Du den Prozessor einfach warten lassen. Dazu muss der Compiler die Taktfrequenz des Prozessors kennen.
Innerhalb einer ms liegen 512 "Schritte" von denen minimal 0 und maximal 255 High sein sollen.

Ich hoffe mal, dass Dir das weiterhilft.
An sonsten sag bescheid.
Und wenns funktioniert hat natürlich auch^^

MfG JoeBlack

Siro
14.06.2010, 21:41
; Mit einem PIC Typ 16F88 läst sich dein Problem sicher sehr gut lösen:
; ich habe eine Ansteuerung für Fernsteuerservos damit gemacht:
; Ein Poti (Poti zwischen Vcc und Ground) am ADU-Eingang steuert den Servo in 1024 Schritten.
;
; Hardware Resourcen vom PIC: TIMER 1
; COMPARE 1
; Interrupt COMPARE 1
;
; Kurzbeschreibung: Timer 1 zählt kontinuierlich von 0..65535. Das Compare
; Register wird mit dem entsprechenden Zählerstand geladen. Wenn Timer
; und Compare Register identisch sind, wird ein Interrupt ausgelöst.
; Die Interruptroutine "addiert" zum Compare Wert die neue gewünschte
; Pulslänge und setzt die neue Pegeländerung für das Portbit, welche nach
; Ablauf der neuen Zeit erfolgen soll.
;
; Vergleichswert für das Compare Register = Quarzfrequenz / 4 * Pulslänge
; Bei einem Quarz von 8Mhz ergeben sich folgende Werte:
; 2000000 * 0,0010 sek = 2000 counts für 1,0ms links
; 2000000 * 0,0015 sek = 3000 counts für 1,5ms mitte
; 2000000 * 0,0020 sek = 4000 counts für 2,0ms rechts
;
; deltacount = maxtime-mintime ==> 4000 - 2000 = 2000
; diviert durch Adu Auflösung ==> 2000 / 1024 = 2 entspricht 10 Bit ADU = 1024 Schritte
;
; Vergleichswert = Aducount * 2 + 2000
; 0 * 2 + 2000 = 2000 ==> 0,0010000000000 Sek
; 512 * 2 + 2000 = 3024 ==> 0,0015000000000 Sek
; 1023 * 2 + 2000 = 4046 ==> 0,0019990234375 Sek
;
; den ganzen Code will ich jetzt nicht hier reinstellen, aber vielleicht die Initialisierung:


; Die Vergleichseinheit initialisieren.
; Wir müssen zunächst sicherstellen, das der Zählerstand vom Timer nicht mit dem Vergleichswert
; übereinstimmt. Da der Timer noch nicht gestartet wurde, sollte er auf 0 stehen.
; Doch man staune :
; also erstmal initialiseren
clrf TMR1H ;
clrf TMR1L ; ist nach Reset undefiniert

; nun setzen wir unseren Vergleichswert auf Maximum.
movlw 0xFF ; lade den Maximalen Vergleichswert 0xFFFF
movwf CCPR1H
movwf CCPR1L

; jetzt stellen wir die Vergleichseinheit so ein, das bei Nichtübereinstimmung der
; Portpin LOW sein soll und bei Übereinstimmung auf High gehen soll.
movlw B'00001000' ; init port to low, on match set to high
movwf CCP1CON
; nun steht der Pegel des Portpin ersteinmal richtig, da Zählerstand und Vergleichswert
; nicht identisch sind.

; nun stellen wir die Vergleichseinheit so ein, das bei Übereinstimmung der Pegel
; der Portpins nicht verändert wird, aber ein Interrupt generiert wird.
movlw B'00001010' ; erzeuge Interrupt wenn Zählerstand (Timer1) und Vergleichswert
movwf CCP1CON ; identisch sind, aber ändere nicht den Level des Portpins

bcf PORTB,3 ; Das Bit 3 im Output Latch des Ports wird auf LOW gesetzt,
; damit beim Umschalten von input auf output der Pegel
; sofort LOW ist. Zudem sollte ein Pulldown an den Portpin gelegt
; werden, da der Pin nach einem Reset floatet, wegen input

movlw B'00000101' ; internal Clock 1:1 Fosc/4
movwf T1CON

bcf PIR1,CCP1IF ; lösche Compare 1 Interrupt Flag

bsf STATUS,RP0 ; RAM BANK 1 wählen
bcf TRISB,3 ; nun das Bit im Richtungsregister auf Output setzen.
bsf PIE1,CCP1IE ; Compare 1 Interrupt einschalten
; der erste Interrupt tritt nach ca. 32,78 ms auf, da wir im
; Vergleichsregister 0xFFFF haben. Er verändert aber nicht den Level
; des Portpins. Es wird dann die TABLE in einer Schleife abgearbeitet.
clrf STATUS ; RAM BANK 0 wählen

; bsf T1CON,TMR1ON ; starte Timer 1

; init Timer 0
BANKSEL OPTION_REG
bcf OPTION_REG,T0CS ; timer 0 internal clock
bcf OPTION_REG,PSA ; prescale to Timer 0
bsf OPTION_REG,PS0
bsf OPTION_REG,PS1
bsf OPTION_REG,PS2
clrf STATUS
; bcf INTCON,TMR0IF ; clear Timer 0 Interrupt Flag
clrf TMR0
bsf INTCON,TMR0IE ; enable Timer 0 Interrupt

bsf INTCON,PEIE ; enable Peripheral Interrupts
bsf INTCON,GIE ; enable Global Interrupts
;

Dein Aktuatorwert könnten die unteren 8 Bits des 10 Bit ADU -Wertes sein.
Ich denke, das ist ein gute Grundlage...
mfg. Siro

JoeBlack
15.06.2010, 01:10
@ Siro
Dein Vorschlag geht wenn mich nicht alles täuscht an der Aufgabenstellung vorbei.
Zumindestens kommt es in meinen augen nicht ganz hin das Du bei ner "Frequenz" von 1ms nen Impuls von 2ms hast.
Die Umsetzung an sich ist jedoch gut gelösst.
Nur an den Werten müsste nach meinem Verständniss der Aufgabe noch was gemacht werden.

MfG JoeBlack