Forum: Mikrocontroller und Digitale Elektronik STM32F0 Stromverbrauch im Stop Mode


von beema (Gast)


Angehängte Dateien:

Lesenswert?

Ich habe hier einen STM32F030F4P6 (TSSOP20-Gehäuse), mit dem ich gerade 
ein paar Versuche mit den Low-Power Modi mache. Speziell interessiert 
mich der Stop-Mode.

Laut Datenblatt (siehe Anhang) sollte im Stop-Mode mit dem 
Spannungsregler im Low-Power Mode die Stromaufnahme bei max. 32 µA (IDD) 
und 3,5 µA (IDDA mit eingeschaltetem VDDA Monitoring) liegen. Insgesamt 
also im Worst-Case 35,5 µA.

Zur Aufnahme der Messwerte sagt das Datenblatt folgendes:
[i]The MCU is placed under the following conditions:
• All I/O pins are in analog input mode
• All peripherals are disabled except when explicitly mentioned
• The Flash memory access time is adjusted to the fHCLK frequency:
– 0 wait state and Prefetch OFF from 0 to 24 MHz
– 1 wait state and Prefetch ON above 24 MHz
• When the peripherals are enabled fPCLK = fHCLK
The parameters given in Table 25 to Table 27 are derived from tests 
performed under ambient temperature and supply voltage conditions.[/i]

In dem unten angegebenen Code habe ich alle GPIOs im Analog Mode 
konfiguriert, mit Ausnahme von GPIOD. Sobald ich in dieses Register 
einen Wert schreibe, landet der µC laut Debugger im HardFault_Handler, 
vermutlich, weil der F4P6 gar keine PD-Pins hat (PC-Pins hat er aber 
eigentlich auch nicht und hier funktioniert alles). Der Flash ist nach 
dem Reset standardmäßig mit 0 wait states und Prefetch off konfiguriert. 
Alle Takte, die ich während dem Programmablauf aktiviere, deaktiviere 
ich vor dem Wechsel in den Stop-Mode wieder.

Wenn ich nun mit einem Multimeter den Strom in VDD + VDDA messe ('A' in 
Schaltplanskizze), erhalte ich einen Wert von 155 µA, was mir deutlich 
zu viel erscheint. Dazu kommt, dass die Werte, die ich oben aus dem 
Datenblatt zitiert habe, als Maximalwerte bei 85°C angegeben sind. Ich 
vermute daher, dass irgendwas in meinem Code nicht stimmt und ich doch 
noch irgendwo einen Energiefresser habe. Auch ein anderes Multimeter 
zeigt einen ähnlichen Wert (150 µA).

Hier der verwendete Code:
1
#include "stm32f0xx.h"
2
3
#define WFI 1
4
#define WFE 2
5
#define LOW_POWER 1
6
#define NORMAL 2
7
8
void PWR_Enter_Stop_Mode(uint8_t mode, uint8_t Regulator_State);
9
10
int main(void)
11
{
12
  //Takt für GPIOs aktivieren
13
  RCC->AHBENR |= RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIOCEN | RCC_AHBENR_GPIODEN | RCC_AHBENR_GPIOFEN;
14
  
15
  //Alle GPIOs in analogen Modus schalten
16
  GPIOA->MODER = 0xFF;
17
  GPIOB->MODER = 0xFF;
18
  GPIOC->MODER = 0xFF;
19
  //GPIOD->MODER = 0xFF; //Springt zu HardFault_Handler im Startup-Code, egal, welcher Wert geschrieben wird
20
  GPIOF->MODER = 0xFF;
21
  
22
  //Takt für GPIOs deaktivieren
23
  RCC->AHBENR &= ~(RCC_AHBENR_GPIOAEN | RCC_AHBENR_GPIOBEN | RCC_AHBENR_GPIOCEN | RCC_AHBENR_GPIODEN | RCC_AHBENR_GPIOFEN);
24
  
25
  PWR_Enter_Stop_Mode(WFI,LOW_POWER);
26
  
27
  while(1)
28
  {
29
  }
30
}
31
32
void PWR_Enter_Stop_Mode(uint8_t Mode, uint8_t Regulator_State) //Wechselt vom Run-Mode in den Stop-Mode
33
{
34
  RCC->APB1ENR |= RCC_APB1ENR_PWREN; //Takt für PWR-Einheit aktivieren
35
  SCB->SCR |= SCB_SCR_SLEEPDEEP_Msk; //SLEEPDEEP-Bit setzen, damit der µC in den Stop-Mode wechselt
36
  PWR->CR &= ~PWR_CR_PDDS; //PDDS-Bit löschen, damit in den Stop-Mode gewechselt wird (und nicht in den Standby-Mode)
37
  PWR->CR |= PWR_CR_CWUF; //WUF-Flag im PWR_CSR Register löschen, damit der µC nicht direkt wieder aufwacht
38
  while((PWR->CSR & PWR_CSR_WUF) == PWR_CSR_WUF); //Warten, bis das Flag gelöscht ist
39
  
40
  if(Regulator_State == LOW_POWER)
41
  {
42
    PWR->CR |= PWR_CR_LPDS; //LPDS-Bit setzen, damit der Spannungsregler in einen Low-Power Modus während des Stop-Mode wechselt
43
  }
44
  else
45
  {
46
    PWR->CR &= ~PWR_CR_LPDS; //LPDS-Bit löschen, damit der Spannungsregler normal weiterläuft
47
  }
48
  
49
  RCC->APB1ENR &= ~RCC_APB1ENR_PWREN; //Takt für PWR-Einheit deaktivieren
50
  
51
  if(Mode == WFI)
52
  {
53
    __WFI(); //Wait for Interrupt
54
  }
55
  else
56
  {
57
    __WFE(); //Wait for Event
58
  }
59
}

Vielleicht kennt sich einer mit den Low-Power Modi des STM32 aus und 
weiß, wo der Wurm drin steckt.
Den Stromverbrauch messe ich mit abgestecktem ST-Link, lasse ich den 
ST-Link angesteckt, dann liegt der Stromverbrauch bei knapp 800 µA.
Mit WFE erhalte ich dasselbe Ergebnis wie mit WFI.

Danke für eure Antworten.

von Bauform B. (bauformb)


Lesenswert?

beema schrieb:
> //Alle GPIOs in analogen Modus schalten
>   GPIOA->MODER = 0xFF;
>   GPIOB->MODER = 0xFF;
>   GPIOC->MODER = 0xFF;
>   //GPIOD->MODER = 0xFF; //Springt zu HardFault_Handler im Startup-Code,
> egal, welcher Wert geschrieben wird
>   GPIOF->MODER = 0xFF;

Die MODE-Register haben 32 Bit, je 2 Bit pro Pin. Wenn du wirklich 
alle GPIO-Pins analog haben willst, musst du 0xFFFFFFFF schreiben. So 
schaltest du die Px0 bis Px3 auf analog und Px4 bis Px15 auf Input. Laut 
Schaltplan sind viele Pins offen und offene Inputs machen seltsame 
Dinge, da sind 150uA schon sehr erfreulich ;)

Der Chip hat wirklich keinen Port D, aber es gibt ihn auch in größeren 
Gehäusen. Dann sind ein paar Pins vom Port C verfügbar.

Am NRST fehlt ein 100n Kondensator, dafür kannst du den 10k auch 
weglassen.

: Bearbeitet durch User
von beema (Gast)


Lesenswert?

Danke für die schnelle Antwort!

Bauform B. schrieb:
> Wenn du wirklich
> alle GPIO-Pins analog haben willst, musst du 0xFFFFFFFF schreiben.
Super, genau das war das Problem! Mit 0xFFFFFFFF in allen 
MODER-Registern (mit Ausnahme von GPIOD) erreiche ich jetzt einen 
Stromverbrauch von 6 µA im Stop-Mode, das deckt sich mit den Angaben im 
Datenblatt.
Ich weiß, alle Pins im Analog Mode macht nicht wirklich viel Sinn, aber 
ich wollte mit dem Programm einfach mal testen, ob ich auf den im 
Datenblatt angegeben Stromverbrauch komme, wenn ich alle Bedingungen aus 
dem Datenblatt einhalte.

Ich glaube, da wäre ich jetzt noch ewig davor gesessen, bis ich den 
Fehler gefunden hätte - manchmal hat man einfach Tomaten auf den Augen.

Bauform B. schrieb:
> Am NRST fehlt ein 100n Kondensator, dafür kannst du den 10k auch
> weglassen.
Danke für den Hinweis, dann werde ich das in Zukunft so handhaben. Ich 
sehe gerade, bei den Nucleo-Boards findet sich dort auch nur ein 
Kondensator und kein Widerstand.

Danke nochmal für die schnelle Hilfe und noch einen schönen Abend! :-)

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.