C Energy Monitoring mit einem STPM32

Janiiix3

Aktives Mitglied
28. Sep. 2013
1.333
10
38
Hannover
Sprachen
  1. ANSI C
  2. C#
Moin Moin.

Bin gerade mal wieder dabei einen SPI Baustein zum reden zu bringen.
Das reden, hat er schon gelernt. Das schreiben mag er noch nicht.
Im Datenblatt steht das ein Kommando oder Frame immer mindestens 4 Bytes lang ist..

lese_adresse, schreib_adresse, data_byte_1, data_byte_2

Also wie beschrieben, Funktioniert das lesen.

Das ist meine schreib Funktion..


CodeBox C
void stpm32x_write(uint8_t addr, uint32_t cmd){

spi_select_low();
spi_usartx_tx_rx(0xff); // Previously requested data byte LSB
spi_usartx_tx_rx(addr); // Previously requested data byte 2 out of 4
spi_usartx_tx_rx((cmd & 0x00FF0000)>>16); // Previously requested data byte 3 out of 4
spi_usartx_tx_rx((cmd & 0xFF000000)>>24); // Previously requested data byte MSB
spi_select_high();

_delay_ms(50);

spi_select_low();
spi_usartx_tx_rx(0xff); // Previously requested data byte LSB
spi_usartx_tx_rx(addr+1); // Previously requested data byte 2 out of 4
spi_usartx_tx_rx((cmd & 0x0000FF00)>>8); // Previously requested data byte 3 out of 4
spi_usartx_tx_rx((cmd & 0x000000FF) ); // Previously requested data byte MSB
spi_select_high();
}


Achso..
Arbeiten tu ich im SPI Mode 3!

Hier das Datenblatt
www.st.com/resource/en/datasheet/stpm34.pdf
 
Zuletzt bearbeitet:
Ich habe mir das Datenblatt angeschaut ...
Mir ist aufgefallen, dass du beim zweiten Word (Bit 15..0) MSB und LSB vertauscht hast.
LSB wird immer zuerst übertragen.

Möglicherweise ist CRC aktiviert. Da du kein CRC sendest, wird der Slave das Write Kommando nicht ausführen ...
Möglicherweise liegt es daran.
The CRC feature, enabled by default, can be
controlled by a configuration bit into US_REG1 memory row (read address 0x24, write
address 0x24).

CRC deaktivieren:
upload_2017-6-27_9-3-21.png
 
Da stand doch..


CodeBox C
5 (optional) Master CRC verification packet Slave CRC verification packet


Das 5 Byte Optional ist?
 
Optional, weil deaktivierbar?

Ich gehe davon aus, wenn CRC aktiviert ist (default), dann muss es auch übertragen werden.

Wenn du Registerinhalte liest und nach dem 4 Byte abbrichst und CRC ignorierst, merkt das ja der Slave nicht.

Wenn du allerdings für eine Schreiboberation CRC nicht überträgst, wird der Slave diese nicht ausführen.
Zumindest vermute ich das mal, ich habe das Datenblatt nun nicht komplett durchgearbeitet.
Aber falls es nicht so wäre, würde die Sicherheitsmaßnahme nicht so gut greifen.
 
Muss ich auf das ausschalten Kommando des CRC´s Mode, auch eine CRC bilden?
Wenn ich es so versuche und danach das Register wieder auslese, ist das Bit nach wie vor gesetzt,,



CodeBox C
spi_select_low();
spi_usartx_tx_rx(0x24); // Previously requested data byte LSB

spi_usartx_tx_rx(0x24); // Previously requested data byte 2 out of 4

spi_usartx_tx_rx(0x07); // Previously requested data byte 3 out of 4

spi_usartx_tx_rx(0x00); // Previously requested data byte MSB

spi_select_high();


Hiermit sollte das CRC Feature aus sein.
 
Muss ich auf das ausschalten Kommando des CRC´s Mode, auch eine CRC bilden?

Ich vermute.

Sende einmal folgendes.

0x24 0x24 0x07 0x00 0x15

CRC = 0x15 nach CRC8-CCITT mit Polynom 0x07 und Startwert 0
 
Das Funktioniert. Wieso gibt man so etwas im Datenblatt an? Jemand der so was noch nie gemacht hat bzw. mit dem Chip gearbeitet hat, wird doch verrückt.
 
Diese Funktionen habe ich schon mal gesehen. Was meint ihr? Sollte man mit CRC Checksummen arbeiten um die plausibilität der Daten zu gewährleisten?

Gibt es eigentlich ein tolles Buch, wo solch Rechenwege wie eben diese "Polynom Division" schön erklärt wird?
 
Sollte man mit CRC Checksummen arbeiten um die plausibilität der Daten zu gewährleisten?
Bei RS232 und Baudraten >115K ist das Pflicht. Da geht sonst alles durcheinander, primär wegen billiger China Ware was die Pegelwandler angeht. SPI hab ich auch schon ohne Probleme mit 1 oder 2 MHz befeuert.

Und OPTIONAL heißt dass es vom Chip her optional ist, nicht aber zwangsweise auch für die Aktion die du durchführen möchtest. Blödes Beispiel:
Function Login(User As Sring, Optional Password As String) As Boolean
Du könntest das Passwort weg lassen wenn der Benutzer bereits angemeldet ist, oder die Passwortüberprüfung generell deaktiviert ist, also nur in 2 von 3 Möglichkeiten ;)
 
Moin Dirk.

Ja das klappt mit den fertigen Funktionen von Atmel. Ich muss mir das mal auf nen Zettel aufschreiben, damit ich die Rechnung auch nachvollziehen kann.
 
Hey Jan,

ich entwerfe für meine Bachelorarbeit eine Metering-Platine mit dem STPM32, Mikrocontroller und einem Zigbee Funkmodul.

Leider habe Probleme mit der SPI Verbindung zum STPM.

Ich benutze einen MSP430FR2311 Mikrocontroller für die Weiterverarbeitung der Werte.

Die SPI Verbindung funktioniert, die Pegel sehen auf dem Oszilloskop gut aus und es ist meines Erachtens nach auch alles korrekt eingestellt.

Jedoch erhalte ich beim Lesen eines Registers nicht die erwarteten Antworten.

Beispiel:

Lesen der Daten aus Row 4 also Adresse 08 dsp_cr6

Senden Anfrage:
08_FF_FF_FF
-->

Dummy Werte zum Empfangen:
FF_FF_FF_FF

Empfang:
93_81_93_87
-->

Default Werte aus der Registertabelle (Seite 87/120 im Datenblatt), welche ich auch durch auslesen via "STPM3x Evaluation Software" erhalten habe sind jedoch

00_3F_F8_00

Das gleiche Problem habe ich mit allen anderen Registern. LSB First ist nicht eingestellt und nach Endian Umwandlung ergeben die erhaltenen Werte auch keinen Sinn.

Ich hoffe du kannst mir weiterhelfen und falls dir nicht direkt etwas einfällt mir deinen Code zum Register lesen als Beispiel zeigen.

Ich wäre dir super dankbar, da dieses Problem mich unglaublich viel Zeit und Nerven kostet und die "hervorragende" Dokumentation von ST mir auch nicht weiterhilft.

Danke im Voraus und beste Grüße

Jonas
_________________________________________________________________________

Edit: Die Frage geht natürlich auch an alle anderen falls jemand eine Idee hat :)
 
Zuletzt bearbeitet:
void stpm32x_write(uint8_t addr, uint32_t cmd){ spi_select_low();spi_usartx_tx_rx(0xff); // Previously requested data byte LSBspi_usartx_tx_rx(addr); // Previously requested data byte 2 out of 4spi_usartx_tx_rx((cmd & 0x00FF0000)>>16); // Previously requested data byte 3 out of 4spi_usartx_tx_rx((cmd & 0xFF000000)>>24); // Previously requested data byte MSBspi_select_high(); _delay_ms(50); spi_select_low();spi_usartx_tx_rx(0xff); // Previously requested data byte LSBspi_usartx_tx_rx(addr+1); // Previously requested data byte 2 out of 4spi_usartx_tx_rx((cmd & 0x0000FF00)>>8); // Previously requested data byte 3 out of 4spi_usartx_tx_rx((cmd & 0x000000FF) ); // Previously requested data byte MSBspi_select_high();}

Ich habe mir das Datenblatt angeschaut ...
Mir ist aufgefallen, dass du beim zweiten Word (Bit 15..0) MSB und LSB vertauscht hast.
LSB wird immer zuerst übertragen.

Kann es sein das dass Protokoll total falsch ist, wie ich die Daten übertrage @Dirk? Muss das nicht anders herum?
 
Hat sich erledigt. Die Kommunikation funkioniert doch einwandfrei.
 
Ich komme nicht weiter...
Versuche die ganze Zeit die AD Werte aus dem Register "0x48" zu lesen aber anscheind ohne Erfolg.
Wenn ich die Spannung an den Messeingängen ändere ( Phase 1) ändert sich auch die Messspannung. Also Physikalisch ist dort alles takko.

Ich werde das Gefühl nicht los das dass "Latchen" von dem Register nicht sauber / überhaupt nicht funktioniert..
Andere Registerinhalte ( mit ihrem default Werten ) kann ich zurücklesen ( dort wo kein Latch gemacht werden muss..)

Hier werden die Daten eingesammelt.. Jemand eine Idee??


CodeBox C
static inline void       stpm32SpiRead   ( uint8_t *buff , uint8_t crcEn )           
{   
   uint8_t reg = buff[0];
   
   uint8_t frame[5] = { reg , 0xFF , 0xFF , 0xFF , 0x00 }; // buff[0] = Register Adresse
       

     STPM32_SYNC_PORT.OUTCLR = ( 1 << STPM32_SYNC_bp );
     _delay_ms(50);
     STPM32_SYNC_PORT.OUTSET = ( 1 << STPM32_SYNC_bp );
     _delay_ms(150);       
   
   stpm32Select();
   for ( uint8_t i = 0 ; i < ( STPM32_FRAME_LENG - 1 ) + crcEn ; i++ )
   {
       spiMasterWriteRead( frame[i] );
   }       

   for ( uint8_t i = 0 ; i < ( STPM32_FRAME_LENG - 1 ) + crcEn ; i++ )
   {
       *buff++ = spiMasterWriteRead( 0xFF );
   }
   stpm32Deselect();   
}
 
Ich werde das Gefühl nicht los das dass "Latchen" von dem Register nicht sauber / überhaupt nicht funktioniert.
Ich habe gesehen, es gibt mehrere Möglichkeiten zu latchen. Welche nutzt du denn gerade?
 
Ich benutze gerade die Hardware Methode. Sprich den SYNC Pin.
 

Über uns

  • Makerconnect ist ein Forum, welches wir ausschließlich für einen Gedankenaustausch und als Diskussionsplattform für Interessierte bereitstellen, welche sich privat, durch das Studium oder beruflich mit Mikrocontroller- und Kleinstrechnersystemen beschäftigen wollen oder müssen ;-)
  • Dirk
  • Du bist noch kein Mitglied in unserer freundlichen Community? Werde Teil von uns und registriere dich in unserem Forum.
  •  Registriere dich

User Menu

 Kaffeezeit

  • Wir arbeiten hart daran sicherzustellen, dass unser Forum permanent online und schnell erreichbar ist, unsere Forensoftware auf dem aktuellsten Stand ist und der Server regelmäßig gewartet wird. Auch die Themen Datensicherheit und Datenschutz sind uns wichtig und hier sind wir auch ständig aktiv. Alles in allem, sorgen wir uns darum, dass alles Drumherum stimmt :-)

    Dir gefällt das Forum und unsere Arbeit und du möchtest uns unterstützen? Unterstütze uns durch deine Premium-Mitgliedschaft!
    Wir freuen uns auch über eine Spende für unsere Kaffeekasse :-)
    Vielen Dank! :ciao:


     Spende uns! (Paypal)