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?
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.
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"
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.
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.
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?
Laut HAL-Manual blockt die Funktion. Was ist für ein Timeout gesetzt? Alternativ mit Int oder DMA und CallBack-Fkt versuchen. Gruß Herby
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.
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
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.
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.
> Wer Floppy-Laufwerke an Druckerports programmiert hat
Das machen richtige Super-IO-Käfer wie der FDC37C672
mit den ganz normalen Floppy-Registern...
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.
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
> 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?
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.
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.
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
...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.
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 .....
Jupp, wollte es nur nochmal erwähnen, da nur noch von dem TXE Flag gesprochen wurde.
Bitte melde dich an um einen Beitrag zu schreiben. Anmeldung ist kostenlos und dauert nur eine Minute.
Bestehender Account
Schon ein Account bei Google/GoogleMail? Keine Anmeldung erforderlich!
Mit Google-Account einloggen
Mit Google-Account einloggen
Noch kein Account? Hier anmelden.