STM32F0: Mit HAL-Lib überprüfen, ob Datenübertragung über SPI abgeschlossen ist?

Gast #4959852
Lesenswert?

Hallo zusammen,

ich verwende einen STM32F0 und programmiere mit dem STM32CubeMX und der 
HAL-Lib.

Ich sende mit der Funktion HAL_StatusTypeDef HAL_SPI_Transmit 
(SPI_HandleTypeDef *hspi, uint8_t * pData, uint16_t Size, uint32_t 
Timeout) mehrere Datenpakete.

Nun möchte ich schauen, wann die Datenübertragung abgeschlossen ist, 
damit ich mein CS wieder auf High setzten kann. Hierfür muss ich prüfen, 
ob das TXE-Bit High oder Low ist.

Ich finde allerdings keine Funktion aus der HAL-Lib mit der dies möglich 
ist. Kennt ihr eine?
Gast #4959938
Lesenswert?

zigner schrieb:
> Nun möchte ich schauen, wann die Datenübertragung abgeschlossen ist,
> damit ich mein CS wieder auf High setzten kann.

Hier habe ich einen Link für dich. Ist zwar nicht direkt die
Lösung deines Problems da ich kein HAL benutze und auch der
Prozessor ist nicht der gleiche, aber das Problem und die
Prozessorfamilie schon. Und vielleich ergibt sich daraus
auch die gleiche Handlungsweise ...

Beitrag "[STM32F4xx] SPI Optimierung"
Gast #4959963
Lesenswert?

Markus M. schrieb:
> Die Funktion blockt solange bis der Transfer abgeschlossen ist. Man
> sollte sich im Zweifelsfall dann immer mal den Source anschauen.
>
> Du kannst also Dein CS Signal deaktivieren wenn die Funktion
> zurückgekehrt ist.

Nein die Funktion blockt nicht. Ich rufe in meinem Programm diese 
Funktion auf und deaktiviere direkt in der nächsten Zeile das CS Signal.

Dann habe ich mir das mal mit dem Oszi angeschaut und dort konnte man 
erkennen, dass CS bereits deaktivert wird, obwohl ein Teil der Daten 
erst danach übertragen wird.
Gast #4959982
Lesenswert?

STM Apprentice schrieb:
> Hier habe ich einen Link für dich. Ist zwar nicht direkt die
> Lösung deines Problems da ich kein HAL benutze und auch der
> Prozessor ist nicht der gleiche, aber das Problem und die
> Prozessorfamilie schon. Und vielleich ergibt sich daraus
> auch die gleiche Handlungsweise ...
>
> Beitrag "[STM32F4xx] SPI Optimierung"

Genau so möchte ich das auch machen, wie in dem Beitrag beschrieben, 
also die einzelnen Flags auswerten.

Ich möchte allerdings nicht wie du auf Registerebene programmieren und 
dort die einzelnen Bits abfragen. Denn bei meiner Aufgabe soll ich 
hauptsächlich auf die Funktionen der HAL-Lib zurückgreifen!

Aber dort suche ich vergeblich eine Funktion, mit der ich den Status der 
einzelnen Flags abfragen kann.

Bei der Standard-Lib gibt es ja folgendermaßen realisiert werden

 while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE)==RESET);

... und so ein Funktion wie GetFlagStatus wird es doch wohl auch bei der 
HAL-Lib geben?
Gast #4959987
Lesenswert?

zigner schrieb:
> Nein die Funktion blockt nicht.

Doch sie blockiert schon, nur nicht so wie man sich das
erwartet. Sie wartet bis sie das letzte Byte in das
SPI-Datenregister schreiben konnte. Dann arbeitet die
puffernde Hardware ....

Also sollte es vielleich auch unter HAL möglich sein das
entsprechende Bit abzufragen wie im Link ausgeführt.
Gast #4959989
Lesenswert?

zigner schrieb:
> STM Apprentice schrieb:
>> Hier habe ich einen Link für dich. Ist zwar nicht direkt die
>> Lösung deines Problems da ich kein HAL benutze und auch der
>> Prozessor ist nicht der gleiche, aber das Problem und die
>> Prozessorfamilie schon. Und vielleich ergibt sich daraus
>> auch die gleiche Handlungsweise ...
>>
>> Beitrag "[STM32F4xx] SPI Optimierung"
>
> Genau so möchte ich das auch machen, wie in dem Beitrag beschrieben,
> also die einzelnen Flags auswerten.
>
> Ich möchte allerdings nicht wie du auf Registerebene programmieren und
> dort die einzelnen Bits abfragen. Denn bei meiner Aufgabe soll ich
> hauptsächlich auf die Funktionen der HAL-Lib zurückgreifen!
>
> Aber dort suche ich vergeblich eine Funktion, mit der ich den Status der
> einzelnen Flags abfragen kann.
>
> Bei der Standard-Lib gibt es ja folgendermaßen realisiert werden
>
>  while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE)==RESET);
>
> ... und so ein Funktion wie GetFlagStatus wird es doch wohl auch bei der
> HAL-Lib geben?

HAL_SPI_GetState

Gruß Herby
Gast #4960071
Lesenswert?

Immer wieder köstlich dieser HAL-Sumpf.

Sie blockiert. Nein sie blockiert nicht.
Sie blockiert, aber nicht richtig.

Das passende Statusbit ist schnell identifiziert.
(Und wäre im Handumdrehen per Registerzugriff auszulesen.)

Stattdessen wundersame Würgarounds wie Callbacks, Int & DMA.

Dann die Preisfrage, wie die entsprechende HAL-Funktion denn
nun wieder heisst...

Har har har.
Gast #4960079
Lesenswert?

Seit ich mich mit STM32 beschäftige (ca 1 Woche) lese ich täglich von 
Problemen mit der HAL und bekomme damit die Bestätigung, dass meine 
Entscheidung, sie nicht zu benutzen, richtig war.

Wenn schon eine Hardware-Abstraktion, dann würde ich lieber gleich 
Arduino nehmen. Aber ehrlich gesagt komme ich mit Registern prima 
zurecht.

Wer Floppy-Laufwerke an Druckerports programmiert hat, für den sind 
Register in Mikrocontrollern luxuriöser Pippikram.
Gast #4960091
Lesenswert?

Stefan U. schrieb:
> Seit ich mich mit STM32 beschäftige (ca 1 Woche)

Stefan U. schrieb:
> Wenn schon eine Hardware-Abstraktion, dann würde ich lieber gleich
> Arduino nehmen. Aber ehrlich gesagt komme ich mit Registern prima
> zurecht.

Ich "sehe" dir diese Woche zu .... denke nur daran dass nicht
alle Register eines Controller nach Reset auch den Power-Up
Zustand bekommen. Die SPL-Aufrufe zum Setzen von Registern
dagegen machen nach meinem Eindruck alles clean damit keine
unvorhergesehenen Überraschungen auftreten. Daher ist die
Benutzung der SPL meine VOrgehensweise wenn es sich nicht um
zeitkritische Dinge handelt.
#4960350
Lesenswert?

Also ich hatte natürlich vor meinem Beitrag die Implementierung der 
HAL-Funktion(en) auf die schnelle überflogen.

So wie ich das gesehen habe, wird das SPI BSY Flag ausgewertet, und das 
sollte doch eigentlich korrekt sein.

Es sei denn das Timeout wäre zu kurz gesetzt. Es wird in Ticks 
angegeben, wobei ein Tick per Vorgabe 1ms entspricht.

EDIT: Hier der Codeschnipsel aus der SPI HAL Lib:
1
/* Procedure to check the transaction complete */
2
  if(SPI_WaitFifoStateUntilTimeout(hspi, SPI_FLAG_FTLVL, SPI_FTLVL_EMPTY, Timeout) != HAL_OK)
3
  {
4
    hspi->ErrorCode |= HAL_SPI_ERROR_FLAG;
5
    return HAL_TIMEOUT;
6
  }
7
  if(SPI_WaitFlagStateUntilTimeout(hspi, SPI_FLAG_BSY, RESET, Timeout) != HAL_OK)
8
  {
9
    hspi->ErrorCode |= HAL_SPI_ERROR_FLAG;
10
    return HAL_TIMEOUT;
11
}
Gast #4960846
Lesenswert?

> denke nur daran dass nicht
> alle Register eines Controller nach Reset auch den Power-Up
> Zustand bekommen.

Danke für den Hinweis, das muss ich mir notieren - finde ich nämlich 
ziemlich überraschend. Woran erkenne ich im Datenblatt oder 
Referenzhandbuch, welche Regsietrs das sind?

Die Default-Werte habe ich gefunden, heisst das nun Default nach reset 
oder Default nach Powerup?
Gast #4963241
Lesenswert?

STM Apprentice schrieb:
> Beitrag "[STM32F4xx] SPI Optimierung"

Ich habe noch eine Frage zu diesem Beitrag:

while ((SPI1->SR & SPI_I2S_FLAG_TXE) == 0);
SPI1->DR = (uint8_t)(val >> 8);

Warum befindet sich die Funktion zum Senden in der While-Schleife?

Ich verstehe diese Schleife so, dass solange gesendet wird, bis der 
"Sendespeicher" leer ist(Transmit Buffer empty Flag).

Aber dieser Speicher wird wohl standardmäßig leer sein, bis ich dort 
eben val>>8 eintrage. Folglich würde es nach meiner Überlegung nie zum 
Senden kommen.

Wo liegt nun mein Denkfehler???
Und wann macht die While-Schleife Sinn? Bei mir funktioniert es auch 
ohne diese.
#4963359
Lesenswert?

Stefan U. schrieb:
> Die Default-Werte habe ich gefunden, heisst das nun Default nach reset
> oder Default nach Powerup?

Es gibt doch nur die Reset-Werte und da verhält sich mit Ausnahme der 
Backup-Domain (RTC und Co) ein Power-Reset wie ein System-Reset.

Edit: Jedenfalls ist das beim F103 so, kann bei anderen Familien anders 
sein. Außerdem sind natürlich nicht alle Register ab Reset mit 0x0 
initialisiert. Nur damit keine Missverständnisse aufkommen. Bei jedem 
STM32 sollte es am Ende eines jeden Kapitels eine Übersicht "XYZ 
Register Map" geben, wobei XYZ alles sein kann, von ADC bis TIM16/TIM17.

zigner schrieb:
> while ((SPI1->SR & SPI_I2S_FLAG_TXE) == 0);
> SPI1->DR = (uint8_t)(val >> 8);
>
> Warum befindet sich die Funktion zum Senden in der While-Schleife?
>
> Ich verstehe diese Schleife so, dass solange gesendet wird, bis der
> "Sendespeicher" leer ist(Transmit Buffer empty Flag).

Da steht gar nichts in der while-Schleife. Da wird so lange gewartet bis 
das TXE-Flag gesetzt ist, sonst nichts. Die Schleife ist leer, da es 
keine geschweiften Klammern gibt und das Semikolon das Ende der Schleife 
markiert.

Da steht gewissermaßen:
1
while ((SPI1->SR & SPI_I2S_FLAG_TXE) == 0) {
2
    // hier passiert genau nichts
3
};
#4964423
Lesenswert?

...man muss aber genau bei diesem Flag aufpassen: Es bedeutet, dass der 
Transmit FIFO Platz für Daten hat.

Es bedeutet aber NICHT, das alles aus dem FIFO gesendet wurde.

Dafür muss das BSY Flag abgefragt werden.

D.h. exakt für den Zweck welchen der TO im Sinn hat(te) (Ende der 
Übertragung abwarten um das CS Signal zu deaktivieren) sollte man das 
BSY Flag abfragen und NICHT das TXE Flag.
Gast #4964442
Lesenswert?

Markus M. schrieb:
> D.h. exakt für den Zweck welchen der TO im Sinn hat(te) (Ende der
> Übertragung abwarten um das CS Signal zu deaktivieren) sollte man das
> BSY Flag abfragen und NICHT das TXE Flag.

Steht in dem verlinkten Thread ja eigentlich genau drin, das
ist genau der Grund warum er eröffnet wurde .....

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