Forum: Mikrocontroller und Digitale Elektronik PIC18f4550 mit PWM


von Georg I. (georgi)


Lesenswert?

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?

von Klaus (Gast)


Lesenswert?

was nun wirklich:

> ... PWM Problem helfen?
.
> .. Rechtecksignal mit ca. 4kHz ausgeben.

PWM oder Rechtecksignal?

MfG Klaus

von Georg I. (georgi)


Lesenswert?

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?

von Sunny (Gast)


Lesenswert?

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).

von Sunny (Gast)


Lesenswert?

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.

von Klaus (Gast)


Lesenswert?

@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

von Manuel (Gast)


Lesenswert?

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

von Sunny (Gast)


Lesenswert?

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.

von Sunny (Gast)


Lesenswert?

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
-- 
------------------------------------------------------------------------

von Manuel (Gast)


Lesenswert?

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

von holger (Gast)


Lesenswert?

>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
Noch kein Account? Hier anmelden.