www.mikrocontroller.net

Forum: Mikrocontroller und Digitale Elektronik RMS über 8192 Werte auf MSPF149 sehr langsam


Autor: Fabian Hof (Firma: keine) (eimer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi Leute,

ich hab mir ein kleines Programm geschrieben das mir den RMS über 8192 
Werte in der Sekunde berechnen sollte.

Jetzt dauert die Berechnung insgesamt ca. 5 Sekunden ist das normal?

Also wenn ich die Wurzelfunktion draussen lass verändert sich nichts 
spürbar, bei der Multiplikation gewinne ich ca. 2 Sekunden.
Der msp430 hat doch ein Hard. Multiplier das sollte doch raz faz gehen.
Ich seh jetzt nicht ganz den Zeitfresser?

Der Timer A3 hat ja eine niedrigere Priorität wie der ADC12, deshalb 
arbeitet der auch alles ab was im ADC gemacht werden soll.

Bin etwas ratlos, kann mir vll. jemand ein tip geben woran das liegen 
kann?
unsigned int RMS_SIG1;
unsigned long long int SUM_SIG1;

#pragma vector=TIMERA0_VECTOR
__interrupt void Timer_A (void)
{
  i++;
  P4OUT ^= 0xFF;                            // Toggle P1.0
  P6SEL |= 0x70;                            // Enable A/D channel A0
  ADC12CTL0 = ADC12ON+SHT0_0+MSC;           // Turn on ADC12, set sampling time
  ADC12CTL1 = SHP+CONSEQ_1;                 // Use sampling timer, set mode
  ADC12MCTL0 = INCH_4+SREF_0;               // channel = A4
  ADC12MCTL1 = INCH_5+SREF_0;               // channel = A5
  ADC12MCTL2 = INCH_6+EOS+SREF_0;           // channel = A6
  ADC12IE = 0x01;                           // Enable ADC12IFG.6
  //ADC12MCTL0 = EOS+INCH_0+SREF_0;
  ADC12CTL0 |= ENC;                         // Enable conversions
  ADC12CTL0 |= ADC12SC;                     // Start conversion

}

#pragma vector=ADC12_VECTOR
__interrupt void ADC12ISR (void)
{
  unsigned long int MW_SIG1,ADC_SIG1;

  
  if(i<8192){
    ADC_SIG1=ADC12MEM0;
    ADC_SIG1*=ADC_SIG1;                        //Quadrat
    SUM_SIG1=SUM_SIG1+ADC_SIG1;                //Summe
    j++;                                    //counter of ADC conversions
  }else{
    MW_SIG1=SUM_SIG1/j;                     //Mean of RMS
    RMS_SIG1=julery_isqrt(MW_SIG1);         //sqrt of RMS
    SUM_SIG1=0;

    i=0;
    j=0;
  }
   ADC12CTL0 &= ~ENC;                         // Enable conversions
}

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Naja, die Frage ist, ob der Kompiler automatisch den HW-Mult 
benutzt....das solltest du anhand des Assembler-Listings oder der 
Kompiler-Optionen erst mal prüfen.

Das Teilen durch j ist natürlich auch ein Zeitfresser....

Autor: Karl Heinz (kbuchegg) (Moderator)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Fabian Hof schrieb:

> Also wenn ich die Wurzelfunktion draussen lass verändert sich nichts
> spürbar, bei der Multiplikation gewinne ich ca. 2 Sekunden.

?
Hast du den Optimizer eingeschaltet.
Das kann ich mir nur schwer vorstellen, dass tatsächlich das bischen 
Rechnerei bei einem ADC Ergebnis so dermassen zeitbestimmend sein soll.

Hast du vielleicht noch andere, höher priorisierte Interrupts am laufen, 
die dem ADC Interrupt keine oder kaum Rechenzeit übrig lassen?

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hier 'MW_SIG1=SUM_SIG1/j;' besser eine Shiftanweisung verwenden.

MW_SIG1 = SUM_SIG1 >> 13 ;

Controller zu langsam getaktet?

Autor: Fabian Hof (Firma: keine) (eimer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi,

so hab mal bitshift reingemacht, hätte ich auch selber drauf kommen 
können. Geht soweit auch ohne Probleme.

Zum Thema Hardware Multiplier, wenn mir einer genau sagt wie ich das 
einstell bei der IAR Workbench mach ich das rein. Ich hab halt gelesen 
das er den automatischbenutz sofern es möglich ist.
Hier mal der Assembler-COde für die Multiplikation
ADC_SIG1*=ADC_SIG1 //Quadrat

mov.w R6,R12
mov.w R7,R13
mov.w R6,R14
mov.w R7,R15
call #?Mul32HW
mov.w R12,R6
mov.w R13,R7

Kommt mir komisch vor im Usergiude von TI zum F149 steht was von
16x16 Unsigned Multiply Accumulate
MOV #01234h,&MAC ; Load first operand
MOV #05678h,&OP2 ; Load 2nd operand
davon ist nichts zu finden.

Zum Thema Interrupts:
Ich hab nur die beiden Interrupts die ihr oben in meinem ersten Poste 
seht laufen. Also sollte mir da nicht reinhageln.

Thema Takt:
Also ich muss sagen da hab ich garnichts eingestellt, ich bin davon 
ausgegangen, das er automatisch auf 5 Mhz läuft bzw.
Wie kann ich mir nochmal MCLK auf PIN5.4 anschauen?
Stimmt das so?
P5SEL |= 0xFF;

Jetzt hab ich auf MCLK und SMCLK 1,5MHZ.

Autor: Martin (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
... call #?Mul32HW ...

Diese Routine könnte der Knackpunkt sein, dahinter ist u. U. eine 
längeres Programm verborgen. Poste doch mal die Routine.

Autor: Fabian Hof (Firma: keine) (eimer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
?Mul32Hw

push.w SR
dint
nop
mov.w R12,&MPY
mov.w R14,&OP2
mov.w  R12,&MAC
mov.w &RESLO,R12
mov.w &RESHI, &RESLO
mov.w R15,&OP2
mov.w R13,&MAC
mov.w R14,&OP2
mov.w &RESLO,R13
reti

Sieht nach HW multiplizierer aus also, da hab ich kein Zweifel.

Kann ich mir in der IAR genau anzeigen lassen wieviel Zeit eine 
Operation verschlingt? Dann könnte man das mal eingrenzen.

Beibt wohl nur noch den Takt Hochzusetzen auf 5 MHZ dann sollte ich 
Faktor 3 gewinnen.

Autor: Ferkel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>  unsigned long int MW_SIG1,ADC_SIG1;

eine 16-Bit MUL kann nur dann verwendet werden, wenn die Variable auch 
16-Bit breit ist. Du definierst aber ADC_SIG1 als unsinged long.

>#?Mul32HW

Diese Routine steht in einer .lib. Die Quelle dürfte verborgen sein :-(

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn du am DCO nix änderst, läuft der mit irgendeiner Standard-Frequenz, 
die im Datenblatt steht. Aber ADC Messungen mit dem DCO...naja, würd ich 
nicht machen, das ist ein relativ instabilder RC-Oszillator. Wenn du die 
Betriebsspannung auf 3,6V anhebst, kannst du einen 8MHz Quarz 
anschließen. Bei 3,3V gehts bis 7,4MHz stabil.
Ansonsten scheint er ja den HW Mult zu benutzen.

Autor: Fabian Hof (Firma: keine) (eimer)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der ADC wir von einem externen 32kHz Quarz getacktet also DCO kann ich 
beliebig wählen.
Hat wer vll. die einstellungen für maximalen Takt vom F149 ?

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Aus den Code-Beispielen von TI:
DCOCTL = DCO0 + DCO1 + DCO2;              // Max DCO

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Christian R. schrieb:
> Aus den Code-Beispielen von TI:
> DCOCTL = DCO0 + DCO1 + DCO2;              // Max DCO

Naja...
ein zusätzliches
BCSCTL1 |= RSEL0 + RSEL1 + RSEL2;
wär vielleicht auch nicht schlecht ;-)

Autor: Guest (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann es sein, dass deine RMS deshalb so lange braucht, weil du den ADC 
mit 32KHz taktest, der ist normalerweise mit 5MHz spezifiziert.

Autor: Christian R. (supachris)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hehe, wieder mal nur eine Zeile erwischt beim Copy-Paste ;)
Das sorgt doch immer noch für die schönsten Effekte beim 
"Programmieren".

Autor: Fabian Hof (Firma: keine) (eimer)
Datum:
Angehängte Dateien:

Bewertung
0 lesenswert
nicht lesenswert
Top! Hab jetzt mal sichergestellt das der CLock auf  ~4.6Mhz und den ADC 
betreib ich jetzt mit ADC12OSC, das sollte ja der maximale sein.

Aber mal eine Frage:
Wenn ich die MIttelwertbildung und das Wurzelziehen im Main mache sollte 
ich doch keine Probleme bekommen, ausser natürlich das dauert länger als 
das meine 8192 Abtastwerte voll sind oder?
Das hab ich jetzt mal so versucht, siehe Anhang.

Leider springt er mir die while nie wieder an ausser beim ersten Aufruf, 
hat einer eine Idee warum?

Langsam krieg ich totes Hirn, für heute.

Autor: Stefan (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Du musst bei Measure==1 in der ISR ja auch LPM0 deaktivieren, damit er 
überhaupt in main hupfen kann

Autor: Peter Dannegger (peda)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Wenn das long long genauso implementiert ist, wie beim AVR-GCC, dann ist 
es schneckenlahm. Da ist sogar float noch besser.

Am besten, Du bastelst Dir das long long aus 2 uint32_t selber.



Peter

Autor: Ferkel (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
>Wenn das long long genauso implementiert ist, wie beim AVR-GCC, dann ist
>es schneckenlahm. Da ist sogar float noch besser.

Darum geht es doch garnicht. Offensichtlich muß nur der ADC schneller 
laufen, damit die CPU schneller rechnet :-)

Autor: Falk Brunner (falk)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Kann man leicht messen. Am Anfang der ISR ein Pin auf High setzen, am am 
Ende auf LOW. Oszi dran, messen. Dann sieht man,

den Abstand der Pulse = ADC Wandlertakt.
Die Breite der Pulse. Rechenzeit in der ISR
Das Tastverhältnis = CPU -Auslastung

MfG
Falk

Autor: Peter Diener (pdiener) Benutzerseite
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Der Hardwaremultiplizierer kann nur maximal 16 bit x 16 bit berechnen.
ADC_SIG1 ist unsigned long int und daher 32 bit breit (oder ist das beim 
IAR Compiler anders?).

ADC_SIG1=ADC12MEM0;
ADC_SIG1*=ADC_SIG1;                        //Quadrat
SUM_SIG1=SUM_SIG1+ADC_SIG1;                //Summe

Das würde ich so schreiben:

SUM_SIG1 += ADC12MEM0 * ADC12MEM0;

Was ist das eigentlich für eine umständliche Vorgehensweise mit dem i 
und j? Letztenendes will man doch samples zählen, das macht man am 
einfachsten direkt im ADC-Interrupt.

Wofür zählt j mit, der Wert, den es bei der Auswertung haben wird, ist 
doch zur Compilezeit bekannt (8192)?


Grüße,

Peter

Autor: Fabian Hof (Gast)
Datum:

Bewertung
0 lesenswert
nicht lesenswert
Hi tip von Stefan mit LPM0 deaktivieren hat gepasst.
Klar kann er auch 32 bit mit dem HW Multiplier machen nur nicht auf 
einmal. Aber die ganze Sache läuft jetzt auch soweit so gut.

Peter das j war noch aus einer früheren Version, ist natürlich bekannt 
und mitlerweile auch verschwunden.
Ausserdem sollte man ADC_SIG1=ADC12MEM0; und dann SUM_SIG1 += ADC_SIG1 * 
ADC_SIG1; machen sonst kommt ein volatile warning.

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [avrasm]AVR-Assembler-Code[/avrasm]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.