ADS1234 und STM32L

Ich versuche, das SPI2-Peripheriegerät auf dem STM32L471RG- Mikrocontroller zu verwenden, um mit dem ADS1234 zu kommunizieren , und wollte meine Gedanken an einigen von Ihnen erfahreneren Firmware-Entwicklern vorbeiführen!

Im Moment verwende ich die interne Uhr des ADC, daher muss ich mich hauptsächlich auf die DRDY/DOUT- und SCLK-Pins konzentrieren. Ich werde eine Initialisierungsfunktion haben, die die anderen ADC-Pins konfiguriert.

Das Referenzhandbuch des STM32L spricht über die verschiedenen möglichen SPI-Modi, was zu meinen Fragen führt:

  1. Ich plane die Verwendung von Simplex-Empfang mit SPI2 - klingt dieser Modus basierend auf den Wellenformen der ADS1234-Schnittstelle vernünftig?
  2. Der ADS1234 ist 24-Bit und der STM32L geht nur bis zu 16-Bit im Puffer. Mein Gedanke ist, es für 12-Bit zu konfigurieren und zwei Übertragungen durchzuführen, obwohl ich mir nicht sicher bin, ob dies mit irgendetwas in Konflikt steht?
  3. Da die Verwendung der DRDY-Funktion nicht vollständig Teil des SPI-Protokolls ist, frage ich mich, wie dies eine Datenübertragung auslösen kann. Wenn der DRDY/DOUT-Pin-Status von High auf Low wechselt (was anzeigt, dass Daten bereit sind), sollte ich für ein Interrupt-on-Change-Ereignis (IOC) konfigurieren und dann mit dem Abschließen einer Übertragung beginnen?

Unten ist die Wellenform des Datenabrufs des ADS1234.

ADS1234-Datenabruf

Vielen Dank für jede Hilfe. Ich mache mir hauptsächlich Sorgen um die Logistik von allem.

Antworten (3)

Ich würde es ganz anders machen.

  1. Stellen Sie den SPI2 MISO-Pin als GPIO-Eingang ein. Setzen Sie den EXTI (fallende Flanke) Interrupt auf diesen Pin
  2. Ändern Sie im EXTI-Interrupt - EXTI deaktivieren diesen Pin auf MISO AF und initiieren Sie eine 3-Byte-DMA-Transaktion (senden Sie 3 Dummy-Bytes, da Sie den Takt für das ADS generieren müssen).
  3. In der DMA-Übertragung vollständiger Interrupt-Wechsel-Pin auf den GPIO-Eingang. Aktivieren Sie EXTI

Die Schritte 2 und 3 werden automatisch bei jeder Konvertierung wiederholt.

Bitte entschuldigen Sie meine Unwissenheit: Was ist die Abkürzung AF?
Alternative Funktion – dh dieser Port fungiert als SPI2 MISO . Es wird eingestellt, indem das GPIOx-MODER-Register auf den alternativen Modus eingestellt wird und die AF-Register eingestellt werden
Ah, verstanden.
Ich sollte nur DMA für TX brauchen, richtig? Oder sollte ich Vollduplex-SPI mit DMA1 und zwei Kanälen für RX und TX machen?
@Biff - DMA für RX, TX können Sie DMA machen oder nicht.
Mir ist nicht klar, warum TX benötigt wird - SCLK wird vom STM32 generiert, da es sich im Master-Halbduplex-RX-Modus befindet?
Die SPI-Schnittstelle generiert den Takt nur, wenn die Daten gesendet werden. Als Master müssen Sie also die Dummy-Daten senden, um etwas zu erhalten
Ist das Generieren von SCLK im Master-Modus keine STM32-spezifische Sache? Entsprechend generiert der Master SCLK (scroll to half-duplex single read) .
Weitere Recherchen ab 36.1 (S. 1210) des STM32-Referenzhandbuchs: Die Schnittstelle kann als Master konfiguriert werden und liefert in diesem Fall den Kommunikationstakt (SCK) an das externe Slave-Gerät.
@Biff Ich entschuldige mich im Voraus für die Dinge, die ich jetzt schreiben werde. Ich fürchte, Sie verstehen die Dokumente, die Sie lesen, nicht. Und von den Beiträgen hast du nicht allzu viel Erfahrung. Aber wenn Sie besser wissen, wie die SPI-Schnittstelle funktioniert, sage ich Pass - keine Hilfe mehr von mir.
Vielen Dank für Ihre Hilfe bisher, ich erkenne meine Unerfahrenheit und versuche zu verstehen. Ich stimme Ihren Ausführungen zu. :)

Ich plane die Verwendung von Simplex-Empfang mit SPI2 - klingt dieser Modus basierend auf den Wellenformen der ADS1234-Schnittstelle vernünftig?

Ja, Sie sollten in der Lage sein, einen Hardware-SPI-Port am STM32 zu verwenden, um mit dem ADS1234 zu kommunizieren

Der ADS1234 ist 24-Bit und der STM32L geht nur bis zu 16-Bit im Puffer. Mein Gedanke ist, es für 12-Bit zu konfigurieren und zwei Übertragungen durchzuführen, obwohl ich mir nicht sicher bin, ob dies mit irgendetwas in Konflikt steht?

Das wird funktionieren, Sie können den Puffer auch für 8 Bytes einrichten. Am Ende der Übertragung füllt sich der Puffer und erzeugt einen Interrupt (falls Sie es so eingerichtet haben), den Sie benötigen, um die Daten aus dem Puffer zu kopieren, bevor Sie eine weitere Übertragung starten.

Da die Verwendung der DRDY-Funktion nicht vollständig Teil des SPI-Protokolls ist, frage ich mich, wie dies eine Datenübertragung auslösen kann. Wenn der DRDY/DOUT-Pin-Status von High auf Low wechselt (was anzeigt, dass Daten bereit sind), sollte ich für ein Interrupt-on-Change-Ereignis (IOC) konfigurieren und dann mit dem Abschließen einer Übertragung beginnen?

Es gibt zwei Möglichkeiten, wie Sie das Sampling des ADC1234 ausführen können:

1) Initiieren Sie eine ADC-Abtastung und warten Sie dann deterministisch mit einem Timer oder verzögern Sie die Datenübertragung, bis Sie wissen, dass DRDY niedrig geworden ist, und initiieren Sie dann eine Übertragung.

2) Tun Sie, was Sie vorschlagen, und warten Sie, bis der DRDY mit einem GPIO-Port unter Verwendung von EXTI auf dem STM32 niedrig wird, und leiten Sie dann eine Übertragung ein.

Wenn ich darauf warte, dass DRDY mit einem EXTI-Port niedrig wird, würde ich effektiv zwei Pins verwenden, richtig? Eine für DOUT und eine andere im Wesentlichen für DRDY mit EXTI, beide parallel?
@laptop2d EXTI port on the STM32 (not all GPIOS support this)welche nicht? EXTI bei fallender Flanke (nicht Low-Pegel)
Ja, eine für DOUT und eine für DRDY. Eigentlich habe ich die EXTI-Anweisung doppelt überprüft und mich geirrt, ich entschuldige mich, ich werde die Antwort korrigieren

Ich habe einen AD4115 ADC, der das gleiche Schema hat, um den Host-uC zu benachrichtigen, dass er Daten bereit hat: Er bringt MISO/DOUT/~RDY auf einen niedrigen Wert. Ich konnte den STM32 dazu bringen, den Pin zwischen SPI- und GPIO-Verhalten umzuschalten.

void PA6_to_SPI1(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = { 0 };

    GPIO_InitStruct.Pin = GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_AF_PP;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    GPIO_InitStruct.Alternate = GPIO_AF5_SPI1;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);

}

void PA6_to_EXTI(void)
{
    GPIO_InitTypeDef GPIO_InitStruct = { 0 };
    GPIO_InitStruct.Pin = GPIO_PIN_6;
    GPIO_InitStruct.Mode = GPIO_MODE_IT_FALLING;
    GPIO_InitStruct.Pull = GPIO_NOPULL;
    GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW;
    HAL_GPIO_Init(GPIOA, &GPIO_InitStruct);
}

Nachdem ich einige Initialisierungen durchgeführt habe, um die AD4115-Register einzurichten, unter main()denen ich den Pin als MISO-Leitung verwenden muss, schalte ich ihn in den EXTI-Modus. Bei der nächsten fallenden Flanke wird die ISR aufgerufen

void HAL_GPIO_EXTI_Callback(uint16_t GPIO_Pin)
{
    if (GPIO_Pin != GPIO_PIN_6) return;

    /* turn PA6 back into a MOSI line */
    PA6_to_SPI1();
    adc_data = ad4115_read_reg(&hspi1, 4, 4);

    __HAL_GPIO_EXTI_CLEAR_IT(GPIO_Pin);

    /* PA6 leaves SPI mode and becomes EXTI source */
    PA6_to_EXTI();

}

Die ISR verwandelt den Pin wieder in ihr SPI-Selbst, liest das 32-Bit-Register aus und löscht alle anstehenden Interrupts (ich kann eigentlich nicht herausfinden, warum ich das tun muss, aber die ISR löste sich weiter aus, wenn ich es nicht tat it), schaltet dann zurück auf EXTI.

Dies alles verwendet direkt programmierte E / A, also so einfach wie es nur geht. Ich lese nur mit 1 kHz aus, daher ist der Overhead derzeit akzeptabel.