RMS über 8192 Werte auf MSPF149 sehr langsam

OP (Firma: keine) #1806167
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?
1
unsigned int RMS_SIG1;
2
unsigned long long int SUM_SIG1;
3

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

20
}
21

22
#pragma vector=ADC12_VECTOR
23
__interrupt void ADC12ISR (void)
24
{
25
  unsigned long int MW_SIG1,ADC_SIG1;
26

27
  
28
  if(i<8192){
29
    ADC_SIG1=ADC12MEM0;
30
    ADC_SIG1*=ADC_SIG1;                        //Quadrat
31
    SUM_SIG1=SUM_SIG1+ADC_SIG1;                //Summe
32
    j++;                                    //counter of ADC conversions
33
  }else{
34
    MW_SIG1=SUM_SIG1/j;                     //Mean of RMS
35
    RMS_SIG1=julery_isqrt(MW_SIG1);         //sqrt of RMS
36
    SUM_SIG1=0;
37

38
    i=0;
39
    j=0;
40
  }
41
   ADC12CTL0 &= ~ENC;                         // Enable conversions
42
}
#1806186
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?
OP (Firma: keine) #1807025
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
1
ADC_SIG1*=ADC_SIG1 //Quadrat
2

3
mov.w R6,R12
4
mov.w R7,R13
5
mov.w R6,R14
6
mov.w R7,R15
7
call #?Mul32HW
8
mov.w R12,R6
9
mov.w R13,R7

Kommt mir komisch vor im Usergiude von TI zum F149 steht was von
1
16x16 Unsigned Multiply Accumulate
2
MOV #01234h,&MAC ; Load first operand
3
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?
1
P5SEL |= 0xFF;

Jetzt hab ich auf MCLK und SMCLK 1,5MHZ.
OP (Firma: keine) #1807067
Lesenswert?

1
?Mul32Hw
2

3
push.w SR
4
dint
5
nop
6
mov.w R12,&MPY
7
mov.w R14,&OP2
8
mov.w  R12,&MAC
9
mov.w &RESLO,R12
10
mov.w &RESHI, &RESLO
11
mov.w R15,&OP2
12
mov.w R13,&MAC
13
mov.w R14,&OP2
14
mov.w &RESLO,R13
15
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.
Gast #1807071
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 :-(
#1807075
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.
OP (Firma: keine) #1807390
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.
Angehängte Dateien:
Gast #1807672
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 :-)
Persönliche Seite #1807803
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
Gast #1811297
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

Bitte melde dich an, um einen Beitrag zu schreiben.

oder

Mit Google-Account einloggen

Die Registrierung ist kostenlos und dauert nur eine Minute.

Jetzt registrieren