Hallo Leute, kann mir eventuell jemand bei meinem PWM Problem helfen? Ich würde gerne mit meinem PIC ein Rechtecksignal mit ca. 4kHz ausgeben. #include <18f4550.h> #fuses HS,NOLVP,NOWDT #use delay (clock=20000000) void main () { setup_ccp1(CCP_PWM); setup_timer_2(T2_DIV_BY_16, 75, 1); //75 würde normalerweiße die 4kHz definieren oder? while(TRUE) { set_pwm1_duty(521); } } Wieso bekomme ich statt einem 4kHz Signal nur eine Gleichspannung heraus?
was nun wirklich: > ... PWM Problem helfen? . > .. Rechtecksignal mit ca. 4kHz ausgeben. PWM oder Rechtecksignal? MfG Klaus
Wen beim PWM Signal der duty cycle auf 50% eingestellt ist kann ich damit ja ein rechtecksignal mit einer Frequenz von z.B. 4kHz erzeugen oder etwa nicht?
Duty cycle hat mit der Frequenz nichts zu tun. There are 2 principal different ways to use the PWMs, either you choose to have a accurate frequency or you choose for a high resolution control. Let's look at the basic parameters total period time = 4 * (pr2 + 1) Tclock Prescaler2 positive period time = duty Tclock Prescaler2 Now from these figures you can see that the positive period (which determines the dutycycle) can only vary from 0 to (4*(pr2 + 1)). As PR2 is just 8 bits, 4*PR2 has a maximum of 10 bits. So the only way to achieve a 10-bit dutycyle range is to set PR2 = 0xFF !!! In that case there are only 3 fixed frequencies available, determined by the PreScaler2, of 1kHz, 5kHz and 20kHz (to be exact 1.22, 4.88, 19.5 kHz).
Jeder PIC18 und teilweise auch manche PIC16 besitzen das Capture, Compare, PWM (CCP) Modul mit dem man zusammen mit dem Timer2 ein Pulsweitenmoduliertes Signal (kurz PWM) erzeugen kann. Ich möchte Euch hier kurz erklären wie Ihr mit dem Modul umzugehen habt. Der Timer2 wird mit 1/4 des am PIC angeschlossenen Quarz Taktes gespeist und kann zusätzlich noch über einen Vorteiler des Timer2 in drei Stufen geteilt werden (1, 4, 16). Im Prinzip sind für den PWM Mode nur zwei Register von "Bedeutung": Das Register CCPR1L und PR2. Während der Timer2 immer bei 0 beginnt zu zählen wird der aktuelle Zählerstand (TMR2) immer mit dem Wert in PR2 und CCPR1L verglichen. Wenn der Zählstand des Timers dem Wert in CCPR1L entspricht, dann wird der CCP1 Ausgang (Pin) gelöscht, also auf Low (0V) gesetzt. Wenn der Wert dem in PR2 entspricht, dann wird der Ausgang auf High (=5V) gesetzt und der Timer2 beginnt wieder von 0 an zu zählen. Da man "10 Bit PWM" sagt aber der Timer2 und das PR2/CCPR1L Register ja eigentlich nur 8 Bit groß sind, bekommt das CCPR1L Register zwei zusätzliche Bits spendiert, welche im CCPCON Register übrig sind. Also lässt sich die Periode trotzdem nur mit 8 Bit einstellen (Timer2 und PR2) aber das Tastverhältnis kann in 10 Bit eingestellt werden. Vorgehensweise zum Nutzen des CCP Moduls zur PWM Erzeugung Timer2 einstellen Periode einstellen Tastverhältnis einstellen PWM aktivieren Beispiel am PIC18F4550 Nicht vergessen das CCP Pin zum Ausgang zu machen (TRISx=0) void PWM_Einstellung(void) { PR2=0xFF; // Größt mögliche Periodendauer CCPR1L=0xFF; // Hier wird das Tastverhältnis eingestellt CCP1CON=0x0C; // PWM Mode ausgewählt T2CON=0x79; // 1:16 Postscale, Timer2 aus, Prescale=4 T2CONbits.TMR2ON=1; // Timer2 an } Formel zum Errechnen der Periodendauer PWM Period = [(PR2) + 1] 4 TOSC * (TMR2 Prescale Value) Formel zum Errechnen von PR2 PR2 = [ PWM_Periode / (4 x Tocs x TM2PS) ] -1 Formel zum Errechnen des Tastverhältnissis CCPR1L / PR2 Anwendung: Jetzt könnte man das CCPR1L Register verändern und somit das Tastverhältnis beeinflussen. Ich benutze dies gerne um bei LCD Displays die Hintergrund Beleuchtung der Helligkeit im Raum anzupassen.
@Sunny Wenn Georg nun die 4kHz wichtiger sind als das Tastverhältnis, hast du ihm das Falsche erklärt. Daher meine Frage weiter oben. MfG Klaus
Wenn ich gerne ca. 20 unterschiedliche PWM Signale ausgeben möchte, kann ich mir die Hardware des PIC auch noch irgendwie zu nutze machen, oder läuft das nur in Software? (Es geht um LEDs also ist die "Genauigkeit" unwichtig.) Grüße, Manuel
Man kann auch unterschiedliche PWM Signale erzeugen, das heisst mit jeder Frequenz, aber nicht mit 10 bit.Das geht nur mit 8 bit, soweit ich das verstehe.
Wie das geht kann man hier sehen: -- ------------------------------------------------------------------------ -- initializes the PWM for accurate frequency and starts the PWM -- Frequency and dutycycle should be set by the following constants -- const pwm_frequency = 2_000 -- pwm frequency in Hz -- const pwm1_dutycycle = 50 -- dutycycle in percent of PWM1 -- const pwm2_dutycycle = 50 -- dutycycle in percent of PWM2 -- ------------------------------------------------------------------------ procedure PWM_Init_Frequency (bit in enable1, bit in enable2) is const byte _pr2_1 = target_clock / ( 1 4 pwm_frequency ) const byte _pr2_4 = target_clock / ( 4 4 pwm_frequency ) const byte _pr2_16 = target_clock / ( 16 4 pwm_frequency ) -- due to a limitation in JAL, the brackects below are VERY essential const byte _duty1_1 = ((pwm1_dutycycle * 4) * _pr2_1) / 100 const byte _duty1_4 = ((pwm1_dutycycle * 4) * _pr2_4) / 100 const byte _duty1_16 = ((pwm1_dutycycle * 4) * _pr2_16) / 100 const byte _duty2_1 = ((pwm2_dutycycle * 4) * _pr2_1) / 100 const byte _duty2_4 = ((pwm2_dutycycle * 4) * _pr2_4) / 100 const byte _duty2_16 = ((pwm2_dutycycle * 4) * _pr2_16) / 100 -- calculate prescaler and divider if _pr2_1 == 0 then pragma error -- pwm frequency is too high elsif _pr2_1 <= 256 then PR2 = _pr2_1 - 1 -- load timer value (base period) CCPR1L_shadow = _duty1_1 / 4 -- 8 high order bits of dutycycle CCPR2L_shadow = _duty2_1 / 4 -- 8 high order bits of dutycycle -- 5:4 - 2 least order bits of dutycycle CCP1CON_shadow = ( _duty1_1 & 0b_0000_0011 ) * 16 CCP2CON_shadow = ( _duty2_1 & 0b_0000_0011 ) * 16 -- load tmr2 prescaler, and turn it on T2CON = ( T2CON & 0b_1111_1000 ) | 0b_0000_0100 elsif _pr2_4 <= 256 then PR2 = _pr2_4 - 1 CCPR1L_shadow = _duty1_4 / 4 CCPR2L_shadow = _duty2_4 / 4 CCP1CON_shadow = ( _duty1_4 & 0b_0000_0011 ) * 16 CCP2CON_shadow = ( _duty2_4 & 0b_0000_0011 ) * 16 T2CON = ( T2CON & 0b_1111_1000 ) | 0b_0000_0101 elsif _pr2_16 <= 256 then PR2 = _pr2_16 - 1 CCPR1L_shadow = _duty1_16 / 4 CCPR2L_shadow = _duty2_16 / 4 CCP1CON_shadow = ( _duty1_16 & 0b_0000_0011 ) * 16 CCP2CON_shadow = ( _duty2_16 & 0b_0000_0011 ) * 16 T2CON = ( T2CON & 0b_1111_1000 ) | 0b_0000_0110 else pragma error -- pwm frequency is too low to be realized by this routine, -- use the post scaler and interrupt end if PWM_min1 = 0 PWM_min2 = 0 PWM_max1 = 0xFF PWM_max2 = 0xFF -- set PWM mode --11xx CCP1CON_shadow = CCP1CON_shadow | 0b_0000_1111 CCP2CON_shadow = CCP2CON_shadow | 0b_0000_1111 PWM12_start -- set IO-pin to output _PWM_enable_pins(enable1,enable2) end procedure -- ------------------------------------------------------------------------
Hallo! Leider kann ich den Quellcode nicht recht durchblicken, da ich momentan nicht so tief in PIC-Registern drin stecke. (Btw. welche Sprache ist das denn? Basic? Gibt es da elsif?) Also nur noch mal um meine Frage klar zustellen: Kann ich das Hardware PWM Module so einstellen, dass es an 20 Pins des PIC jeweils kontrolliert unterschiedliche Signale "Spannungen" ausgibt? Grüße, Manuel
>Also nur noch mal um meine Frage klar zustellen: >Kann ich das Hardware PWM Module so einstellen, dass es an 20 Pins des >PIC jeweils kontrolliert unterschiedliche Signale "Spannungen" ausgibt? Nein.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.