Forum: Mikrocontroller und Digitale Elektronik STM32F0: Mit HAL-Lib überprüfen, ob Datenübertragung über SPI abgeschlossen ist?


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 zigner (Gast)


Bewertung
0 lesenswert
nicht 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?

von Markus M. (adrock)


Bewertung
0 lesenswert
nicht lesenswert
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.

von STM Apprentice (Gast)


Bewertung
0 lesenswert
nicht 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"

von STM Apprentice (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Markus M. schrieb:
> Du kannst also Dein CS Signal deaktivieren wenn die Funktion
> zurückgekehrt ist.

Vermutlich nicht wenn das oben im Link beschriebene Problem
zuschlägt.

von zigner (Gast)


Bewertung
0 lesenswert
nicht 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.

von zigner (Gast)


Bewertung
0 lesenswert
nicht 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?

von Herbert P. (Gast)


Bewertung
0 lesenswert
nicht lesenswert
Laut HAL-Manual blockt die Funktion. Was ist für ein Timeout gesetzt?

Alternativ mit Int oder DMA und CallBack-Fkt versuchen.

Gruß Herby

von STM Apprentice (Gast)


Bewertung
0 lesenswert
nicht 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.

von Herbert P. (Gast)


Bewertung
0 lesenswert
nicht 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

von --- (Gast)


Bewertung
0 lesenswert
nicht 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.

von Stefan ⛄ F. (stefanus)


Bewertung
-1 lesenswert
nicht 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.

von STM Apprentice (Gast)


Bewertung
0 lesenswert
nicht lesenswert
--- schrieb:
> Har har har.

Narzissmus leben ist eine Zier, doch weiter kommt man ohne ihr.

von --- (Gast)


Bewertung
0 lesenswert
nicht lesenswert
> Wer Floppy-Laufwerke an Druckerports programmiert hat

Das machen richtige Super-IO-Käfer wie der FDC37C672
mit den ganz normalen Floppy-Registern...

von STM Apprentice (Gast)


Bewertung
1 lesenswert
nicht 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.

von Markus M. (adrock)


Bewertung
0 lesenswert
nicht 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
}

: Bearbeitet durch User
von Stefan ⛄ F. (stefanus)


Bewertung
0 lesenswert
nicht 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?

von STM Apprentice (Gast)


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

Mein Nick ist Programm, mein Wissen ist auch (sehr) beschränkt.

von zigner (Gast)


Bewertung
0 lesenswert
nicht 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.

von Christopher J. (christopher_j23)


Bewertung
0 lesenswert
nicht 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
};

: Bearbeitet durch User
von Markus M. (adrock)


Bewertung
0 lesenswert
nicht 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.

von STM Apprentice (Gast)


Bewertung
0 lesenswert
nicht 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 .....

von Markus M. (adrock)


Bewertung
0 lesenswert
nicht lesenswert
Jupp, wollte es nur nochmal erwähnen, da nur noch von dem TXE Flag 
gesprochen wurde.

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.