Forum: Mikrocontroller und Digitale Elektronik MSP430 variable PWM mit Timer A


von P. G. (dronus)


Lesenswert?

Hallo,


ich versuche eine variable PWM (Signalgenerator) mit einem MSP430FR4133 
zu implementieren. Der Timer dafür hat eine 256 Zyklen lange Periode und 
läuft mit dem vollen Systemtakt. Die auszugebenden Werte werden aus 
einer Tabelle im RAM gelesen.

Leider hat dieser MSP nur "Timer A" Module, die nicht über ein Latch für 
die Compare-Register verfügen wie "Timer B" Module haben.

Daher läuft man beim Setzen der Compare-Register (z.B. TA0CCR1) in 
Gefahr, eine Periode zu überspringen, wenn die Phase gerade entsprechend 
kurz bzw. besonders lang ist. Das beschränkt den nutzbaren Bereich 
ziemlich stark, so auf ca. 50-200 für mit GCC compilierten Code.

Nun will ich versuchen, den TA0CCR1 anstatt im Overflow-Interrupt in 
einem eigenen Interrupt (TA0CCR2=x) zu setzen, und zwar so dass der Wert 
genau zum Zeitpunkt TA0R == 0 gesetzt wird. Damit wird in etwa das 
Verhalten vom CCR-Latch eines "Timer B" simuliert.

Ist das realistisch, oder ist der Ausführungszeitpunkt zu schlecht 
vorhersagbar, um den genauen Zeitpunkt zu treffen?

von Clemens L. (c_l)


Lesenswert?

Die Anzahl der Taktzyklen ist genau spezifiziert (Abschnitt 4.5.1.5 des 
User's Guide). Allerdings braucht ein normaler Befehl zwischen 1 und 6 
Zyklen, also ist beim  Interrupt schon mal eine Ungenauigkeit von 
mindestens 5×MCLK drin.

Timer_B oder zumindest DMA wären schon nützlich ...

von c-hater (Gast)


Lesenswert?

P. G. schrieb:

> Leider hat dieser MSP nur "Timer A" Module, die nicht über ein Latch für
> die Compare-Register verfügen wie "Timer B" Module haben.

Nun, ich habe keine Ahnung von der MSP-Hardware, aber wenn ich einen 
Timer hätte, der keine synchronisierten Updates der Compare-Register 
unterstützt, würde ich einfach in Software eine Synchronisation BAUEN, 
die den Schaden möglichst gering hält.

Das ist doch absolut trivial. Der einzige Nachteil wäre, dass es 
passieren kann, das das Update des Compare-Registers um n (n=unbestimmt, 
aber mindestens 1) Zyklen verzögert erfolgt. In den verpassten Zyklen 
würde einfach der letzte gültige Wert erneut ausgegeben. Das ist 
immerhin sehr viel besser als ein Glitch.

Man muss dazu nur das genaue Timingverhalten der eigenen Software 
kennen. Sprich: in der einzig akzeptablen Sprache für harte Echtzeit 
programmieren: Assembler.

von P. G. (dronus)


Lesenswert?

Hm, die Befehle meines Codes im Interrupt kann ich ja ausmessen. Aber 
wie Clemens sagt ist der Interrupt-Einsprung schon auf 5 Zyklen ungenau, 
und da der MSP430 Caches hat würde mich nicht wundern wenn die Anzahl 
der Waitstates beim RAM-Zugriff ebenfalls schwankt. Allerdings sind die 
alle ausgegebenen PWM-Tabellen recht groß, so dass eigentlich kein 
Cache-Treffer zu erwarten ist, wenn die Tabellen immer vollständig 
ausgegeben werden, was im Moment der Fall ist.

Man kann natürlich den Interrupt "rechtzeitig" ansetzen, und dann in der 
Interrupt-Routine wie bei einem Spinlock auf TA0R == 0 warten.

Bzw. man kann sich doch sicher noch feiner rantasten, um die noch 
genauer als die Zyklenzeit einer Warteschleife zu arbeiten? Z.b. erstmal 
auf TA0R < 5 warten und dann noch etwas abhängig vom TA0R Wert machen? 
So müsste auch eine Punktlandung zu schaffen sein, oder?

von Clemens L. (c_l)


Lesenswert?

P. G. schrieb:
> So müsste auch eine Punktlandung zu schaffen sein, oder?

Mit Code im SRAM, und genügend trickreichen Assemberbefehlen, rein 
theoretisch ja.

von P. G. (dronus)


Lesenswert?

Ich habe das Problem nun anders gelöst:

Da alle generierten Signale ein gutes Stück unterhalb der 
Nyquist-Frequenz liegen, ergibt sich die Garantie, dass die variablen 
Flanken der PWM sich niemals näher als einen bestimmten Mindestabstand 
kommen.

Nach wie vor kann aber bei hoher Amplitude die variable Flanke beliebig 
nahe an die feste Flanke rücken.

Daher habe ich nun das Aktualisieren des PWM-Wertes in einen Interrupt 
auf der variablen Flanke verlegt. Wegen des oben genannten 
Mindestabstandes wird nun keine Periode mehr übersprungen, die 
Interruptroutine passt immer in den Zeitraum zwischen zwei variablen 
Flanken.

Das funktioniert natürlich nur mit Signalen mit einer begrenzten 
Steilheit, aber bisher genügen alle meine zu generierenden Signale 
dieser Bedingung.

Das beantwortet zwar die ursprüngliche Frage nicht ganz, aber 
"funktioniert einfach" ohne großes ausmessen der 
Instruktions-Laufzeiten.

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.