Hallo, wenn man einen STM32F4 über die cubeMX HAL als SPI-Master konfiguriert, kann man bei der Konfiguration wählen, ob der CS- bzw. NSS-Pin per Hardware oder per Software gesteuert werden soll. Bei spi.Init.NSS = SPI_NSS_HARD übernimmt der SPI-Master die Steuerung der CS-Leitung. Das heißt, wenn Daten über MOSI gesendet werden, zieht der SPI-Master die CS-Leitung automatisch auf Low. Bei spi.Init.NSS = SPI_NSS_SOFT muss man sich selbst um den CS-Pin kümmern. Das heißt man definiert einen beliebigen Pin als ganz normalen Output ohne alternative Funktion und zieht diesen vor dem Senden dann manuell auf Low. Nun frage ich mich aber, wie das bei einer Slave-Konfiguration funktioniert. Ein SPI-Slave soll ja nur aktiv werden, wenn seine CS-Leitung vom Master auf Low gezogen wird. Nun könnte man ja beim Slave auf die Idee kommen, spi.Init.NSS = SPI_NSS_SOFT zu konfigurieren und dann den CS-Pin als Input konfigurieren? In diesem Fall wüsste der Slave doch aber gar nicht, dass der CS-Pin als Input existiert? Woraus ich schlussfolgern würde, dass bei der Slave-Konfiguration nur spi.Init.NSS = SPI_NSS_HARD zulässig ist (der entsprechende CS-Pin bekommt dann als alternative Funktion den SPI zugewiesen)? Viele Grüße
Der SPI hat zusätzlich noch das SSI (Slave Select Internal) bit, wenn SPI auf Software SS konfiguriert ist, wird der Zustand dieses bit verwendet, also auch bei Slave. Dazu müsste also ein externer Interrupt auf der SS Leitung verwendet werden und in dem Interrupt wird das SSI bit gesetzt. Wozu das gut sein soll, kann ich mir zwar nicht vorstellen, aber funktionieren würde es.
Alex D. schrieb: > Der SPI hat zusätzlich noch das SSI (Slave Select Internal) bit, wenn > SPI auf Software SS konfiguriert ist, wird der Zustand dieses bit > verwendet, also auch bei Slave. Dazu müsste also ein externer Interrupt > auf der SS Leitung verwendet werden und in dem Interrupt wird das SSI > bit gesetzt. Vielen Dank! Alex D. schrieb: > Wozu das gut sein soll, kann ich mir zwar nicht vorstellen, aber > funktionieren würde es. Man könnte erst den DMA starten oder mit Pollen beginnen, nachdem CS wirklich auf Low gezogen wurde. So könnte sich der Slave über CS mit dem Master synchronisieren. Bei STM32 ist es aber auch möglich an einem hardwaregesteuerten CS ein Interrupt zu konfigurieren (Pins, die eine Alternate function wie z.B. SPI erhalten, können zusätzlich auch auf Interrupts konfiguriert werden). So gesehen, wäre es eigentlich völlig egal, für welche Variante man sich entscheidet.
Johannes B. schrieb: > Man könnte erst den DMA starten oder mit Pollen beginnen, nachdem CS > wirklich auf Low gezogen wurde. So könnte sich der Slave über CS mit dem > Master synchronisieren. Bei STM32 ist es aber auch möglich an einem > hardwaregesteuerten CS ein Interrupt zu konfigurieren (Pins, die eine > Alternate function wie z.B. SPI erhalten, können zusätzlich auch auf > Interrupts konfiguriert werden). So gesehen, wäre es eigentlich völlig > egal, für welche Variante man sich entscheidet. Wieso nimmst du den CS nicht als SPI_NSS_HARD und lässt den DMA arbeiten? Das ist schneller und kostet keine Rechenleistung. Kann dir nicht sagen wie man das in Cube konfiguriert, aber mit den LL-Drivern geht das problemlos. Wenn du den CS via externen Interrupt nutzt, kann es bei schneller Datenübertragungen zu langsam sein den DMA von Hand anzuwerfen. (Erfahrung musste ich bereits machen :))
Viele Programmierer denken, /CS ist überflüssig. Und solange beide MCs gleichzeitig bestromt werden, geht das auch ne ganze Weile gut. Später merkt man aber, daß es unzuverlässig ist. Dann wird mit dem Timerinterrupt ein SW-Sync als Krücke dazu gebastelt.
mr. mo schrieb: > Wieso nimmst du den CS nicht als SPI_NSS_HARD und lässt den DMA > arbeiten? Das ist schneller und kostet keine Rechenleistung. Kann dir > nicht sagen wie man das in Cube konfiguriert, aber mit den LL-Drivern > geht das problemlos. Für meinen Anwendungsfall tauschen sich Master und Slave Nachrichten fester Länge aus. Der DMA soll im Slave, nachdem die feste Länge über SPI empfangen wurde, ein Interrupt triggern. Das Problem ist folgendes: Mikrocontroller A startet und beginnt als SPI-Master etwas zu versenden. Während Mikrocontroller A noch am Senden ist, startet Mikrocontroller B und beginnt sofort als SPI-Slave etwas zu empfangen. Mikrocontroller B empfängt dann nur den letzten Teil der Nachricht. Der Interrupt des DMAs wird dadurch nicht ausgelöst, weil noch nicht die komplette Länge empfangen wurde. Beim nächsten Schleifendurchlauf sendet Mikrocontroller A dann die nächste Nachricht fester Länge. In Mikrocontroller B löst der DMA dann ein Interrupt aus, weil der DMA-Puffer nun die Länge der Nachricht erreicht hat. Fälschlicherweise glaubt dann Mikrocontroller B er hat nun eine zusammengehörige Nachricht empfangen, aber eigentlich besteht diese Nachricht aus zwei unterschiedlichen Nachrichten vom Master. Deshalb habe ich mir Gedanken gemacht, wie man das synchronisieren könnte. Dabei kamen mir zwei Ideen. A) Den DMA erst starten, wenn CS vom Master auf Low gezogen wurde (daher meine Frage hier im Forum). B) Der Master sendet mehrmals eine bestimmte Reihenfolge von Startbytes. Der Slave schreibt alles, was er empfängt, in einen größeren Puffer, durchsucht diesen Puffer nach den Startbytes und kann sich so mit dem Master synchronisieren. mr. mo schrieb: > Wenn du den CS via externen Interrupt nutzt, kann es bei schneller > Datenübertragungen zu langsam sein den DMA von Hand anzuwerfen. > (Erfahrung musste ich bereits machen :)) Dann fällt die Lösung A) wohl flach. Aber der Slave könnte stattdessen Pollen, eine Antwort an den Master senden, wenn er synchron ist und danach erst den DMA anwerfen.
Johannes B. schrieb: > Deshalb habe ich mir Gedanken gemacht, wie man das synchronisieren > könnte. Dabei kamen mir zwei Ideen. A) Den DMA erst starten, wenn CS vom > Master auf Low gezogen wurde (daher meine Frage hier im Forum). B) Der > Master sendet mehrmals eine bestimmte Reihenfolge von Startbytes. Der > Slave schreibt alles, was er empfängt, in einen größeren Puffer, > durchsucht diesen Puffer nach den Startbytes und kann sich so mit dem > Master synchronisieren. Wird bei deiner Übertragung CS während der ganzen Übertragung LOW gehalten? Dann kannst du einfach bei steigender Flanke von CS am Slave den Buffer verwerfen, falls dieser nicht voll ist. Wenn CS immer nur für 1 Byte LOW geht, dann is es wohl am besten ein Protokoll darüber zu bauen, bei dem der Start und das Ende eindeutig erkannt werden können.
Alex D. schrieb: > Wird bei deiner Übertragung CS während der ganzen Übertragung LOW > gehalten? Dann kannst du einfach bei steigender Flanke von CS am Slave > den Buffer verwerfen, falls dieser nicht voll ist. > > Wenn CS immer nur für 1 Byte LOW geht, dann is es wohl am besten ein > Protokoll darüber zu bauen, bei dem der Start und das Ende eindeutig > erkannt werden können. CS wird während der ganzen Übertragung LOW gehalten. Ich finde, den Puffer bei steigender Flanke zu verwerfen, ist eine sehr gute Idee. Wenn nach der steigenden Flanke an CS der DMA noch nicht fertig ist, weiß man, dass die Nachricht nicht vollständig war. Dann setzt man die Adresse des DMA manuell wieder an den Anfang und ist somit bei der nächsten Nachricht synchron.
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.