SPI auf STM32 funktioniert ohne Pullup-Widerstände nicht und funktioniert auch dann schlecht

8

Ich habe seit einiger Zeit versucht, den SPI1 auf dem STM32F103C8 ( Blue Pill Board) zum Laufen zu bringen . Während ich gerade erst anfange, ARM zu lernen, versuche ich einfach, Daten in ein 74HC595-Schieberegister zu verschieben und es zu verriegeln, um ein Byte LEDs zu beleuchten. Ich lese keine Daten zurück, daher habe ich nur MOSI-, SCK- und SS-Leitungen.

Zuerst bekam ich nichts heraus, aber als ich einige Online-Beispiele las, konnte ich diese ersten Probleme beheben, um die Kommunikation in Gang zu bringen (ich musste die GPIOA-Pins richtig einstellen und die Software SS einstellen).

Das Hauptproblem im Moment ist, dass wenn ich nicht in allen Leitungen Pull-up-Widerstände (MOSI, SCK und SS) einbeziehe, der Mikrocontroller in keiner Leitung etwas ausgibt (mit einem Oszilloskop überprüft). Darüber hinaus ist die Anstiegszeit der Impulse nach dem Hinzufügen von Pull-up-Widerständen sehr langsam, sodass ich keine zu hohe Frequenz verwenden kann (mit 10-kΩ-Pull-up-Widerständen bin ich auf ca. 250 kHz SCK und Schalten beschränkt bis 330 Ω ca. 4 MHz). Ich arbeite an einem Steckbrett, aber selbst dann mit AVR und unordentlicherer Verkabelung konnte ich einen 4-MHz-SPI ohne zusätzliche Widerstände problemlos zum Laufen bringen, und die Wellenformen waren sauberer.

Hier sind zwei Bilder (Entschuldigung für den miserablen Zustand meines Oszilloskopbildschirms), die das Byte 0b01110010 mit einem 250-kHz-Takt übertragen. Die obere Spur ist SCK und die untere ist MOSI. Das erste Bild zeigt 10-kΩ-Pull-up-Widerstände und das zweite 330-Ω-Pull-up-Widerstände, die die Wellenformen viel schöner machen (aber nicht benötigt werden sollten).

Ich würde mich über Hilfe freuen, um herauszufinden, was los ist.

10 kΩ Pull-Up-Widerstände und 250 kHz Takt

330 Ω Pull-Up-Widerstände und 250 kHz machen die Wellenform viel schöner

Die relevanten Teile meines Codes sind:

#define SS_LOW        GPIOA->BSRR |= 1 << 4 + 16;
#define SS_HIGH        GPIOA->BSRR |= 1 << 4;

// SPI GPIO configuration
RCC->APB2ENR |= RCC_APB2ENR_IOPAEN;
GPIOA->CRL |= 0b0011 << 4 * 4;    // Set pin A4 as PP out 50mHz for SS
GPIOA->CRL |= 0b1011 << 5 * 4;    // Set pin A5 AltFunc PP out 50mHz for SCK
GPIOA->CRL |= 0b1011 << 7 * 4;    // Set pin A7 AltFunc PP out 50mHz for MOSI
SS_HIGH;

// SPI1 configuration
RCC->APB2ENR |= RCC_APB2ENR_SPI1EN;        // Enable SPI1 clock
SPI1->CR1 |= SPI_CR1_SSM;        // Software SS
SPI1->CR1 |= SPI_CR1_SSI;
SPI1->CR1 |= SPI_CR1_BR_0;        // Set prescaler
SPI1->CR1 |= SPI_CR1_BR_1;
SPI1->CR1 |= SPI_CR1_BR_2;
SPI1->CR1 |= SPI_CR1_MSTR;        // Master mode
SPI1->CR1 |= SPI_CR1_SPE;        // Enable SPI

// Transmit byte
SS_LOW;
SPI1->DR = 0b01110010;
while(!(SPI1->SR & SPI_SR_TXE));
while(SPI1->SR & SPI_SR_BSY);
SS_HIGH;
jjpprr
quelle
Was ist dein Setup? Wie sind Ihre Drähte verbunden? Verwenden Sie ein benutzerdefiniertes Board oder ein Steckbrett?
Tarick Welling
Ich benutze ein Steckbrett. Der 74hc595 wird über die 3,3 V der blauen Pillenplatte mit Strom versorgt (genauer gesagt: revspace.nl/File:Bluepill.jpg ). Die einzigen Drähte, die vom und zum Schieberegister führen, sind MOSI, SCK und SS. Ich bin mir sicher, dass die Verkabelung korrekt ist. Ich habe sie mehrmals überprüft (und noch einmal, bevor ich Ihnen geantwortet habe).
jjpprr

Antworten:

12

Sie sollten den Wert der Pins, die Sie ändern, zurücksetzen, bevor Sie die Bits setzen.

Der Rücksetzwert von GPIOA_CRL ist 0x4444 4444. Jeder Pin wird also mit 0b0100 initialisiert. Wenn Sie | = 0b0011 ausführen, erhalten Sie 0b0111, einen Open-Drain-Ausgang. Dasselbe gilt für 0b1011 und wird zu 0b1111. Dies ist ein offener Drain mit alternativer Funktion.

Sie müssen also so etwas tun:

// Reset pin configuration
GPIOA->CRL &= ~(0b1111 << 4 * 4);  // Reset Pin A4
GPIOA->CRL &= ~(0b1111 << 5 * 4);  // Reset Pin A5
GPIOA->CRL &= ~(0b1111 << 7 * 4);  // Reset Pin A7
GPIOA->CRL |= 0b0011 << 4 * 4;  // Set pin A4 as PP out 50mHz for SS
GPIOA->CRL |= 0b1011 << 5 * 4;  // Set pin A5 AltFunc PP out 50mHz for SCK
GPIOA->CRL |= 0b1011 << 7 * 4;  // Set pin A7 AltFunc PP out 50mHz for MOSI
Arsenal
quelle
Das war's!! Vielen Dank, ich wusste, dass es etwas so Einfaches werden würde. Sollte die erste Zeile in GPIOA_CRL des Datenblattes gelesen worden sein, habe ich nur angenommen, dass der Rücksetzwert alle Nullen sind. Es funktioniert jetzt ein Zauber.
jjpprr
@jjpprr Nun, ich habe auch eine Weile gebraucht, um zu realisieren :-) Ich bin froh, dass ich helfen konnte. Wenn Sie I²C auf dem F103 verwenden, seien Sie bereit für eine harte Fahrt. Ich erinnere mich, dass es schrecklich war.
Arsenal
: O wird dies berücksichtigen, nachdem USART in Betrieb genommen wurde, sind I2Cs an der Reihe. Danke für die Warnung.
jjpprr
Das Ding, das am tiefsten auffällt, wo die Interrupts, die ich bekam, ohne eine Interruptquelle waren, die meine Zustandsmaschine durcheinander brachte. Am Ende habe ich mich für einen Ansatz entschieden, bei dem überhaupt keine I²C-Interrupts verwendet werden (sondern der DMA-Interrupt für das Ende der Übertragung) und nur die I²C-Bits nach Start und anderen Dingen abgefragt werden, aber meine Anwendung musste trotzdem warten, bis I²C beendet ist Also habe ich sowieso keine Zeit mit Interrupts gewonnen.
Arsenal
War das nur mit dem F103 oder auch anderen stm32 Chips? Weil mein Plan war, es nur zu verwenden, um den Dreh raus von stm32-ICs zu bekommen, aber dann für kleine Projekte zum F091 und für anspruchsvollere Dinge zum F446 überzugehen.
jjpprr