Forum: Mikrocontroller und Digitale Elektronik STPM32 - Register beschreiben..


von Jan H. (janiiix3)


Lesenswert?

Hallo in die Rund schmeiß

Eine "kleine" & "kurze" Frage..
Wie genau beschreibe ich eines der Register vom STMP32?
1
void stpm32x_write(uint8_t addr, uint32_t cmd){
2
3
  spi_select_low();
4
  spi_usartx_tx_rx(0x00); // Previously requested data byte LSB
5
  spi_usartx_tx_rx(addr); // Previously requested data byte 2 out of 4
6
  spi_usartx_tx_rx((cmd & 0x0000FF00)>>8 ); // Previously requested data byte 3 out of 4
7
  spi_usartx_tx_rx((cmd & 0x000000FF)    ); // Previously requested data byte MSB
8
  spi_select_high();  
9
  
10
  spi_select_low();
11
  spi_usartx_tx_rx(0x00); // Previously requested data byte LSB
12
  spi_usartx_tx_rx(addr+1); // Previously requested data byte 2 out of 4
13
  spi_usartx_tx_rx((cmd & 0xFF000000)>>24); // Previously requested data byte 3 out of 4
14
  spi_usartx_tx_rx((cmd & 0x00FF0000)>>16); // Previously requested data byte MSB
15
  spi_select_high();  
16
}

Also das lesen klappt.. Im Datenblatt steht so viel, dass ich gar nicht 
mehr durchsteige, wie ich ein Register beschreiben muss..

: Bearbeitet durch User
von Jan H. (janiiix3)


Lesenswert?

Keiner eine Idee..?

von Stefan F. (Gast)


Lesenswert?

Gegenfrage: Was ist ein STMP32 ?

Und warum heisst die Funktion "stpm32..."? Wobei ich mit STPM32 auch 
nichts anfangen kann.

Du meinst aber nicht STM32, oder?

von Jan H. (janiiix3)


Lesenswert?

Stefan U. schrieb:
> Gegenfrage: Was ist ein STMP32 ?
>
> Und warum heisst die Funktion "stpm32..."?

Ja, dass war heute morgen ein Dreher.

STPM32x heißt der kleine.

von Jan H. (janiiix3)


Lesenswert?

Stefan U. schrieb:
> Gegenfrage: Was ist ein STMP32 ?
>
> Und warum heisst die Funktion "stpm32..."? Wobei ich mit STPM32 auch
> nichts anfangen kann.
>
> Du meinst aber nicht STM32, oder?


Nein, die heißen wirklich so. Das ist ein Energy Monitor via. SPI.

von Jim M. (turboj)


Lesenswert?

Jan H. schrieb:
>> Du meinst aber nicht STM32, oder?
>
> Nein, die heißen wirklich so. Das ist ein Energy Monitor via. SPI.

Dann hätte man besser mal das Datenblatt verlinkt. Wir kennen den 
nämlich nicht.

von Jan H. (janiiix3)


Lesenswert?

Jim M. schrieb:
> Jan H. schrieb:
> Du meinst aber nicht STM32, oder?
>
> Nein, die heißen wirklich so. Das ist ein Energy Monitor via. SPI.
>
> Dann hätte man besser mal das Datenblatt verlinkt. Wir kennen den
> nämlich nicht.

Mist. Heute ist nicht mein Tag.

Hier der richtige Name und hier das Datenblatt.

http://www.st.com/en/data-converters/stpm32.html

von Stefan F. (Gast)


Lesenswert?

Hast du Kapitel 8.6 gelesen, und dazu eventuell konkrete Fragen?

von Jan H. (janiiix3)


Lesenswert?

Stefan U. schrieb:
> Hast du Kapitel 8.6 gelesen, und dazu eventuell konkrete Fragen?

Habe ich gelesen. Hast du etwa oben im Code einen Fehler gefunden?

von Jan H. (janiiix3)


Lesenswert?

Moin,

habe mich seit den letzten Tagen weiter mit dem "STPM32" beschäftigt.
Lesen kann ich die Register ohne Probleme ( es weichen zwar einige von 
ihren default Werten ab.. ).

Das schreiben klappt noch nicht.
Wenn ich das Register "0x24" lese, bekomme ich 0x4007 raus.
Das ist das " SPI / USART " Register. Dort ist auch das CRC Poly. 
enthalten. Ändere ich irgendein Bit davon, wird es nicht übernommen.

Kann evtl. mal jemand auf meine " schreib " Routine schauen?

Hiermit baue ich das Kommando zusammen..
1
void stpm32Write_( uint8_t addr , uint32_t cmd , bool crcEn )    
2
{
3
  uint8_t frameLow  []  = { 0xFF , addr    , ( cmd & 0x000000FF ) , ( ( cmd & 0x0000FF00) >> 8 ) , 0x00 };
4
  uint8_t frameHigh  []  = { 0xFF , addr + 1 , ( ( cmd & 0x00FF0000 ) >> 16 ) , ( ( cmd & 0xFF000000) >> 24 ) , 0x00 };
5
  
6
  for ( uint8_t x = 0 ; x < ( STPM32_FRAME_WITHOUT_CRC + crcEn ) ; x++ )
7
  {
8
    stpm32Tx[x][0] = frameLow[x];
9
    frameLow[STPM32_CRC] = stpm32Crc( frameLow[STPM32_CRC] , frameLow[x] );
10
  }
11
  stpm32SpiWrite( frameLow , ( STPM32_FRAME_WITHOUT_CRC + crcEn ) );
12
  
13
  
14
  for ( uint8_t x = 0 ; x < ( STPM32_FRAME_WITHOUT_CRC + crcEn ) ; x++ )
15
  {
16
    stpm32Tx[x][1] = frameHigh[x];
17
    frameHigh[STPM32_CRC] = stpm32Crc( frameHigh[STPM32_CRC] , frameHigh[x] );
18
  }
19
  stpm32SpiWrite( frameHigh , ( STPM32_FRAME_WITHOUT_CRC + crcEn ) );
20
}

Hier werden die Daten auf den Bus geschoben
1
static void stpm32SpiWrite( uint8_t *buff , size_t leng )      
2
{
3
  uint8_t x;
4
  
5
  STPM32_SYNC_PORT |= ( 1 << STPM32_SYNC_bp );
6
  _delay_ms( 50 );
7
  STPM32_SYNC_PORT &= ~( 1 << STPM32_SYNC_bp );
8
  _delay_ms( 50 );
9
  
10
  stpm32.spiSlaveSelect();
11
  _delay_ms(50);
12
  
13
  for ( x = 0 ; x < leng ; x++ )
14
  {
15
    stpm32.spiTxRx( buff[x] );
16
  }
17
  
18
  stpm32.spiSlaveDeSelect();
19
  _delay_ms(50);
20
}

von pegel (Gast)


Lesenswert?

Ist zwar HAL, d.h. du müsstest den Funktionen bis zu ihrer Definition 
folgen, aber ST bietet wie immer auch Programmbeispiele an:

https://www.st.com/content/st_com/en/products/embedded-software/evaluation-tool-software/stsw-stpm002.html

In der Datei metrology.c dürfte alles Nötige zu finden sein.

von Jan H. (janiiix3)


Lesenswert?

Danke.
Hatte ich mir schon angesehen. Leider steige ich da nicht ganz so 
durch..
Das ist sehr kompliziert geschrieben.

von Chris (Gast)


Lesenswert?

Interessanter Zufall, ich habe seit gestern auch einen STPM32 bzw das 
EVALSTPM32 bei mir und kann nach anfänglichen Schwierigkeiten (im SPI 
Modus starten) auch lesen.

Beim Schreiben werden die gesendeten Werte jedoch nicht übernommen.

Die Beispiele von ST sind leider wirklich sehr undurchsichtig, da diese 
sehr allgemein gehalten sind um auch mit mehreren verschiedenen STPMs zu 
laufen. Wirklich viel Code ist zum senden aber scheinbar eh nicht 
notwendig. Siehe z.B. metrology_hal.c, ab Zeile 844, Funktionen 
Metro_HAL_Stpm_write() und Metro_HAL_Stpm_read()

Aus deinem Programcode ist mir nicht ganz ersichtlich ob du die Daten 
mit oder ohne CRC-Byte sendest. Das könntest du mal versuchen. Wenn 
nämlich ein Datenpaket mit falschem oder fehlendem CRC Byte am STPM32 
ankommt, liefert dieser beim nächstem Lesezugriff den Inhalt von 
Register 0x00, nämlich 0x040000A0+CRC, soweit nicht geändert.

Mir ist zudem aufgefallen dass die Reihenfolge der MSB und LSB Bytes 
beim Senden etwas gewöhnungsbedürftig ist und vermute hier noch einen 
Fehler bei mir.

von Jan H. (janiiix3)


Lesenswert?

Bist du bei Skype?

von Chris (Gast)


Lesenswert?

Jan H. schrieb:
> Bist du bei Skype?

Leider nein, wieso?

Ich habe mein Problem aber mitlerweile gefunden, es lag an der 
auskommentierten CRC Berechnung beim Senden von Daten. Das ist mir nicht 
aufgefallen, da ich nur den CRC beim Empfangen ausgewertet und mit einer 
LED ausgegeben habe...

von Chris (Gast)


Lesenswert?

Anbei mein Code in Auszügen, der soweit auch funktioniert.
1
void Init_AC_Metro_SPI(void)
2
{
3
  // Enable SPI peripheral. Keep CS low for typical 10 ms after system startup (after VCC is asserted to the STPM32) to select SPI-communication
4
  HAL_GPIO_WritePin(SPI2_CS_GPIO_Port,SPI2_CS_Pin,GPIO_PIN_RESET);
5
  HAL_Delay(20);
6
  HAL_GPIO_WritePin(SPI2_CS_GPIO_Port,SPI2_CS_Pin,GPIO_PIN_SET);
7
  HAL_Delay(1);
8
9
  // Single pulse on CS rev BC (reset pulse)
10
  HAL_GPIO_WritePin(SPI2_CS_GPIO_Port,SPI2_CS_Pin,GPIO_PIN_SET);
11
  HAL_Delay(2);
12
  HAL_GPIO_WritePin(SPI2_CS_GPIO_Port,SPI2_CS_Pin,GPIO_PIN_RESET);
13
  HAL_Delay(1);
14
  HAL_GPIO_WritePin(SPI2_CS_GPIO_Port,SPI2_CS_Pin,GPIO_PIN_SET);
15
16
  // Wait 20 ms
17
  HAL_Delay(20);
18
19
  // Enable SPI
20
  __HAL_SPI_ENABLE(&hspi2);
21
}
22
23
// CRC Calculation handling for STPM32
24
#define CRC_8 (0x07)
25
#define AC_METRO_FRAME_LEN (5)
26
uint8_t CalcCRC8(uint8_t *pBuf)
27
{
28
  uint8_t i;
29
  uint8_t CRC_u8Checksum = 0;
30
  for (i = 0; i < AC_METRO_FRAME_LEN-1; i++)
31
  {
32
    uint8_t loc_u8Idx = 0;
33
    uint8_t loc_u8Temp;
34
    uint8_t u8Data = pBuf[i];
35
36
    while(loc_u8Idx < 8)
37
    {
38
      loc_u8Temp = u8Data ^ CRC_u8Checksum;
39
      CRC_u8Checksum <<= 1;
40
      if(loc_u8Temp & 0x80)
41
      {
42
        CRC_u8Checksum ^= CRC_8;
43
      }
44
      u8Data <<= 1;
45
      loc_u8Idx++;
46
    }
47
  }
48
  return CRC_u8Checksum;
49
}
50
51
void SPI_send_AC_metro(uint8_t* tx_data)
52
{
53
  // generate CRC for transmission
54
  tx_data[AC_METRO_FRAME_LEN-1] = CalcCRC8(tx_data);
55
56
  // reset CS-signal
57
  HAL_GPIO_WritePin(SPI2_CS_GPIO_Port,SPI2_CS_Pin,GPIO_PIN_RESET);
58
59
  // send and receive data via SPI
60
  HAL_SPI_Transmit(&hspi2, tx_data, AC_METRO_FRAME_LEN, 1000);
61
62
  // set CS-signal
63
  HAL_GPIO_WritePin(SPI2_CS_GPIO_Port,SPI2_CS_Pin,GPIO_PIN_SET);
64
}
65
66
int main()
67
{
68
    volatile uint8_t tx_data[AC_METRO_FRAME_LEN];
69
    // Initialize STPM32 AC metrology via SPI
70
    Init_AC_Metro_SPI();
71
72
73
    // write address 0x18 with 0x0F27 0327
74
    tx_data[0] = 0x18;  // read back all 32-bits of register
75
    tx_data[1] = 0x18;  // write 16-bit MSW of register
76
    tx_data[2] = 0x27;  // write LSB
77
    tx_data[3] = 0x03;  // write MSB
78
    send_AC_metro_with_CRC(tx_data);
79
80
    ++tx_data[0];  // read back all 32-bits of register
81
    ++tx_data[1];  // write 16-bit MSW of register
82
    tx_data[2] = 0x27;  // write LSB
83
    tx_data[3] = 0x0F;  // write MSB
84
    send_AC_metro_with_CRC(tx_data);
85
}

von Jan H. (janiiix3)


Lesenswert?

Okay. Du hast es für einen STM32 geschrieben oder?

von Jan H. (janiiix3)


Lesenswert?

Chris schrieb:
> tx_data[AC_METRO_FRAME_LEN-1] = CalcCRC8(tx_data);

Dumme Frage.. Wieso bennent man alles mit "METRO"? Das habe ich auch 
schon bei ST gesehen.

von Chris (Gast)


Lesenswert?

Jan H. schrieb:
> Du hast es für einen STM32 geschrieben oder?

Ja, bei mir ist es ein STM32F072

Jan H. schrieb:
> Dumme Frage.. Wieso bennent man alles mit "METRO"? Das habe ich auch
> schon bei ST gesehen.

Das soll die Abkürzung für "Metrology" sein, also die Messschaltung

von Chris (Gast)


Angehängte Dateien:

Lesenswert?

Ich habe aktuell ein weitere Problem mit dem STPM32. Das Beschreiben der 
Konfiguration und Auslesen der Messwerte per SPI klappt. Die RMS 
Spannung lässt sich ebenfalls auf den eingestellten Wert (=10 VAC RMS 
durch Trenntrafo) ermitteln.

Der Strom von 100 mA (AC RMS), dessen roher ADC Wert im gleichen 
Register wie die Spannung steht, springt jedoch extrem. Mal werden 85 
mA, kurz darauf 4.5A und sogar fast 9A ausgegeben. Zu kleine Datentypen 
oder Rundungsfehler kann ich ausschließen, da ich schon zum testen schon 
auf Double umgestellt habe. Auch die 17 Bit des Wertes für den Strom 
habe ich beachtet. Die Umstellung von Auto-Latching auf manuelles 
Latching macht ebenfalls keinen Unterschied. Besonders seltsam ist das, 
da RMS Spannung und Strom im gleichen Register 0x48 gespeichert sind und 
gleichzeitig ausgelesen werden. Daher würde ich erwarten, dass auch der 
Messwert der Spannung schwankt.

Auch bei der Messung der Periodenzeit aus Register 0x2E oder 0x2F 
erhalte ich immer den Rohwert 2500. Das macht irgendwie noch weniger 
Sinn, da man bei 50 Hz Netzfrequenz und 20ms Periodenzeit eher einen 
Rohwert von 2000 erwartet...

von Chris (Gast)


Lesenswert?

Chris schrieb:
> Der Strom von 100 mA (AC RMS), dessen roher ADC Wert im gleichen
> Register wie die Spannung steht

Der Strom wurde übrigens durch einen einstellbaren Widerstand mit 100 
Ohm "erzeugt"

von Jan H. (janiiix3)


Lesenswert?

Hey Chris,

Wie latched du die Daten?

von Chris (Gast)


Lesenswert?

Jan H. schrieb:
> Wie latched du die Daten?

Das Latching kann man ja über Register 0x04 einstellen. Entweder 
Auto-Latching (siehe unten) alle ~200us oder manuell, dann muss man die 
Register immer beschreiben und es wird danach einmal gelatched.

1
// write register DSP_CR3 at address 0x04 with 0x0000 04E0, Autolatching
2
spi_ac_metro_tx_data[0] = 0x04;  // read back all 32-bits of register
3
spi_ac_metro_tx_data[1] = 0x04;  // write 16-bit MSW of register
4
spi_ac_metro_tx_data[2] = 0xE0;  // write LSB
5
spi_ac_metro_tx_data[3] = 0x04;  // write MSB
6
SPI_send_to_AC_metro(spi_ac_metro_tx_data, 1);
7
8
//spi_ac_metro_tx_data[0];  // read back all 32-bits of register
9
++spi_ac_metro_tx_data[1];  // write 16-bit MSW of register
10
spi_ac_metro_tx_data[2] = 0xE0;  // write LSB, Autolatching
11
spi_ac_metro_tx_data[3] = 0x00;  // write MSB
12
SPI_send_to_AC_metro(spi_ac_metro_tx_data, 1);

von Jan H. (janiiix3)


Lesenswert?

Kannst du eine korrekte Spannung auslesen?

von Chris (Gast)


Lesenswert?

Jan H. schrieb:
> Kannst du eine korrekte Spannung auslesen?

Ja, wie oben geschrieben funktioniert das auslesen der Spannung gut, nur 
der Wert vom ermittelten Strom springt extrem

von Jan H. (janiiix3)


Lesenswert?

Hast du den Chip kalibriert?

von Chris (Gast)


Lesenswert?

Jan H. schrieb:
> Hast du den Chip kalibriert?

Nein, bin ich noch nicht dazu gekommen. Ich glaube auch nicht, dass das 
das Problem mit der Strommessung behebt. Wenigstens ein konstanter Wert 
sollte auch ohne Kalibrierung rauskommen.

Hat das bei dir einen ähnlichen Fehler behoben?

von Jan H. (janiiix3)


Lesenswert?

Nein. Die Spannung jedoch verhält sich auch sprunghaft ( 5-8 V).

von Chris (Gast)


Lesenswert?

Wie erzeugst du diese (Wechsel)Spannung? Versuche mal, diese zu 
belasten. Eine Messung mit einem Multimeter zeigt eine stabile Spannung?

von Jan H. (janiiix3)


Lesenswert?

Ja. Die Spannung kommt aus einem Einstellbaren Trenntrafo. Habe parallel 
ein Hameg.

Wie würde denn die Kalibrationsroutine aussehen? Also bei dem Datenblatt 
haben sie (ST) nicht alles gegeben.

von Chris (Gast)


Lesenswert?

Ich fand die Kalibrierroutine eigentlich recht gut beschrieben, sogar in 
einem eigenem Dokument mit den einzelnen Registerzugriffen (AN4470, 
DocID026176 Rev 3). Dafür braucht man aber eine halbwegs genaue Quelle 
und Last, da auf diese bekannten Werte kalibriert wird.

von Jan H. (janiiix3)


Lesenswert?

Hast du schon was geschrieben dazu?

von Chris (Gast)


Lesenswert?

Nein, steht erst mal hinten an

von Vivek S. (vivek_s)


Lesenswert?

We are using stpm32 for Ac metering. We have sent the sequence ( 48 FF 
FF FF 22 ) to read register 36 which will read VRMS and IRMS. Now it is 
reading but when I change the AC mains voltage, the readings are not 
changing. Is there anything I need to reset the registers? Or do I need 
to send any other sequence before reading register 36?

Beitrag #5511558 wurde von einem Moderator gelöscht.
von Chris (Gast)


Lesenswert?

Please check register 0x04 which will affect the latching of the data. 
Autolatching will store a new value every ~200us.

So write register DSP_CR3 at address 0x04 with 0x0080 04E0 for 
autolatching.

If you want to manually latch the data, the according register value 
should be set to 0x006004E0 before every reading

von Jan H. (janiiix3)


Lesenswert?

Hey Chris...
Wie läuft es mit deinen Routinen?
Irgendwie bin ich gerade am verzweifeln..
Wenn ich Register 0x48 mehrfach hintereinander Auslese... Kommen ab und 
zu immer falsche AD Werte für die Spannungen.. Mal 0 mal 313 usw.

Hast du eine Idee?

: Bearbeitet durch User
von Chris (Gast)


Lesenswert?

Hi Jan,

da kann ich dir aktuell leider nicht weiterhelfen, da ich auch nicht 
mehr dazu gekommen bin. Mit schwankenden Spannungswerten hatte ich aber 
nie Probleme, dafür habe ich ein ähnliches Problem beim Strom. Bislang 
habe ich hier aber noch nichts neues herausfinden können.

Eine Idee, die ich mal hatte aber noch nicht testen konnte wäre 
folgendes: Nachsehen, ob es beim STPM ein Bit gibt, welches die 
Gültigkeit des Messwertes anzeigt. Erst wenn dieses gesetzt wurde das 
auslesen der Messwerte starten.

Hast du denn außerdem mal versucht die Messung händisch zu starten 
(manuelles latching), eine gewisse Zeit gewartet und erst dann 
ausgelesen?

von Jan H. (janiiix3)


Lesenswert?

Hi Chris,

habe es jetzt. Spannung und Strom sind auch kalibriert.
Trdz danke für deine Antwort.

von Chris (Gast)


Lesenswert?

Hallo Jan,

wäre schön wenn du uns deine Lösung noch mitteilen könntest

von Orikson (Gast)


Lesenswert?

Hallo,

ist die Lösung mittlerweile bekannt?

von Ben (Gast)


Lesenswert?

Hey Jan,

ich kämpfe auch mit den RMS Spannungswerten die eher der momentan 
Spannung entsprechen. Du hattest die Lösung dazu gefunden?

von Jan H. (janiiix3)


Lesenswert?

Ben schrieb:
> Hey Jan,
>
> ich kämpfe auch mit den RMS Spannungswerten die eher der momentan
> Spannung entsprechen. Du hattest die Lösung dazu gefunden?

Joar..

von Chris (Gast)


Lesenswert?

Ben schrieb:
> RMS Spannungswerten die eher der momentan Spannung entsprechen

Ich verstehe die Frage nicht, irgendwas fehlt in dieser Formulierung...

Mein Problem von damals hatte ich aber auch gefunden. Ich hatte einfach 
zu wenig Dummy-Daten gesandt, nachdem ich das zu lesende Register 
übertragen hatte... Seltsamerweise ging es meistens und ist nur in 
gewissen Fällen ausgestiegen

von Mark G. (markg)


Angehängte Dateien:

Lesenswert?

Hi!

Ich mache auch ein Power-Metering Projekt mit STPM32 und STM32.
Habe den code von Chris für die CRC-Berechnung beim SPI-Kommunikation 
benutzt.
Mein Program sendet alles ohne problem und richtig, aber kriegt zurück 
immer den gleichen "Default" Wert von dem ersten Register: 040000A0. 
(Bild angehängt)

Hat jemand Ideen was kann die Ursache davon sein?

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.