Forum: Mikrocontroller und Digitale Elektronik Rechnen auf dem microcontroller/DSP (embedded C)


von Alexander (Gast)


Lesenswert?

Hi Leute,
Mein Wissen bezüglich uC begrenzt sich auf die Basics wie z.B. 
interrupts, PWM etc. Ich möchte aber gerne verstärkt mit digitaler 
Regelung zu tun haben, und benötige dafür nun mehr Kenntnisse im Bereich 
uC Berechnungen.

Mein größter Erfolg hinsichtlich uC war eine einfache Implementierung 
einer Sinus PWM mittels DDS. Funktionierte soweit auch ganz 
zufriedenstellend für meine Ansprüche.

Nachdem ich nun den Code von jemanden gesehen habe, der im Bereich 
embedded C arbeitet, komme ich ein wenig ins Straucheln. Anbei ein 
Auszug:
1
volatile uint32_t phase;
2
int16 t_A;
3
uint32_t phase_a = 0L;
4
uint16_t index_a;
5
int16  *sin_table = (signed int *)0x3FE000; ///< ptr to sine table in boot ROM
6
int16 phase_offset;      ///< round off amount from sine lookup
7
int16 val_diff; ///< interpolation temp variable
8
int16 val_lo; ///< interpolation temp variable
9
int16 sin_val; ///< interpolated sine table value
10
#define PHASE_180        (uint32_t)(4294967296.0/2.0 + 0.5)
11
12
// Dann viel Code hier...
13
14
15
  index_a=(phase_a>>22)|0x0001; // to access high word of 32 bit sine table
16
  phase_offset = (phase&0x007F0000L)>>16;
17
18
  // interpolate more accurate sin value
19
  val_lo = sin_table[index_a];
20
  val_diff = sin_table[index_a+2] - val_lo;
21
  sin_val = val_lo + (int16)(((int32)phase_offset*(int32)val_diff)>>7);
22
23
  t_A = (int16)(((int32)M*(int32)(sin_val))>>8);
24
25
  bla1=(int16)(((int32)t_A*(int32)PRD)>>14);

Was mir einige Schwierigkeiten bereitet, sind die Berechnungen. Z.B.:
1
sin_val = val_lo + (int16)(((int32)phase_offset*(int32)val_diff)>>7);
Es finden zunächst 2 castings statt: phase_offset und val_diff werden zu 
int32 variablen gesetzt und dann multipliziert. Das Ergebnis wird durch 
7 geteilt (die letzten 7 Bits des Ergebnisses entsprechen den 
Nachkommastellen???) Das Ergebnis wird dann zu int16 gecastet und zu 
val_lo addiert.

Verstehe ich den Code soweit richtig?

Der verwendete uC ist übrigens der TMS320F28027F mit einem 32bit 
Prozessor.

Meine Frage an euch ist nun:
Kennt ihr eine gute und praxisnahe Referenz, die sich mit dem Umgang mit 
uC Berechnungen befasst? Für euch ist der o.g. Code sicherlich einfach 
zu schreiben, für mich ist diese Bit-Schubserei aber ein wenig 
verwirrend und wäre sicherlich nicht von alleine darauf gekommen.

Vielen Dank an alle

von Patrick B. (p51d)


Lesenswert?

Alexander schrieb:
> as Ergebnis wird durch
> 7 geteilt (die letzten 7 Bits des Ergebnisses entsprechen den
> Nachkommastellen???) Das Ergebnis wird dann zu int16 gecastet und zu
> val_lo addiert.

Das Schieben um 7 Stellen nach rechts teilt die Zahl durch 128, und 
nicht durch 7!

Da man nicht sieht, woher hier die Werte kommen (z.B. phase) ist es auch 
nur ein raten. Ich vermute mal, dass hier eine Trapez-Interpolation von 
einer gegebenen Sinus-Tabelle gemacht wird. Da wird der nächste Wert 
einfach zwischen den Stützpunkten linearisiert.
Aber dieser Teil hier scheint mir somit nicht richtig zu sein:
1
val_diff = sin_table[index_a+2] - val_lo;
Mehr Sinn würde "index_a+1" machen.

Rechnen mit uC ist eigentlich nicht sooo schwer. Wenn keine FPU zur 
Verfügung steht, muss man sich halt Nachkommastellen durch geeignetes 
Multiplizieren "erschaffen" (für Rundungsfehler), welche am Schluss 
wieder wegdividiert werden. Sehr schnelle Multiplikationen und 
Divisionen sind immer Faktor 2,4,8,... da hier die operation durch einen 
Schiebebefehl ausgeführt wird.

von m.n. (Gast)


Lesenswert?

Alexander schrieb:
> Nachdem ich nun den Code von jemanden gesehen habe, der im Bereich
> embedded C arbeitet, komme ich ein wenig ins Straucheln. Anbei ein
> Auszug:

Dein Straucheln ist nicht schlimm. Der gezeigte Code ist ein gutes 
Beispiel für schlechte Programmierung. Der Urheber wird ihn dank 
fehlender Kommentare wohl selber nicht mehr lesen können.

Die Schiebeoperationen, die eine vermeintliche Divison sparen sollen, 
sind von vorvorgestern. Aktuelle Compiler optimieren selber, sodaß man 
einfach schreibt: wert = wert/128.

Alexander schrieb:
> Ich möchte aber gerne verstärkt mit digitaler
> Regelung zu tun haben, und benötige dafür nun mehr Kenntnisse im Bereich
> uC Berechnungen.

Dann sieh Dir Code an, der lesbar ist und an dem Aufgabe und Lösung 
nachvollziehbar sind. Wenn Fließkomma gerechnet werden muß, dann mache 
es, und fange nicht damit an, irgendwelche Optimierungen einbringen zu 
müssen. Die absolute Rechengeschwindigkeit ist fürs erste Verständnis 
unerheblich und aktuelle µCs sind von Hause aus schon sehr schnell.

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.