Forum: Mikrocontroller und Digitale Elektronik STM32 SPI 2 Byte senden


Announcement: there is an English version of this forum on EmbDev.net. Posts you create there will be displayed on Mikrocontroller.net and EmbDev.net.
von Walt N. (belayason)


Lesenswert?

Hallo Leute,

ich probiere mich gerade daran mit meinem STM32F411RE eine Verbindung zu 
einem MCP4922 aufzubauen. Dafür habe ich zum ersten mal eine SPI 
Schnittstelle mit hilfe der HAL Lib erstellt. Ich scheitere aber daran 2 
bytes hintereinander zu senden.
1
char message[] = "H";
2
3
HAL_GPIO_WritePin(GPIOA, SPI1_CS_Pin, 0);
4
5
HAL_SPI_Transmit(&hspi1,(uint8_t *)message, strleng(message), HAL_MAX_DELAY);
6
7
HAL_GPIO_WritePin(GPIOA, SPI1_CS_Pin, 1);
Dieser code funktioniert. Es wird genau 1 Byte gesendet mit dem inhalt 
"H".
Soweit ganz gut, als nächstes wollte ich nun meine eigenen 2 Byte mit 
dem Inhalt versenden, der dem Register des MCP4922 entspricht.
1
char low_byte, high_byte;
2
3
high_byte |= (0x01 << 4);  /** ( 0 0 0 1 | ...4 data bits ) [A/B = 0 -> write to DAC A ; BUF = 0 -> unbuffered; GA = 0 -> 2x; SHDN = 1 active mode operation]*/
4
low_byte  |= ((0x01 << 7)|(0x01 << 6)|(0x01 << 5)|(0x01 << 4)|(0x01 << 0));    /** ( 1 1 1 1 | 0 0 0 1)*/
5
6
HAL_GPIO_WritePin(GPIOA, SPI1_CS_Pin, 0);
7
8
HAL_SPI_Transmit(&hspi1,(uint8_t *)high_byte, strleng(message), HAL_MAX_DELAY);
9
10
11
HAL_SPI_Transmit(&hspi1,(uint8_t *)low_byte, strleng(message), HAL_MAX_DELAY);
12
13
14
HAL_GPIO_WritePin(GPIOA, SPI1_CS_Pin, 1);

Das Ergebnis stimmt leider vorne und hinten nicht... Was mache ich bei 
der Übertragung falsch?

von Einer K. (Gast)


Lesenswert?

Walt N. schrieb:
> Das Ergebnis stimmt leider vorne und hinten nicht..

> (uint8_t *)high_byte
Warum du ein "Byte" zum Zeiger castest ist mir ein Rätsel.
Und was der Zeiger dann mit strleng(message) zu tun hat, verstehe ich 
auch nicht.

Wie auch immer, mich wundern unerwünschte Ergebnisse nicht.

von OMG (Gast)


Lesenswert?

Walt N. schrieb:
> Das Ergebnis stimmt leider vorne und hinten nicht... Was mache ich bei
> der Übertragung falsch?

Zunächst macht du einmal falsch dass du uns das Ergebnis nicht
mitteilst, nämlich was vorne und hinten nicht stimmt.

von John Doe (Gast)


Lesenswert?

Walt N. schrieb:
> Das Ergebnis stimmt leider vorne und hinten nicht... Was mache ich bei
> der Übertragung falsch?

Ganz einfach: Du hast Dich vorher nicht mit der Sprache C beschäftigt!

von Martin B. (ratazong)


Lesenswert?

Hallo

HAL_SPI_Transmit(&hspi1,(uint8_t *)high_byte, strleng(message), 
HAL_MAX_DELAY);


Damit sendest Du eine Speicherstelle, die du nicht senden willst.

Du brauchst (uint8_t *)&high_byte, der zeigt auf die Speicheradresse, 
die Du senden willst.

von Guest (Gast)


Lesenswert?

Man kann es sich auch schwer machen....
Im Übrigen sieht man relativ leicht was eine Funktion haben will, wenn 
man sich die Übergabeparameter anschaut und die Beschreibung liest.
1
uint8_t data[2];
2
3
data[0] |= (0x01 << 4); 
4
data[1]  |= ((0x01 << 7)|(0x01 << 6)|(0x01 << 5)|(0x01 << 4)|(0x01 << 0));    
5
6
HAL_GPIO_WritePin(GPIOA, SPI1_CS_Pin, 0);
7
HAL_SPI_Transmit(&hspi1, data, 2, HAL_MAX_DELAY);
8
HAL_GPIO_WritePin(GPIOA, SPI1_CS_Pin, 1);

PS: die meisten SPI von den STMs kann man so konfigurieren das sie 
gleich 16 Bit schicken. Dann müsste entsprechend eine 1 statt einer 2 
bei der Länge stehen.

von PittyJ (Gast)


Lesenswert?

Was berechnet eigentlich strleng(message) ?

Meisten gehen solche Funktionen bei Binärdaten nicht.

von Walt N. (belayason)


Lesenswert?

Guest schrieb:
> uint8_t data[2];
>
> data[0] |= (0x01 << 4);
> data[1]  |= ((0x01 << 7)|(0x01 << 6)|(0x01 << 5)|(0x01 << 4)|(0x01 <<
> 0));
>
> HAL_GPIO_WritePin(GPIOA, SPI1_CS_Pin, 0);
> HAL_SPI_Transmit(&hspi1, data, 2, HAL_MAX_DELAY);
> HAL_GPIO_WritePin(GPIOA, SPI1_CS_Pin, 1);

Perfekt danke!!! Das war des Rätsels Lösung

von Walt N. (belayason)


Angehängte Dateien:

Lesenswert?

Zusätzlich stellt sich jetzt noch eine weitere Frage. Ich würde mit dem 
MCP4922 gerne einen Sinus mit 40 KHz generieren. Die Auflösung ergibt 
sich, wie viele Werte für eine ganze Schwingung innerhalb von 0,025 ms 
mit dem MCP4922 ausgeben kann. Im Bild Anhang sind 3 Ouputs meiner SPI 
Schnittstelle zu sehen. Ab einem Baudratenprescaler 16 sieht das clk 
Signal nicht nach einer klassischen clock aus. Die Bitfolge scheint 
dennoch zu stimmen wenn man es vergleicht. Liegt das vielleicht an 
meinem china logic analyzer ? Der MCP wird mit dieser clock die Bitfolge 
wohl nicht entschlüsseln können, oder? (Bauteil kommt morgen und ich 
bereite die SPI Schnittstelle vor)

von John Doe (Gast)


Lesenswert?

Welche Samplerate hast Du eingestellt?

von Walt N. (belayason)


Lesenswert?

John Doe schrieb:
> Welche Samplerate hast Du eingestellt?

Dem bin ich heute nachgegangen. Meine SPI1 Schnittstelle hängt am APB2 
Bus, laut CubeMX habe ich dort eine clock von 16 MHz. In der 
SystemClock_config() function habe ich einen teiler durch 1.
1
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;
In meiner SPI1 init function habe ich einen Baudrateprescaler 2 also den 
kleinsten eingestellt.
1
  hspi1.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
Das bedeutet dass ich mein clock Signal an der SPI1 Schnittstelle 8MHz 
beträgt. 125 nS beträgt die Periodendauer von 8MHz. Will ich nun einen 
Wert an den mcp4922 senden bedeutet das 16 * 125 nS = 2µs pro Wert. Für 
einen sinus brauch ich leider mehr Werte als einen. Gehen wir mal von 10 
Werten aus (5 pro halbwelle, keine schöner sinus aber sinusförmig). 
(16*10)*125nS = 20000ns = 20µS entsprechen 50KHz, hier ist die Zeit 
nicht einberechnet die mich der Chipselect kostet etc.

: Bearbeitet durch User
von Lothar M. (lkmiller) (Moderator) Benutzerseite


Lesenswert?

Walt N. schrieb:
> Das bedeutet dass ich mein clock Signal an der SPI1 Schnittstelle 8MHz
> beträgt. 125 nS beträgt die Periodendauer von 8MHz. Will ich nun einen
> Wert an den mcp4922 senden bedeutet das 16 * 125 nS = 2ms pro Wert.
Da hast du aber glatt 3 Zehnerpotenzen verschlampert.

> clock Signal an der SPI1 Schnittstelle 8MHz ... 16 Bit
Ich rechne da überschlägig, dass das Problem woanders liegt:
8MHz / 16 = 500kHz

EDIT: dürfte also bei zügiger Ansteuerung und anschließeder Filterung 
gerade so reichen. Und schneller kann der DAC mit 4,5µs Settling Time 
sowieso nicht.

: Bearbeitet durch Moderator
von Walt N. (belayason)


Lesenswert?

Lothar M. schrieb:
> Da hast du aber glatt 3 Zehnerpotenzen verschlampert.

Ist mir auch aufgefallen, verdammt.

16 * 125 nS = 2µS dauert demnach 1 Wert. 25µS entsprechen 40KHz das 
bedeutet ich bekomme höchstens 25µS/2µS = 12,5 Werte übertragen. Und da 
ist die Zeit noch nicht einberechnet die mich die Chipselect operation 
kostet. Kriege ich mit diesem setup überhaupt 40KHz hin?

Antwort schreiben

Die Angabe einer E-Mail-Adresse ist freiwillig. Wenn Sie automatisch per E-Mail über Antworten auf Ihren Beitrag informiert werden möchten, melden Sie sich bitte an.

Wichtige Regeln - erst lesen, dann posten!

  • Groß- und Kleinschreibung verwenden
  • Längeren Sourcecode nicht im Text einfügen, sondern als Dateianhang

Formatierung (mehr Informationen...)

  • [c]C-Code[/c]
  • [code]Code in anderen Sprachen, ASCII-Zeichnungen[/code]
  • [math]Formel in LaTeX-Syntax[/math]
  • [[Titel]] - Link zu Artikel
  • Verweis auf anderen Beitrag einfügen: Rechtsklick auf Beitragstitel,
    "Adresse kopieren", und in den Text einfügen




Bild automatisch verkleinern, falls nötig
Bitte das JPG-Format nur für Fotos und Scans verwenden!
Zeichnungen und Screenshots im PNG- oder
GIF-Format hochladen. Siehe Bildformate.
Hinweis: der ursprüngliche Beitrag ist mehr als 6 Monate alt.
Bitte hier nur auf die ursprüngliche Frage antworten,
für neue Fragen einen neuen Beitrag erstellen.

Mit dem Abschicken bestätigst du, die Nutzungsbedingungen anzuerkennen.