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?
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.
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:
> 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:
...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 .....