Fragen zu extrem langsamer PWM und Prescaler, PREA, DIVA

OP Persönliche Seite #1395308
Lesenswert?

Hallo,

ich versuche mittels PWM ein Ventil regelmäßig zu schalten. Die 
Periodenlängen dabei sind bis zu 300 sek und einstellbar von 10 bis 
300sek.
Mein AVR32 UC3A1512 läuft auf 12 MHz und der Vorteiler für den PWM-Kanal 
(CPRE aus dem CMR-Register des Kanals) steht auf 1024 (0xA).
Damit komme ich dann bei 16 bit max auf eine Periode von 5.59 sek. 
Deshalb dachte ich, dass ich noch eine 2. Vorteiler nutzen kann und habe 
das so angestellt:
1
void PWM2(int channel, int duty, int period)
2
{
3
  AVR32_GPIO.port[1].gperc = 1 << (19+channel);              // PB20 = PWM Channel[1]
4
  AVR32_GPIO.port[1].pmr0c = 1 << (19+channel);              // PB20 = Function A
5
  AVR32_GPIO.port[1].pmr1c = 1 << (19+channel);              // PB20 = Function A
6

7

8
  AVR32_PWM.mr =     0 << AVR32_PWM_PREB_OFFSET |        // PWM PREB Divider Input clock
9
            0xa << AVR32_PWM_PREA_OFFSET |        // PWM PREA Divider Input clock
10
            0 << AVR32_PWM_DIVB_OFFSET |        // PWM CLKB Divider factor
11
            0xff << AVR32_PWM_DIVA_OFFSET ;        // PWM CLKA Divider factor
12

13

14
  AVR32_PWM.channel[channel].cmr =
15
                0 << AVR32_PWM_CPD_OFFSET |    // Writing to the CUPD1 will modify the duty cycle at the next period start event.
16
                0 << AVR32_PWM_CPOL_OFFSET |  // The output waveform starts at a Low level.
17
                0 << AVR32_PWM_CALG_OFFSET |   // The period is left aligned.
18
                0x3 << AVR32_PWM_CPRE_OFFSET ;  // PWM CLKA Divider factor
19

20
  AVR32_PWM.channel[channel].cprd = period;          // max pwm Value
21
  AVR32_PWM.channel[channel].cdty = duty;            // duty
22

23
  AVR32_PWM.ena |= 1 << channel;                // Enable PWM Channel[1]
24
}

Leider stellt sich nicht der gewünschte Effekt ein (MCK/(PREA*DIVA)).

Wer weiß rat oder hat selbiges schon probiert?
OP Persönliche Seite #1396426
Lesenswert?

So, wie ich nochmal nachgelesen habe, ist der interne Counter 20bit 
groß, d.h. ich kann bis 1048575 zählen, was mir bei maximalen Vorteiler 
und 12 MHz 89.4784 s Periodenlänge (sogar selbst gemessen) ermöglicht. 
Schon etwas näher dran, aber immer noch daneben. Wie löst man das 
Problem vielleicht eleganter?

Als Notlösung könnte ich den Chiptakt auf z.B. 3 MHz reduzieren, was 
aber Nachteile bringt.
OP Persönliche Seite #1404948
Lesenswert?

Ich habe noch eine Frage:

Standardmäßig wird beim AVR32 bei Änderungen der Periodenlänge oder der 
Pulsbreite erst im nächsten Periodendurchlauf der Parameter geändert.
Da ich aber sofort eine Änderung möchte, dachte ich, es wäre möglich die 
PWM des Kanals zu dekativieren und einfach neu zu initialisieren.
Allerdings setzt sich der µC dort mit dem A**** drauf und macht selbst 
bei folgender Variante Änderungen erst im nächsten Periodendurchlauf:
1
if (buttons[1] == 1){
2
      up++;
3
      if(up > 80){up = 80;}
4
      AVR32_PWM.dis = (1 << 2);             //PWM for channel 2 disabled
5
      PWM2(2, 2343, 11718+up*11718); //11718 entspricht einer Sekunde
6
    }

Code der Funktion PWM2:
1
void PWM2(int channel, int duty, int period)
2
{
3
  AVR32_GPIO.port[1].gperc = 1 << (19+channel);              // PB20 = PWM Channel[1]
4
  AVR32_GPIO.port[1].pmr0c = 1 << (19+channel);              // PB20 = Function A
5
  AVR32_GPIO.port[1].pmr1c = 1 << (19+channel);              // PB20 = Function A
6
  AVR32_PWM.channel[channel].cmr =
7
                0 << AVR32_PWM_CPD_OFFSET |    // Writing to the CUPD1 will modify the duty cycle at the next period start event.
8
                1 << AVR32_PWM_CPOL_OFFSET |  // The output waveform starts at a Low level.
9
                0 << AVR32_PWM_CALG_OFFSET |   // The period is left aligned.
10
                0xa << AVR32_PWM_CPRE_OFFSET ;  // PWM CLKA Divider factor
11

12
  AVR32_PWM.channel[channel].cprd = period;          // max pwm Value
13
  AVR32_PWM.channel[channel].cdty = duty;            // duty
14
  AVR32_PWM.ena |= 1 << channel;                // Enable PWM Channel[1]
15
}

Wie gesagt, über CUPD lässt sich auch erst in der nächsten Periode etwas 
ändern.

Wie kann man PWM sofort stoppen und wieder neu starten lassen?

Das Manual sagt:
"CNT: Channel Counter Register
Internal counter value. This register is reset when:
• the channel is enabled (writing CHIDx in the ENA register).
• the counter reaches CPRD value defined in the CPRDx register if the 
waveform is left aligned."

Das entsprechende Bit wird ja auch gesetzt ... :-/

Antwort schreiben

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren