Hallo zusammen,
ich bin gerade dabei mir eine 32-Kanal Soft-PWM in C zusammen zu bauen.
Insgesamt funktioniert der Code auch schon, aber ich hab mir dann mal
das Assembler-Listing angeguckt und gesehen, daß da noch
Verbesserungspotenzial ist, nur weiß ich leider nicht, wie ich das
umsetzen kann.
Insgesamt läuft es ungefähr so, wie in dem Artikel hier zur Soft-PWM:
in der ISR einen Zähler hochzählen, und dann von jedem Kanal den
PWM-Wert mit dem Zähler vergleichen und ein Bit setzen/löschen.
Das sieht in C (am Beispiel von nur zwei Kanälen) so aus:
Insgesamt "relativ" klar. Aber man sieht ja z.B., daß jedes mal der
ISR-Zähler in r24 kopiert wird. Es würde doch reichen, das ein einziges
Mal zu machen.
Auch könnte man den Wert in r19 doch stehen lassen, und erst ganz zum
Schluß ein einziges mal nach "Shift_Register" kopieren.
Aber ich frag mich, wie ich diese Dinge in mein Programm gebastelt
kriege o_O . Oder kann man den C-Sourcecode so umstellen, daß der
Compiler das besser hinkriegt?
Danke schonmal,
Grüße!
m.n. schrieb:> Vielleicht als Anregung:> http://mino-elektronik.de/AVR_PWM_64/AVR_PWM_64.htm> Die PWM wird etwas anders erzeugt. Du mußt ein bißchen lesen, um es zu> verstehen.
Hi und vielen Dank für die schnelle Antwort!
Das sieht wirklich interessant aus. Das ist ja in der Tat sehr ähnlich
zu meiner Anwendung :) .
Ich werde mich mal an (Inline-)Assembler versuchen. Ich glaube auf die
Schnelle ist das das... ähm... schnellste :P .
Danke!
Sind Shift_Register und/oder IRQ_Counter zufällig global?
Dann eventuell mal sowas probieren:
1
uint8_ttmp=Global;
2
// ...Rechnen mit tmp anstatt Global
3
Global=tmp;
Also temporäre Variablen verwenden. Datentyp natürlich anpassen. avr-gcc
optimiert Operationen mit globalen Variablen meist nicht wirklich oder
zumindest sehr unzuverlässig.
Detlef schrieb:> Sind Shift_Register und/oder IRQ_Counter zufällig global?>> Dann eventuell mal sowas probieren:>>
1
uint8_ttmp=Global;
2
>// ...Rechnen mit tmp anstatt Global
3
>Global=tmp;
>> avr-gcc optimiert Operationen mit globalen Variablen meist nicht> wirklich oder zumindest sehr unzuverlässig.
besonders wenn "Global" als volatile deklariert ist, was man nur
braucht, wenn Daten von ISR und Hauptprogramm gemeinsam genutzt werden.
Die lokale Variable "entfernt" dieses volatile, was kein Problem ist,
solange es keine weitere ISR gibt und man innerhalb der beiden ISR die
Interrupts gesperrt läst.
Noch klarer könnte man Daten, die nur die ISR benutzt, innerhalb dieser
als "static" deklarieren. Dann kommt auch keiner von außen an so ran.
Richtig, aber bei volatile sind dem Compiler auch die Hände gebunden.
Das darf er gar nicht anders.
Trotzdem optimiert avr-gcc auch normale nicht-volatile globale und auch
static(!) Variablen nur sehr unzuverlässig. Da kommt man oft nicht um
temporäre Variablen herum. Einfach mal in größeren Projekten testen.
Hallo nochmal,
vielen Dank für eure Antworten! Das mit den Abhängigkeiten zwischen
Datentyp und Optimierung wußte ich nicht. Damit werde ich mal ein wenig
herumexperimentieren.
@Detlef
ja, die Variablen sind leider global. Und so, wie es im Moment ist,
komme ich da auch nicht drum herum, weil mit den VAriablen außerhalb der
ISR noch was gemacht wird, was zu zeitfressend ist, als daß ic es mit in
die IRS packen wollen könnte/möchte.
Ich hab das Ganze jetzt nochmal als Inline-Assembler aufgezogen. Von
Prinzip her kommt es mir jetzt etwas sinnvoll vor, aber testen konnte
ich es noch nicht X( . Ich gebe auf jeden Fall Rückmeldung, wie's läuft,
wenn's läuft.
Danke nochmal!
Wenn Deine PWM Deinen mc so stark belastet, daß Du optimieren musst,
würde ich erst einmal den verwendeten Algorithmus unter die Lupe nehmen.
Statt <PWM-Auflösung> mal Interrupts mit jeweils 32 Vergleichen kannst
Du auch mit zwei vorberechneten Tabellen[32] mit Timer-Offsets und
Port-Outputs arbeiten. Das braucht mehr RAM für die Tabellen, ist aber
um Größenordnungen schneller: In einem IRQ gibst Du dann nur den
nächsten Timer-Offset und 4 Werte auf die PWM-8Bit-Ports aus.
Weiterer Vorteil: mit steigender PWM-Auflösung musst Du mit keiner
zusätzlichen Rechenzeit rechnen.
Gruß, Stefan
Eine eigene Frage?
Dieser Thread ist über 10 Jahre alt.
Stell sie in einem eigenen Thread – dort lesen mehr Leute mit, und sie wird öfter und schneller beantwortet.