Multiplexen von SPI-Slaves mit niedriger Geschwindigkeit mit einem SPI-Master mit hoher Geschwindigkeit (Zeitteilung?)

Ich habe 12 SPI-Slaves, die SPI mit einer maximalen Taktrate von 2 MHz unterstützen. Der SPI-Master (ein ESP32 ) kann mit bis zu 80 MHz (und ganzzahligen Divisionen davon) laufen. Meine Slaves sind alle 8-Kanal-ADCs ( MCP3208 ), die ich ständig abfragen muss. Daher möchte ich irgendwie den Durchsatz maximieren.

Ich dachte, dass es möglich sein könnte, Zeitmultiplex auf den Slaves durchzuführen, indem der Master mit 40 MHz betrieben und 20 Zeitabschnitte erstellt werden, von denen jeder eine 2-MHz-Leitung für einen potenziellen Slave ist. Dies würde meine Slaves effektiv zu einem einzigen SPI-Gerät mit höherer Geschwindigkeit kombinieren (während alle Bits für den Master verschachtelt werden). Leider finde ich keine Quellen zu diesem Thema.

Unten ist ein Diagramm, das das Konzept zeigt, indem ein externer Taktteiler verwendet wird, um einen 2-MHz-Takt aus dem 40-MHz-Basistakt zu erzeugen (der idealerweise für jeden Slave versetzt werden sollte), ein Multiplexer für MOSI und ein Demultiplexer für MISO-Leitungen.

Leider fehlt mir das nötige Hintergrundwissen, um beurteilen zu können, ob das überhaupt möglich ist und ob die benötigten ICs überhaupt existieren.

Konzept Schaltung

Wenn der esp32 den SPI-Bus bitbangen muss, anstatt das SPI-Peripheriegerät zu verwenden, ist es ziemlich unwahrscheinlich, dass er immer noch 40 MHz erreichen kann.
Oder wenn Sie eine externe Schaltung wie die von Ihnen gezeigte verwenden, kann der esp32 die empfangenen Daten bei 40 MHz entschachteln?
Wenn alle Slaves 2 MHz haben, warum nicht einfach den SPI-Kanal mit 2 MHz betreiben? Alles wird sowieso auf diese Geschwindigkeit verlangsamt ... Ich sehe keinen Vorteil darin, den Master 40-mal schneller als die Slaves zu betreiben. Die Slaves können Daten nicht 40-mal schneller ausgeben, wenn Sie sie also zurücklesen müssen Um zu berücksichtigen, dass 1 Bit-Änderung 40-mal länger ist als normalerweise (weil der Impuls 40 Taktzyklen statt 1 dauert), benötigen Sie eine komplizierte Routine, um ihn zu decodieren. Ich denke, Sie haben den falschen ADC gewählt und eine Lösung "repariert", die einfacher ist, indem Sie den richtigen ADC auswählen.
@RonBeyer Denn wenn ich alles mit 2 MHz betreibe, reduziere ich den Durchsatz effektiv auf 1/12 pro Slave und verschwende zusätzliche Samples der ADCs. Es stimmt, dass ich andere ADCs hätte wählen können, aber ich konnte nichts in der gleichen Preisklasse (~ 2 $ pro ADC) finden, das mir dies ermöglichen würde.
Auch der ESP verwendet eine Hardware-SPI-Schnittstelle, die über DMA auf den Speicher zugreift. Da es sich also auch um ein Dual-Core-System handelt, sollte ich in der Lage sein, die Daten schnell genug zu dekodieren.
Der ESP32 hat auch mindestens 2 Master-SPI-Kanäle, sodass Sie diese aufteilen können (6 Slaves pro Kanal). Ich denke, es hat tatsächlich 3, also könnten Sie 4 Slaves pro Kanal haben und mehrere Transaktionen gleichzeitig durchführen.
@RonBeyer Ja, das würde das Problem zumindest um den Faktor 2/3 mildern. Trotzdem bin ich immer noch neugierig, ob diese Zeitteilungssache möglich wäre.

Antworten (3)

Das halte ich für überhaupt nicht praktikabel.

Erstens, wie werden Sie die SPI-Schnittstelle dazu bringen, Daten zu verschachteln? Ich bezweifle sehr, dass Sie dies mit einem dedizierten synchronen seriellen Peripheriegerät erreichen können, und wie @ThePhoton betont, wird die effektive Taktrate dramatisch sinken, wenn Sie die Schnittstelle bit-bangen müssen.

Sie benötigen für jeden ADC einen separaten 2-MHz-Takt, damit jedes Gerät die entsprechende Taktflanke nur dann sieht, wenn sein korrekter Datenwert vorhanden ist. Sie können die Datenleitungen nicht einfach demuxen, es sei denn, Sie fügen Speicher für jede Datenleitung hinzu, damit sie den richtigen Wert enthält, bis die Taktflanke auftritt.

Für eingehende Daten müssen Sie das Gegenteil tun ... erfassen Sie jede ADC-MISO-Leitung an der entsprechenden Taktflanke.

Sie haben Recht mit den Slave-Eingängen, aber ich denke, dass ich in diesem Fall den MOSI-Muxer überspringen und alle mit genau demselben 2-MHz-Takt ansteuern kann, wodurch alle Slaves effektiv gleichzeitig arbeiten. (Weil die MOSI-Nachricht an alle ADCs immer gleich ist). Bei eingehenden MISO-Daten muss ich nicht genau an der Taktflanke erfassen, da die Slaves den Wert für den gesamten Taktzyklus halten. Und da ich nur 12 Slaves habe, sollte es keine Probleme mit Anstiegs- und Abfallzeiten geben, wenn ich die ersten und letzten 4 Unterzyklen überspringe.
Abgesehen davon hast du natürlich recht, das ist sehr unpraktisch. Ich war nur neugierig, ob es funktionieren würde

Zusätzlich zu dem, was in Ihrem Diagramm gezeigt wird, benötigen Sie auch einen Zähler, um die SEL-Signale für die [De] Multiplexer zu erzeugen. Und dieser Zähler muss durch 12 Zustände statt durch 8 oder 16 zählen.

Bevor Sie fertig sind, implementieren Sie all dies in einem CPLD.

Ich würde stattdessen empfehlen, einen anderen ADC zu finden. Entweder ein Mehrkanalgerät mit einer schnelleren SPI-Schnittstelle. Oder ein paralleler Ausgang, mit dem Sie die Rücklesungen über so etwas wie einen seriell-parallelen Puffer 74LVC595A durchführen können (der dann bis weit in die 10 MHz von Ihrem SPI-Port lesen kann).

Ja, wahrscheinlich die beste Idee. Ich denke, ich werde einen 16-Kanal-ADC mit 20 MHz SPI-Takt verwenden.

Die ADC-Chips funktionieren nicht mit einer höheren Taktfrequenz als den im Datenblatt angegebenen 2 MHz.

Am besten teilen Sie das vom MSP erzeugte MCLK-Signal herunter und stellen es allen ADCs parallel zur Verfügung. Aus dem Datenblatt geht hervor, dass die ADC-Chips eine maximale Umwandlungsrate von 100.000 Samples/Sekunde haben, und dies hängt von der Uhr ab, die den Chip antreibt.

Eine Möglichkeit, wie Sie dies angehen könnten, wäre, das Ganze zu bit-bangen. Wenn Sie gemeinsame MCLK-, MOSI- und /CS-Leitungen verwenden, wobei jeder MISO-Pin mit einem separaten GPIO-Pin verbunden ist, können Sie einen gemeinsamen Befehl an alle Chips gleichzeitig senden. Das Lesen der Werte von allen 12 ADCs würde dann durch Lesen der GPIO-Register bei jedem Zyklus des Bit-Bang-Takts erfolgen.

Bei den meisten Mikros wäre es bei sorgfältiger Auswahl der GPIO-Pins möglich, den Zustand von 12 Pins mit nur wenigen Anweisungen zu lesen: ein byte- oder wortweites Lesen in ein Register und eine Bitverschiebung im Register, die 12 Mal wiederholt wird für die 12-Bit-ADC-Werte. Das Register würde dann den zu sortierenden Bitstrom in Software enthalten, möglicherweise in einem anderen (nicht zeitkritischen) Codeabschnitt.

Ich habe noch nie ein ESP32 verwendet; Ich weiß nicht, wie praktisch / möglich es wäre, die GPIO-Pins auf diese Weise zu lesen.

Wenn Sie das GPIO-Timing des ESP32 aufgrund von Interrupts nicht steuern können (während es beispielsweise das WLAN und den Stack verwaltet), kann es sich lohnen, einen billigen Mikrocontroller hinzuzufügen, der zwischen dem ESP32 und den 12 ADC-Chips sitzt und alles verarbeitet davon für dich; Stattdessen wird ein einzelner SPI- oder UART-verbundener Slave präsentiert, den Sie mit den im ESP32 vorhandenen hardwareunterstützten Blöcken verwenden könnten.