PDA

Archiv verlassen und diese Seite im Standarddesign anzeigen : PWM --> Pic



Superfreak
19.06.2008, 07:50
hey leute,

habe ien frage und zwar kann mir jemand eine url posten. Wo erklärt bekommt wie die Pwm bei Pics programmeiren kann.
Habe es bei spurt nicht so ganz kapiert,
oder wenn jemand von euch eine fertigen Programme code hat und mir den posten kann, wäre es auch nciht shclecht. Müsste nur wissen was ich dann da ändenr müsste

Duke of Doom
19.06.2008, 08:02
c oder Assembler

Superfreak
19.06.2008, 16:20
in assembler bitte

the_Ghost666
19.06.2008, 19:04
Ok, Prinzipell läufts immer gleich ab:
Erst initialisieren, dann nutzen.

Das PWM-Modul hat einige SpecialFunctionRegisters, mit denen es benutzt wird. Ich zeig das mal am PIC16F876a.

Da wäre einmal der Timer2, er stellt den Takt für die PWM-Erzeugung bereit.

CCP1CON ist das Controll Register. Es besteht aus den Wahlschaltern für die Modulfunktion (kann ja auch zb Pulse vermessen), und den zwei kleinsten Bit, da wir hier ein 10Bit PWM haben.
Am besten schreibst du für PWM 0x0F in CCP1CON, also die untersten 4 Bit =1. Du müsstest nur Bit 2 und 3 auf 1 setzen, da Bit 0 und 1 ja X, also unwichtig sind, um PWM zu erreichen.

Ausserdem schreibst du in das PR2 Register. Hier wird die Periodendauer des Signals angegeben, dh, wieviel Zeit vergeht, bis das PWM-Signal wieder von neuem beginnt. Im Datenblatt steht dazu eine Formel.
Die Periodendauer hängt ab von: Dem Wert in PR2, dem Prescaler (Vorteiler) von Timer2 und dem Oszillatortakt an Timer2, meist die Frequenz des externen Quarz.
Ich benutze immer eine kleine Excel Datei um alle Werte einzutragen. Dann kann man solange probieren, bis man genau hat, was man will. Natürlich kannst du auch zu Fuß rechnen.

Danach kommt das Einschaltverhältnis, oder Duty-Cycle dran. Im Register CCPR1L kannst du einen Wert von 0-255 reinschreiben. Damit hast du 256 Stufen, du kannst noch die Bits 4 und 5 von CPP1CON nutzen, um auf 1024 Stufen Auflösung zu kommen. Meist habe ich es nicht gebraucht.
Noch was zur Auflösung: Die ändert sich mit dem Prescaler von Timer2, du kannst also nicht unbedingt alle 10bit nutzen. Ich verweise nur auf die Formel im Datenblatt.

Wichtig: Der CCP1 oder CCP2 Pin, ist nur mit dem Modul verbunden, wenn er über das TRIS Register auf Ausgang geschaltet ist, sonst bekommst du kein PWM Signal, sondern nur High oder Low Pegel, je nach Beschaltung.

Ok, der Ablauf ist folgendermaßen:
Zuerst PR2 wie gewollt einstellen,
Dann das Einschaltverhältnis in CCPR1L schreiben,
Den CCP Pin mit TRIS auf Ausgang stellen,
Den Timer2 Vorteiler einstellen und Timer2 anschalten,
Zum Schluss den 0x0F in das CCP1CON Register schreiben.

Hier ein Beispielcode von mir, er soll ein Signal mit 38kHz liefern, das ungefähr 25% Einschaltdauer hat und am Pin wahlweise ausgegeben wird.




;PWM INIT
BANKSEL PR2 ;PWM auf 38kHz, DutyCycle 0,25
MOVLW D'78'
MOVWF PR2
BANKSEL CCPR1L
MOVLW D'20'
MOVWF CCPR1L
BANKSEL T2CON
MOVLW D'4'
MOVWF T2CON
BANKSEL TMR2
CLRF TMR2
BANKSEL CCP1CON
MOVLW 0x0F
MOVWF CCP1CON

;In der Anwendung Signal einschalten:
BANKSEL TRISC
BCF TRISC,2
;Ausschalten
BANKSEL TRISC
BSF TRISC,2

Superfreak
19.06.2008, 20:35
ja wollte das mit dem pic 16f877a machen

aber danke =) werde es morgen mal direkt ausprobieren=) danke sehr

the_Ghost666
19.06.2008, 22:38
Der Pic 16F877A ist genau der gleiche, wie der 876A, hat nur einen Port mehr. Dh du musst nur schauen, ob der CCP1 Pin anders liegt. Was der Banksel Befehl bzw das Macro macht, weißt du?

Superfreak
22.06.2008, 13:19
also habe dies jetzt mal für 9.5 kz gemacht


;PWM INIT
BANKSEL PR2 ;PWM auf 9.5 kHz, DutyCycle 0,25
MOVLW D'20'
MOVWF PR2
BANKSEL CCPR1L
MOVLW D'5'
MOVWF CCPR1L
BANKSEL T2CON
MOVLW D'1'
MOVWF T2CON
BANKSEL TMR2
CLRF TMR2
BANKSEL CCP1CON
MOVLW 0x0F
MOVWF CCP1CON

;In der Anwendung Signal einschalten:
BANKSEL TRISC
BCF TRISB,1 ; Pin auswahl für die PWm
;Ausschalten
BANKSEL TRISC
BSF TRISB,1


müsste doch so stimmen oder?
ccp1 i ist auf bank 1
siehe --> http://ww1.microchip.com/downloads/en/DeviceDoc/39582b.pdf

und im initialisierungsbereich einfach ccp1con, CCPR1L etc. löschen!
Danach direkt dem pwm code drunter schreiben?
Anosnten habe ich es echt gut verstanden, mit der PWM. War echt super beschrieben danke schon einmal.

the_Ghost666
22.06.2008, 14:13
Nein, wenn du das mit dem PIC16F877A machen willst, ist CCP! der Pin RC2, also muss es BSF TRISC,2 heißen!

Mit welchem Takt betreibst du den PIC?
Bei 4Mhz wär deine Einstellung eine Frequenz von ca. 12kHz, bei 2Mhz ca. 6kHz.

Superfreak
22.06.2008, 15:03
ja stimmt
habe ich nach dem posten auch schon bemerkt=)

aber danke

Bräuchte aber 2 mal eine PWM, hat der PIC16f877 nur einen Pin, wo die PWM erzeugt werden kann.??
die Taktfrequenz ist 4 Mhz sprich dann 12 khZ
habe das programm nun noch einmal umgeschrieben







LIST p=16F877 ; list directive to define processor
#include <p16F877.inc>; processor specific variable defs
__CONFIG H'3F39' ; _CP_OFF & _WDT_OFF & _PWRTE_ON & _RC_OSC
ERRORLEVEL -302 ; unterdrücke Warnungen zur Bank-Auswahl
ERRORLEVEL -203




Main:
Initialisierung

bsf STATUS,RP0
clrf TRISD

bcf STATUS,RP0
clrf PORTD
clrf CCPR1L
clrf T2CON
clrf TMR2
clrf CCP1CON
clrf TMR2 ; TMr muss nicht vor definiertwerden



Ausgabe:


;PWM INIT
BANKSEL PR2 ;PWM auf 12 MHz, DutyCycle 0,25
movlw D'20'
movwf PR2

BANKSEL CCPR1L
MOVLW D'5'
MOVWF CCPR1L
BANKSEL T2CON
MOVLW D'1'
MOVWF T2CON
BANKSEL TMR2
CLRF TMR2
BANKSEL CCP1CON
MOVLW 0x0F
MOVWF CCP1CON

;In der Anwendung Signal einschalten:
BANKSEL TRISC
BCF TRISC,2
;Ausschalten
BANKSEL TRISC
BSF TRISC,2



goto Ausgabe


end

the_Ghost666
22.06.2008, 18:40
nein, der PIC16F877A hat zwei, CCP1 und CCP2, die liegen beide auf PORTC und du kannst den zweiten separat mit den Registern CCP2CON usw ansteuern, aber sie müssen wohl mit gleicher Frequenz laufen

Superfreak
22.06.2008, 19:00
ja klar ist verständlich, aber so wie ich das oben geschrieben habe, müsste es doch gehen oder ?

the_Ghost666
22.06.2008, 19:57
Ich glaub schon, du kannst folgendes machen um es zu testen:
MPLAB IDE und der Simulator haben ein Oszilloskop in Software, das auch die PWM Outputs richtig darstellen kann. Du stellst als Debugger MPLAB SIM ein, dann gehst du auf View und Simulator Logic Analyser. Unter Channels wählst du dann CCP1 und CCP2 aus. Dann kannst du das Programm laufen lassen und dir ansehen.

Superfreak
22.06.2008, 20:54
ja habe es gefunden, aberleider ist dort immer dasselbe signal--..

Werde noch etwas herum experimentieren..
sage bescheid, wenn sich was tut ^^

also ich kenne das vom Timer 0 so, dass der bei der initialisierung noch im Oprionreg eingestellt werden muss.
Muss man dies bei der PWM für den timer auch machen

the_Ghost666
22.06.2008, 23:13
Ich hab nochmal deinen Code angeschaut, diesmal genauer:

Das kann nicht gehen, du hast eine Endlosschleife von Ausgabe bis goto Ausgabe, dh das CCP Modul wird jedes mal neu gestartet. Das ist nicht weiter schlimm, aber auch nicht hübsch.
Was schlimm ist, ist, dass du ihm überhaupt keine Zeit lässt, das PWM-Signal auch zu senden, du aktivierst es und schaltest es 3 Befehle später wieder ab, da kann ja nichts zu erkennen sein!
Bau eine Pausenschleife ein, oder teste erstmal nur mit einem eingeschalteten Signal. Dann sollte auch der Logic Analyser was anzeigen.

EDIT:
GANZGANZ WICHTIG! Das kann nicht klappen, wenn Timer2 nicht läuft. Du benutzt den Befehl MOVLW D'1' MOVWF T2CON,
Dabei setzt du nur Bit0, für den Prescaler, aber Bit2 bleibt auf null, damit läuft der Timer nicht! Also wird er auch nie Zählen und den PWM Wert erreichen, woraufhin das ganze den Pegel wechselt. Schreibe entweder eine D'5' in T2CON oder mache anschließend den Befehl BSF T2CON,2. Mit letztem bist du immer auf der sicheren Seite, da dieser Befehl nur das entsprechende Bit setzt, egal was in dem Register steht.

Superfreak
23.06.2008, 11:42
danke danke
habe jetzt einen funktionstüchtigen code.
Dieser funktioniert auch per Simulation =)

falls du ihn brauchst oder fragen dazu hast=)
beantworte ich sie dir gerne




initialisierung
; Vorteiler
BsF T2CON,T2CKPS1 ; Vorteiler 16:1
bcf T2CON,T2CKPS0
BSF T2CON,TMR2ON ; Timer2 ein

; Frequenz
BSF STATUS,RP0 ; Bank1
MOVLW D'123'
MOVWF PR2 ; 2,5 kHz
BCF STATUS,RP0 ; Bank1

; Tastverhältnis auf 50% einstellen
MOVLW D'62'
MOVWF CCPR1L ; 50% von 124

; RC2/CCP1 auf Ausgang stellen
BSF STATUS,RP0 ; Bank1
BCF TRISC, 2 ; RC2: output=0
BCF STATUS,RP0 ; Bank 0

; PWM MODE mit CCP1 initialisieren
CLRF CCP1CON ; CCP1-Modus aus
BSF CCP1CON,CCP1M3 ; CCP1-Modus PWM-Mode
BSF CCP1CON,CCP1M2

loop
GOTO loop

end

the_Ghost666
23.06.2008, 11:50
Super! Schön, dass es läuft.
Das hast du auch gut und deutlich kommentiert.

Nochmal zu BANKSEL:
Das ist ein Macro, was selbstständig erkennt, welches Register in welcher Bank du ansprechen willst. D.h. du brauchst dich nicht mit BSF STATUS,RP0 zu bemühen, da Banksel automatisch die Bits richtig setzt. Das ist ganz nett, wenn man mit vielen SFRs hantiert, hat aber immer 2 Befehle, statt möglicherweise 1.

Superfreak
23.06.2008, 16:12
ja danke schon mal für deine hilfe =)

bei meiner programmierung kommt es nicht so sehr auf die zeit an. Deswegen habe ich es lieber so gemacht.
Funktioniert auch so=)

the_Ghost666
23.06.2008, 21:30
Nene, eigentlich ist deine Lösung sogar schneller, als die mit Banksel, funktionieren tut beides, ausserdem weiß man bei deiner Lösung immer wo man ist, sodass man vielleicht mehrere Tätigkeiten in einer Bank durchführen kann. Dennoch halte ich das Banksel Macro für sinnvoll und praktisch, deswegen hab ichs ja auch benutzt. Wollte das nurnoch mal erläutern.
Was wird das denn genau, wofür du das PWM brauchst? Ich hab mit meinem Beispiel Code ne Samsung-Fernbedienung imitiert.