Wie nutzt man SPI (Master/Slave) am besten?

Dies ist ein weiterer/neuer Einblick in Bezug auf meine vorherige Frage Messages for SPI protocol .

Eine Idee aus dieser Frage ist, die SS-Leitung zu verwenden, um zu wissen, dass eine neue Nachricht vom Master an den Slave gesendet wird. Der Master ist der STM32 und der Slave der Arduino, siehe unten:

  Slave   <---  Master
 Arduino  (SPI) STM32
   |            ^ ^ ^
   V            | | |
RS485/DMX512   3x UART/MIDI

Der Master empfängt MIDI-Signale von verschiedenen Quellen, verarbeitet sie, sendet (veränderte) MIDI-Nachrichten zurück und sendet SPI-Nachrichten an den Arduino, der die DMX-Signale sendet.

So weit so gut, ich implementiere gerade den Arduino-Code (inklusive einer Windows-Testanwendung).

Der Grund, warum ich ein Arduino für RS485/DMX verwende, liegt hauptsächlich darin, dass ich es nicht auf einem STM32 zum Laufen bringen konnte, aber auch, um die Rechenleistung des STM32 zu entlasten.

Ich brauche jedoch mehr SRAM auf dem Arduino, also werde ich einen SPI-SRAM-Chip (32K256) verwenden. Das Problem ist, dass ich nicht sicher bin, ob ich den Arduino zum Sklaven machen kann.

SPI RAM 32K256
    |(SPI)
    V
   Slave   <---  Master
  Arduino  (SPI) STM32
    |            ^ ^ ^
    V            | | |
RS485/DMX512     3x UART/MIDI

Einige Dinge, die ich in Betracht gezogen habe:

  • Den Arduino zum Master machen und den STM32 abfragen (was wahrscheinlich zu meinen nutzlosen Umfrageereignissen führt).
  • Beibehaltung des STM32-Masters und wenn ein Sendeversuch nicht wiederholt werden kann.
  • Mit I2C, aber ich denke, SPI ist einfacher zu implementieren.

Afaik muss die Kommunikation vollständig synchron sein, aber ich bin mir nicht sicher, ob es aufgrund von Puffern in den SPI-Peripheriegeräten zu einer gewissen „Entspannung“ kommt.

Noch ein paar Hintergrundinformationen zum gesamten Projekt:

  • Der STM32 liest Eingänge von verschiedenen MIDI-Eingängen (hauptsächlich Synthesizer)
  • Zu einem späteren Zeitpunkt werde ich vielleicht auch andere Eingänge (nicht MIDI) hinzufügen.
  • Der STM32 verarbeitet diese Nachrichten und sendet MIDI-Nachrichten und -Befehle für den Arduino-Slave.
  • Der Arduino-Slave verarbeitet die Nachrichten, die so etwas wie sein können (alle vorderen DMX-Lichter zwischen Rot und Blau ein- und ausblenden lassen, Lichter X und Y grün machen, Stroboskop mit Geschwindigkeit 50 einschalten usw.). Diese Nachrichten haben alle die gleiche Länge (18 Bytes).
  • Für jedes DMX-Licht (bisher 17, kann aber in Zukunft zunehmen) habe ich eine Klasse (Instanz), die Informationen (max. 64 Bytes) pro Licht enthält. Dies passt nicht in ein Arduino, daher verwende ich externes SRAM.
  • So oft wie möglich (aber mindestens alle paar ms) verarbeitet der Arduino ein Licht, indem er seine Daten aus dem SRAM liest und die Fade-Farben ändert, und verarbeitet auch neue Befehle vom Master, falls vorhanden. Und schließlich die geänderten Daten in SRAM zurückspeichern.

Alle Erkenntnisse wären hilfreich.

Abhängig von der benötigten Geschwindigkeit ist die Implementierung von SPI auf Bit-Banging-Basis ziemlich einfach und normalerweise sehr tolerant gegenüber variablen Bit-Timings.
@PeterSmith Für die Arduino-32K256-Verbindung möchte ich eine sehr schnelle Kommunikation, für die Arduino-STM32-Verbindung brauche ich (wahrscheinlich) keine hohen Geschwindigkeiten. Eigentlich glaube ich nicht, dass ich die SPI-Geschwindigkeit sowieso nicht einfach ändern kann, also muss ich einen "guten" Wert finden.
Ein Einblick: Slave-Kommunikationen zurück zu einem Master sind normalerweise am anfälligsten, um korrekt empfangen zu werden.
Basierend auf Ihrem zweiten Diagramm scheint es, dass der Arduino eine SPI-Master-Schnittstelle benötigt, um mit dem SRAM zu kommunizieren, und eine SPI-Slave-Schnittstelle, um Nachrichten vom STM32 zu empfangen. Gibt es einen Grund, warum dies nicht machbar ist?
@Andyaka, was wäre also eine gute Lösung, wenn der Slave 2 SPI-Geräte verwendet? (und hat nur eine SPI-Peripherie)
@DaveTweed ... ja ... ein Arduino hat nur ein SPI-Peripheriegerät.
Also dann bit-bang oder ein anderes Protokoll verwenden. Sie sagen, dass die STM -> Arduino-Verbindung eine relativ geringe Bandbreite hat - können Sie dazu konkrete Zahlen nennen?
Klingt nach einem XY-Problem. Wofür braucht man 32 Kilobyte SRAM auf Arduino? Ich würde mir vorstellen, dass Arduino nur der Teil ist, der kontinuierlich das letzte vollständige DMX-Paket sendet, das der STM32 senden soll. Bitte beschreiben Sie genauer, welche MCU was im System macht.
@DaveTweed meinst du, überhaupt kein SPI/I2C-Protokoll zu verwenden? Daran habe ich nicht gedacht, wäre aber möglich. ... wahrscheinlich ist die tatsächliche Anzahl sehr gering (etwa 20 Bytes alle 20 ms, aber wahrscheinlich kann es noch langsamer sein).
Das habe ich nicht gesagt. Siehe den ersten Kommentar von @PeterSmith.
@Justme Ich habe es am Ende hinzugefügt (hoffe, es reicht).
@DaveTweed Entschuldigung, ich bin etwas verwirrt ... gibt es eine "nichts schlagende SPI-Implementierung"?

Antworten (1)

Den Arduino zum Master machen und den STM32 abfragen (was wahrscheinlich zu meinen nutzlosen Umfrageereignissen führt)

Vielleicht können Sie eine zusätzliche "Interrupt" -Leitung vom STM32 zum Arduino haben, um zu signalisieren, wann Daten verfügbar sind. Es könnte direkt einen Interrupt auf dem Arduino auslösen.

schematisch

Simulieren Sie diese Schaltung – Mit CircuitLab erstellter Schaltplan

Wenn Sie Datenpakete mit fester Größe haben, können die STM32 SPI + DMA-Peripheriegeräte den SPI-Slave-Verkehr autonom verarbeiten, ohne CPU-Eingriff, nachdem die Interrupt-Leitung ausgelöst wurde (OK, das Signal muss eventuell zurückgesetzt werden, ein DMA-Transfer-Complete-Interrupt oder ein Eins -shot timer kann das).

Das klingt sehr brauchbar, ich habe SPI + DMA nie ausprobiert, aber es ist gut, das zu versuchen.
Danke ... und zwei kleine zusätzliche Fragen (ich glaube nicht, dass der Arduino DMA hat, aber ich denke, ich kann es auf dem STM32 verwenden (auch nützlicher, weil das das kritische Gerät sein wird) und was bedeutet der NSS-Pin (N??? Slave Select) ?
@MichelKeijzers 1. Ja, DMA ist auf der STM32-Seite. Es kann das SPI-Datenregister mit voller Geschwindigkeit füttern, ohne die Programmausführung merklich zu verlangsamen (ich verwende es zB, um SPI-Anzeigen im Hintergrund zu aktualisieren). 2. Aus irgendeinem Grund wird Chip Select NSSin der ST-Dokumentation aufgerufen. Ich nehme an , ich habe S lave Select gewählt .
Danke für die zusätzlichen Informationen (übrigens plane ich auch, ein Display hinzuzufügen, aber ich beabsichtige, I2C dafür zu verwenden, da ich bereits ein I2C 1602- und 2004-Modul habe. Das STM wird hoffentlich (wenn ich den obigen Teil jemals fertigstelle). ) erhalten mehr Eingänge (wie IR, nRF und vielleicht noch mehr) und werden durch einen STM32F4VET6 (anstelle von STM32F1C8T6) ersetzt.
@MichelKeijzers Wenn Sie den ST-Controller aufrüsten, könnte er sicherlich etwas RAM und Zyklen sparen, um auch die Datenstrukturen der Lichter zu speichern, wodurch der zusätzliche SRAM-Teil unnötig wird.
stimmt, aber dann müsste ich sehr schnell sehr spezifische Befehle senden. Ich meine, jetzt kann ich zum Beispiel von STM->Arduino senden: Fade lights from red to green. Auf dem Arduino wird dies in alle paar ms übersetzt, um das Licht langsam zu ändern.
Wenn ich das auf dem STM machen würde, dann 1) würde ich viele Befehle senden, 2) das STM müsste viel mehr Arbeit leisten ... Was ich tun könnte, ist ein weiteres STM dazwischen zu fügen, um die gesamte Verarbeitung zu erledigen , also STM (liest MIDI und sendet Befehle) -> STM (Befehl-> DMX-Nachrichten) -> Arduino (tatsächlich DMX-Nachrichten senden). Das würde ein zusätzliches STM erfordern, aber ich spare beim 32K256, und ich brauche nur einen SPI beim Arduino.