Forum: Mikrocontroller und Digitale Elektronik Stromaufnahme uC - unklares Verhalten bei verschiedenen Aktionen


von Dennis (Gast)


Lesenswert?

Guten Morgen liebe Gemeinde.

Ich hoffe, hier ist vielleicht jemand, der mir bei meinem Problem helfen 
kann. Ich arbeite gerade mit einem MSP430FR6989 und versuche, den 
Stromverbrauch auf ein Minimum zu drücken - mein Ziel ist etwas in der 
Gegend von 300uA, aber ich kann gerade das Verhalten des uCs nicht ganz 
nachvollziehen. Taktfrequenz 2.67MHz vom internen DCO für MCLK und 
SMCLK, sowie der interne VLO für ACLK mit 10kHz.

Ich habe fünf Taster (P6.0 bis P6.4) und 5 LEDs (P6.5, P6.6, P2.4, P2.5, 
P2.6). Die Taster ziehen die Input-Pins auf Masse. Es sind externe 
Pull-Ups dran mit 220k. Die Versorgung liegt bei 3,3V. Ein Tastendruck 
erzeugt somit ca. 15uA zusätzlichen Strom auf Grund des Pull-Ups. Die 
Ausgänge für die LEDs gehen auf das Gate eines N-MOSFETS, welcher dann 
die LEDs treibt (diese werden aus einer anderen Spannungsquelle 
versorgt, damit mir die leuchtenden LEDs die Stromaufnahme des 
Prozessors nicht verfälschen).

Die Initialisierung der relevanten Portpins ist einfach folgende:
1
P2SEL0  = 0x00;
2
P2SEL1  = 0x00;
3
P2OUT   = 0x00;
4
P2DIR   = ( 0x10 | 0x20 | 0x40 );
5
6
P6SEL0  = 0x00;
7
P6SEL1  = 0x00;
8
P6OUT   = 0x00;
9
P6DIR   = ( 0x20 | 0x40 );
10
11
PM5CTL0 &= ~LOCKLPM5; // Enable Portpins
Die restlichen Pins sind auf Ausgang und 'low' konfiguriert, damit sie 
nicht floaten.

Derzeit macht mein Programm nicht viel. Es sieht folgendermaßen aus:
1
volatile uint16_t var_counter = 0;
2
3
while( 1 )
4
{
5
  var_counter++;
6
7
  if( !(P6IN & 0x01) ) P6OUT |= 0x20;
8
  else P6OUT &= ~0x20;
9
10
  if( !(P6IN & 0x02) ) P6OUT |= 0x40;
11
  else P6OUT &= ~0x40;
12
13
  if( !(P6IN & 0x04) ) P2OUT |= 0x10;
14
  else P2OUT &= ~0x10;
15
16
  if( !(P6IN & 0x08) ) P2OUT |= 0x20;
17
  else P2OUT &= ~0x20;
18
19
  if( !(P6IN & 0x10) ) P2OUT |= 0x40;
20
  else P2OUT &= ~0x40;
21
}
Mein Programm verbraucht in diesem Zustand 411uA.

Erste Frage ist folgende: Ich hatte die Abfrage der Input-Pins vorher 
anders (hier nur einer als Beispiel, analog dazu alle anderen):
1
if( ~P6IN & 0x01 ) P6OUT |= 0x20;
2
else P6OUT &= ~0x20;
Diese Abfrage verbraucht komischerweise 110uA mehr Strom. Aber wo ist 
der Unterschied? Ich komme einfach nicht drauf. Hier nehme ich doch nur 
das Komplement des Input-Registers, was mit bei gedrücktem Taster eine 
'1' liefert und das Register dann AND 0x01, wodurch ich den Tastendruck 
an P6.0 erkenne.

Desweiteren habe ich festgestellt, dass wenn ich alle Tasterabfragen und 
LED-Anzeigen auskommentiere, also nur die Variable hochzähle, der 
Stromverbrauch bei 236uA liegt. Das wäre natürlich ein schöner Wert.

Schalte ich jetzt eine Tasterabfrage mit LED-Ausgabe dazu [Variante: 
!(P6IN & 0x10)], dann geht der Stromverbrauch auf 241uA hoch, was an 
sich schon seltsam ist, da selbst der gedrückte Taster für sich ca. 15uA 
braucht. Aber gut, die paar uA schwanken auch von mal zu mal.

Frage ich jetzt Taster 1 und 2 ab, also hintereinander direkt zweimal 
der Zugriff auf das Input-Register, dann liegt der Stromverbrauch bei 
426uA.

Alle fünf Abfragen verbrauchen 473uA. Der Sprung zwischen zwei und fünf 
Abfragen ist also nicht mehr so groß.

Jetzt habe ich noch ausprobiert, das gesamte P6IN-Register in eine 
Variable zu kopieren und dann alle Abfragen mit dieser Variable zu 
machen.
1
if( ~input_reg & 0x01 ) P6OUT |= 0x20;
2
else P6OUT &= ~0x20;
3
4
...
Ergebnis: 391uA - und hier ist es umgekehrt mit den zwei 
Abfragevarianten, denn
1
if( !(input_reg & 0x01) ) P6OUT |= 0x20;
2
else P6OUT &= ~0x20;
verbaucht hier mehr, nämlich 410uA.

So, jetzt meine zweite Frage: Ist der Registerzugriff so stromfressend 
in einem uC (klar, wir reden hier von uA, aber das macht in der 
Gesamtbetrachtung ja schon eine Menge aus)? Ich habe noch testweise ein 
Delay zwischen die Abfragen gemacht, damit der Zugriff weniger häufig 
auftritt, was tatsächlich den Verbrauch verringerte, wenn auch nur 
marginal.

Hat jemand einen Tip, wie ich die Sache ggf. noch anders angehen kann? 
Ich meine, ohne Registerzugriffe geht es nicht, nur wieso ist einer noch 
so im Rahmen und bei 2+ geht der Stromverbrauch so in die Höhe?

Gruß und danke,

Dennis


P.S.: Ich habe diese Thematik auch im E2E-Forum gestellt, aber dort bis 
jetzt auch noch keine Antwort und ich glaube die schlafen auch noch alle 
;-)

von Peter K. (Gast)


Lesenswert?

Dennis schrieb:
> So, jetzt meine zweite Frage: Ist der Registerzugriff so stromfressend
> in einem uC

der Register Zugriff nicht aber der zugriff auf den SRAM bzw das 
schreiben auf den SRAM

Wegen deinen zwei Varianten für die erkennung der Tasterflanke, ich 
nehme an das kommt daher das die alu bitweises invertieren in einer 
anderen schaltung macht wie logisches invertieren.

Dennis schrieb:
> Ich meine, ohne Registerzugriffe geht es nicht, nur wieso ist einer noch
> so im Rahmen und bei 2+ geht der Stromverbrauch so in die Höhe?

Ich denke mal wenn du mehr implementierst gehen dem Prozessor die 
Register aus und er muss mehr SRAM zugriffe machen, schau dir einfach 
mal das Disassambly an, befehle wie push pop store load oder so ähnlich 
greifen auf den SRAM zu auch mov befehele können auf den SRAM zugreifen
Ich kennen den Controler nicht und kann daher aber nicht viel zu den 
Zugriffen im Assembler sagen.

Wenn du aber strom sparen willst ist das der falsche Ansatz, stromsparen 
macht man mit einem µC so dass man ihn in den sleep oder standby modus 
setzt wenn gerade nichts zu tun ist.
Sagen wir mal du willst den Tasterwert alle 200ms auslesen, dann setzt 
du einen Timer der den µC aufwecken kann auf 200ms und schickst den µC 
in den standby.
Der prozessor hört auf zu arbeiten und verbraucht keinen Strom, die 
peripherien (timer ports usw) aber verbrauchen immer noch strom, der 
stromverbrauch hängt hier davon ab wie viel in deinem jeweiligen modus 
noch eingschaltet ist, sollte im datenblatt stehen.
Nach den 200ms weckt der Timer den µC per interrupt auf, der µC prüft 
alle Inputs und geht wieder in den standby, während der kern arbeitet 
verbraucht deine schaltung zwar 500µA, aber das dauert ja nicht lange 
bis der Prozessor wieder in den standby geht, danach verbraucht er sagen 
wir mal 100µA für 200ms und dann wieder für kurze zeit 500µA

von Peter K. (Gast)


Lesenswert?

übrigens in deinem Code muss var_counter nicht volatile sein wenn du ihn 
nicht in Interrupts verwendest

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.