SPI su STM32 non funzionerà senza resistori pullup e anche allora funziona male


8

Sto provando a far funzionare correttamente SPI1 su STM32F103C8 ( scheda Blue Pill ) da qualche tempo. Mentre sto appena iniziando a studiare ARM, sto semplicemente cercando di spostare i dati in un registro a scorrimento 74HC595 e bloccarli per illuminare un byte di LED. Non sto leggendo alcun dato, quindi ho solo linee MOSI, SCK e SS.

All'inizio non stavo ottenendo nulla, ma leggendo alcuni esempi online ho potuto risolvere questi primi problemi per avviare la comunicazione (avevo bisogno di impostare correttamente i pin GPIOA e impostare il software SS).

Il problema principale in questo momento è che se non includo resistenze di pull-up su tutte le linee (MOSI, SCK e SS) il microcontrollore non emette nulla su nessuna linea (controllato con un ambito). Inoltre, dopo aver aggiunto resistori pull-up, il tempo di salita sugli impulsi è molto lento, quindi non posso usare una frequenza troppo alta (con resistori pull-up da 10 kΩ ho un limite di circa 250 kHz SCK e la commutazione a 330 Ω circa 4 MHz). Sto lavorando su una breadboard, ma anche in questo caso con AVR e cavi più corposi ho potuto ottenere un SPI a 4 MHz funzionante senza problemi senza resistori aggiunti e le forme d'onda erano più pulite.

Ecco due immagini (mi dispiace per lo stato abissale della mia schermata dell'oscilloscopio) che trasmettono il byte 0b01110010 a un clock di 250 kHz. La traccia superiore è SCK e la parte inferiore è MOSI. La prima immagine è con resistenze pull-up da 10 kΩ e la seconda con resistenze pull-up da 330 Ω che rendono le forme d'onda molto più belle (ma non dovrebbero essere necessarie).

Apprezzerei un po 'di aiuto per capire cosa sta succedendo.

Resistenze pull-up da 10 kΩ e clock da 250 kHz

Le resistenze pull-up da 330 Ω e 250 kHz rendono la forma d'onda molto più piacevole

Le parti rilevanti del mio codice sono:

#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;

Qual è la tua configurazione? Come sono collegati i tuoi fili? Stai usando una scheda personalizzata o una breadboard?
Tarick Welling,

Sto usando una breadboard. Il 74hc595 è alimentato dal 3.3V della scheda pillola blu (questo per essere precisi: revspace.nl/File:Bluepill.jpg ). Gli unici fili che vanno da e verso il registro a scorrimento sono MOSI, SCK e SS. Sono sicuro che il cablaggio sia corretto, l'ho verificato numerose volte (e ancora una volta prima di risponderti).
jjpprr,

Risposte:


12

È necessario reimpostare il valore dei pin che si stanno modificando prima di impostare i bit.

Il valore di reset di GPIOA_CRL è 0x4444 4444. Quindi ogni pin viene inizializzato con 0b0100, se si esegue un | = 0b0011 si finisce con 0b0111 che è un'uscita di drain aperta. Lo stesso con 0b1011 diventa 0b1111 e questo è uno scarico aperto a funzione alternativa.

Quindi devi fare qualcosa del genere:

// 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

Era questo!! Grazie mille, sapevo che sarebbe stato qualcosa di così semplice. Avrei dovuto leggere la prima riga su GPIOA_CRL del foglio dati, supponevo solo che il valore di reset fosse tutto azzerato. Ora funziona a meraviglia.
jjpprr,

@jjpprr bene mi ci è voluto un po 'di tempo per realizzare anche :-) Sono contento di aver potuto aiutare. Se hai intenzione di usare I²C sull'F103, preparati per un giro difficile, ricordo che è orribile.
Arsenale,

: O lo terrà in considerazione, dopo aver avviato USART e averlo avviato, sarà il turno degli I2C. Grazie per il testa a testa.
jjpprr,

La cosa che spicca in modo più profondo dove gli interrupt che stavo ottenendo senza alcuna fonte di interruzioni che hanno incasinato la mia macchina a stati. Alla fine ho optato per un approccio che non utilizza affatto interruzioni I²C (ma l'interrupt DMA per la fine della trasmissione) e esegue semplicemente il polling dei bit I²C per inizio e roba, ma la mia applicazione ha dovuto attendere comunque che I²C finisse , quindi non stavo guadagnando tempo con gli interrupt comunque.
Arsenale,

Era solo con l'F103 o anche altri chip stm32? Perché il mio piano era quello di usarlo solo per impiccare i circuiti integrati stm32 ma poi passare a F091 per piccoli progetti e F446 per cose più impegnative.
jjpprr,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.