Forum: Mikrocontroller und Digitale Elektronik Mehrere PWM-Kanäle mit ATXmega


von Christoph (Gast)


Lesenswert?

Hallo,

ich stehe gerade vor einem Problem mit einem ATXmega32A4, programmiert 
mit dem AVR-Studio. Ich möchte gerne jeweils drei PWM-Kanäle en bloc 
über einen USART setzen, jedoch werden die Werte scheinbar nicht korrekt 
in die Register geschrieben.

Folgende Initialisierung habe ich:

/* Initialize PWM outputs on PORTC and PORTD.
   PWM frequency = 730Hz
   resolution = 8bit */
TCC0.CTRLA    = TC_CLKSEL_DIV64_gc;
TCC0.CTRLB    = TC_WGMODE_SS_gc | TC0_CCAEN_bm | TC0_CCBEN_bm;
TCC0.CTRLC    = 0;
TCC0.CTRLD    = TC_EVACT_OFF_gc;
TCC0.CTRLE    = 0;
TCC0.PER      = 255;
TCC0.CCABUF   = 0;
TCC0.CCBBUF   = 0;

TCC1.CTRLA    = TC_CLKSEL_DIV64_gc;
TCC1.CTRLB    = TC_WGMODE_SS_gc | TC1_CCAEN_bm | TC1_CCBEN_bm;
TCC1.CTRLC    = 0;
TCC1.CTRLD    = TC_EVACT_OFF_gc;
TCC1.CTRLE    = 0;
TCC1.PER      = 255;
TCC1.CCABUF   = 0;
TCC1.CCBBUF   = 0;

TCD0.CTRLA    = TC_CLKSEL_DIV64_gc;
TCD0.CTRLB    = TC_WGMODE_SS_gc | TC0_CCBEN_bm | TC0_CCCEN_bm;
TCD0.CTRLC    = 0;
TCD0.CTRLD    = TC_EVACT_OFF_gc;
TCD0.CTRLE    = 0;
TCD0.PER      = 255;
TCD0.CCBBUF   = 0;
TCD0.CCCBUF   = 0;

Das Setzen erfolgt durch die folgenden Zeilen:

if (PC_Interface_Buffer[3] == 0)
{
   /* Set PWM1, 2 and 3 */
   TCD0.CCCBUF = PC_Interface_Buffer[4];
   TCD0.CCBBUF = PC_Interface_Buffer[5];
   TCC1.CCABUF = PC_Interface_Buffer[6];
}
else
{
/* Set PWM4, 5 and 6 */
   TCC1.CCBBUF = PC_Interface_Buffer[4];
   TCC0.CCBBUF = PC_Interface_Buffer[5];
   TCC0.CCABUF = PC_Interface_Buffer[6];
}

Wenn ich jetzt in TCD0.CCCBUF den Wert 255 schreibe und in TCD0.CCBBUF 
0, so bleiben beide PWM-Kanäle auf 0 (geprüft mit Oszi). Vertausche ich 
die Werte (TCD0.CCCBUF jetzt 255), so liegt an OC0B (also dem anderen) 
das Signal an, OC0C bleibt 0.

Mir scheint es, als würden die Werte nicht korrekt in die Register 
geschrieben werden. Daher hatte ich auch schon CCx statt CCxBUF 
probiert, mit dem gleichen Resultat.

Sonst noch jemand eine Idee? Schreibe ich nur ein Register in der 
gleichen Routine, geht es merkwürdigerweise.

Grüße

Christop

von Gerhard G. (xmega)


Lesenswert?

Hallo,

du musst deine Werte in diese Register speichern.

zum Beispiel:

TCC0.CCA=0x00FF;
TCD0.CCA=0x0FFF;
usw.

nicht in die Buffer!!


Gruß xmega

von Christoph (Gast)


Lesenswert?

Hallo,

genau das hatte ich auch probiert, siehe Text oben. Das Resultat blieb 
jedoch das gleiche.

von Knut B. (Firma: TravelRec.) (travelrec) Benutzerseite


Lesenswert?

Dein Code sollte sich mal darauf einigen, welche Register überhaupt 
beschrieben werden sollen. Sowohl die Timer, als auch die 
OCR/PWM-Register werden mit abweichenden Bit/Registernamen definiert. 
Überprüfe nochmal jede einzelne Zeile Deines Codes!

von Christoph B. (christophbudelmann) Benutzerseite


Lesenswert?

Knut Ballhause schrieb:
> Dein Code sollte sich mal darauf einigen, welche Register überhaupt
> beschrieben werden sollen. Sowohl die Timer, als auch die
> OCR/PWM-Register werden mit abweichenden Bit/Registernamen definiert.

Die Initialisierung passt soweit, zumindest stimmen die Registernamen 
alle zueinander. Benutzt werden scheinbar 0A und 0B sowie 1A und 1B von 
TimerC sowie 0B und 0C von Timer D (wobei 0A scheinbar initialisiert 
wird, aber nicht in dem zweiten Teil des Codes genutzt wird.

> Überprüfe nochmal jede einzelne Zeile Deines Codes!

Das würde ich auch raten, allerdings würde ich auch mal genau 
überprüfen, ob die Werte aus dem UART (sieht zumindest danach aus) 
korrekt gelesen werden oder ob da schon falsche Werte ankommen.

Ob man CCx oder CCxBUF verwendet, sollte für die Funktion erstmal keine 
Rolle spielen (beeinflusst nur den Update-Zeitpunkt).

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.