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 ... :-/