SPI Kommunikation mit STM32 und PST360G2

OP #7685939
Lesenswert?

Guten Tag zusammen,

das ist mein erster Beitrag und hoffe alle Regeln zu beachten.

Zu meinem Problem: ich bin neu in der STM Umgebung sowie der Programmierung. Ich möchte nun einen Sensor (PST360G2-1S) mit dem STM32-L432KC auslesen. Leider stoße ich an Probleme, die ich mir leider nicht erklären kann.

Im Anhang findet Ihr meinen Code sowie das Datenblatt zur Kommunikation des Sensors.

Eingestellt habe ich in der Cube folgendes:

  • SPI Mode: Full-Duplex Master
  • Hardware NSS Signal Disable
  • Frame Format: Motorola
  • Data Size: 8 Bits
  • Prescaler: 2
  • CPOL: Low
  • CPHA: 1 Edge

Die ausgelesenen Werte seinen nicht zu stimmen. Könnt Ihr mir dabei helfen dem Problem auf den Grund zu gehen?

Liebe Grüße

Angehängte Dateien:
#7686156
Lesenswert?

Karlo schrieb:

Die ausgelesenen Werte seinen nicht zu stimmen.

Ich kann da nichts Falsches dran sehen.

Könnt Ihr mir dabei helfen dem Problem auf den Grund zu gehen?

Nimm ein Oszilloskope und sieh Dir die Signale an.

Ohne Oszilloskope definiere Dir ein paar Portpins passend für synchrone Übertragung und lass die Pins per Software 'wackeln'. Das kann ganz langsam passieren und mit LEDs kontrolliert werden. Zu Cube kann ich nichts sagen, das ist mir zu kompliziert.

#7687527
Lesenswert?

The DATA16 could be a valid angle, or an error condition. The two meanings are distinguished by the LSB.

Wäre vllt. nicht schlecht erstmal die unteren 2 Bits zu prüfen ob ein Fehler vorliegt.

1
if ((data[2] & 0x03) == 0x01)
2
{
3
    // alles OK
4
}
5

6
if ((data[2] & 0x03) == 0x02)
7
{
8
    // Error
9
}

Und was float betrifft, schreib es lieber so: Nicht das er deine first14 Variable nicht als float betrachtet.

1
float value = (float)first14 / 16384.0f;
2
float angle = (value - 0.1f) / (0.9f - 0.1f) * 360.0f;
#7687634
Lesenswert?

Karlo schrieb:

Wieso ist das immer null?

Jede Operation liefert einen Wert eines bestimmten Typs. xxx << n liefert einen Wert des Typs, den xxx hat. Welchen Typ sollte man denn sonst nehmen?

Beispiel: uint8_t xyz = 3;

In Bits geschrieben ist der Wert der Variablen 00000011. Der Ausdruck (xyz << 7) hat den Typ uint_8 und den Wert 10000000. Ein Bit ist im Nirvana verschwunden. Bei (xyz << 8) ist der Wert also immer 00000000. Selbst wenn man nach dem Verschieben castet, ändert das nichts: Erst wird der Wert (= 00000000) ermittelt, dann wird der Cast ausgeführt: (uint16_t) (xyz << 8) ist also 0000000000000000

Man muss also den Cast vor dem Verschieben ausführen, um einen 16-Bit-Wert zu bekommen: ((((uint16_t)yxz)) << 8), das ergibt den gewünschten Wert 0000001100000000. Ohne überflüssige Klammern (uint16_t)yxz << 8

#7687705
Lesenswert?

Adam P. schrieb:

Das funktioniert so seit Jahren.

Seit Jahren funktioniert hier auch, daß Leute aufschlagen, nur Fragen stellen, keine Details angeben und erwarten, ihre Probleme anhand zugeworfener Häppchen gelöst zu bekommen. Es werden keine Zwischenwerte (Inhalt von data[]) angegeben, nur ein printf()-Wert erwähnt, der angeblich falsch sein soll, und dann irgendwann gemotzt, daß ihm nicht geholfen wird.

Moderator Persönliche Seite #7687763
Lesenswert?

Rolf schrieb:

Jede Operation liefert einen Wert eines bestimmten Typs. xxx << n liefert einen Wert des Typs, den xxx hat.

Das ist falsch.

Gegenbeispiel:

1
#include <stdio.h>
2
#include <stdint.h>
3

4
int main (void)
5
{
6
    uint8_t a = 1;
7
    uint8_t b = 8;
8
    uint16_t c;
9

10
    c = (a << 8) | b;
11

12
    printf ("%d\n", c);
13
}
1
cc a.c && ./a.out
2
264

Stichwort ist hier: Integer Promotion.

#7687856
Lesenswert?

Frank M. schrieb:

Stichwort ist hier: Integer Promotion.

Ok, da hast du Recht. Aber ich habe auch Recht. ;-)

Die Integer Promotion funktioniert – entgegen der Aussage von Adam P. – nicht bis zu beliebig großen Datentypen. "Kleine" Typen werden nur bis zur Größe eines 'int' aufgeblasen:

https://en.cppreference.com/w/cpp/language/implicit_conversion#Integral_promotion if T is char8_t, (since C++20)char16_t, char32_t or (since C++11)wchar_t, val can be converted according to the rules specified in item (3); otherwise, if the integer conversion rank of T is lower than the rank of int: val can be converted to a prvalue of type int if int can represent all the values of T; otherwise, val can be converted to a prvalue of type unsigned int.

Wenn der Prozessor größere Register hat, als es einem 'int' entspricht, dann verschwinden beim Links-Shift die weiteren Bits im Nirvana. Ggf. muss der Compiler eben einen Befehl zum Löschen einfügen:

https://en.cppreference.com/w/cpp/language/operator_arithmetic

The value of a << b is the unique value congruent to a * 2b modulo 2N where N is the number of bits in the return type (that is, bitwise left shift is performed and the bits that get shifted out of the destination type are discarded).

#7687865
Lesenswert?

Rolf schrieb:

Die Integer Promotion funktioniert – entgegen der Aussage von Adam P. – nicht bis zu beliebig großen Datentypen. "Kleine" Typen werden nur bis zur Größe eines 'int' aufgeblasen:

Was anderes habe ich nie behauptet! Kein Mensch redet hier von 64 oder 128bit variablen.

Wie dem auch sei, du hast Recht. Katastrophe.

#7687921
Lesenswert?

Adam P. schrieb:

Die Integer Promotion funktioniert – entgegen der Aussage von Adam P. – nicht bis zu beliebig großen Datentypen. "Kleine" Typen werden nur bis zur Größe eines 'int' aufgeblasen:

Was anderes habe ich nie behauptet!

Du hast gesagt, es würde bis auf die Registergröße von 32 Bit aufgeblasen. Ich glaube aber nicht, dass 'int' in diesem Fall 32 Bit hat, es wird 16 Bit haben. Oder?

Gast #7688109
Lesenswert?

Rolf schrieb:

Ok, da hast du Recht. Aber ich habe auch Recht. ;-)

Du bist genau der Diplomat, den die von Kriegen verletzte Welt braucht.

Respekt - also übernimm die Verantwortung und engagier Dich.

Genau hier und jetzt auf diesem Planeten, wo wir und unsere Kinder leben.

#7688162
Lesenswert?

Rolf schrieb:

Du hast gesagt, es würde bis auf die Registergröße von 32 Bit aufgeblasen. Ich glaube aber nicht, dass 'int' in diesem Fall 32 Bit hat, es wird 16 Bit haben. Oder?

Cortex-M4F

Läuft so seit Jahren:

1
static inline uint16_t u8u16(uint8_t *src)
2
{
3
  return ((src[1] << 8) | (src[0]));
4
}
5

6
static inline uint32_t u8u32(uint8_t *src)
7
{
8
  return ((src[3] << 24) | (src[2] << 16) | (src[1] << 8) | (src[0]));
9
}
OP #7688357
Lesenswert?

Hey zusammen und an die, die das in der Zukunft lesen werden.

Die Probleme, welche ich hatte, sind behoben und ich bekomme die richtigen Winkel auf dem STM32 L4 raus.

Einstellungen für STMCube:

  • SPI Mode: Full-Duplex Master
  • Hardware NSS Signal Disable
  • Frame Format: Motorola
  • Data Size: 8 Bits
  • Prescaler: 256 (Das ist eine Notwendige Änderung)
  • CPOL: Low
  • CPHA: 2 Edge (Das ist eine Notwendige Änderung)

Ich hoffe das hilft jemandem in der Zukunft auch!

Ein Tipp von mir als Anfänger für weitere Anfänger: beschäftigt euch mit dem Datenblatt ausreichend, um wirklilch jeden einzelnen Schritt zu verstehen. Dann ist es leichter Fehler zu finden. Außerdem versteht die Commands, die Ihr benutzt und wie diese aufgebaut sind.

Also dann, danke an jede/n, der/die mir geholfen hat!

Angehängte Dateien:

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