O SPI no STM32 não funcionará sem resistores de pullup e, mesmo assim, apresenta um desempenho ruim


8

Estou tentando fazer com que o SPI1 no STM32F103C8 (quadro azul ) funcione corretamente há algum tempo. Como estou começando a aprender o ARM, estou simplesmente tentando transferir dados para um registro de deslocamento 74HC595 e travá-lo para acender um byte de LEDs. Não estou lendo nenhum dado, por isso só tenho linhas MOSI, SCK e SS.

No começo, eu não estava conseguindo nada, mas, lendo alguns exemplos online, eu poderia resolver esses primeiros problemas para iniciar a comunicação (eu precisava definir corretamente os pinos GPIOA e o software SS).

O principal problema agora é que, se eu não incluir resistores pull-up em todas as linhas (MOSI, SCK e SS), o microcontrolador não produzirá nada em nenhuma linha (verificado com um escopo). Além disso, após adicionar resistores pull-up, o tempo de subida nos pulsos é muito lento, então não posso usar uma frequência muito alta (com resistores pull-up de 10 kΩ, estou limitado a cerca de 250 kHz SCK e alternando a 330 Ω cerca de 4 MHz). Estou trabalhando em uma placa de ensaio, mas mesmo assim com o AVR e a fiação mais bagunçada, eu poderia obter um SPI de 4 MHz sem problemas, sem nenhum resistor adicional e as formas de onda estavam mais limpas.

Aqui estão duas fotos (desculpe pelo estado abismal da minha tela de escopo) transmitindo o byte 0b01110010 a um relógio de 250 kHz. O rastreio superior é SCK e a parte inferior é MOSI. A primeira foto é com resistores pull-up de 10 kΩ e a segunda com resistores pull-up de 330 that, que tornam as formas de onda muito mais agradáveis ​​(mas não devem ser necessárias).

Eu apreciaria alguma ajuda para descobrir o que está acontecendo.

Resistores de pull-up de 10 kΩ e relógio de 250 kHz

Os resistores pull-up de 330 and e 250 kHz tornam a forma de onda muito melhor

As partes relevantes do meu código são:

#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 é a sua configuração? Como seus fios estão conectados? Você está usando uma placa personalizada ou uma tábua de pão?
Tarick Welling 28/05/19

Eu estou usando uma tábua de pão. O 74hc595 é alimentado a partir de 3,3V do painel de comprimidos azul (este para ser mais preciso: revspace.nl/File:Bluepill.jpg ). Os únicos fios que vão de e para o registrador de mudança são MOSI, SCK e SS. Tenho certeza de que a fiação está correta, verifiquei várias vezes (e mais uma vez antes de responder).
jjpprr

Respostas:


12

Você deve redefinir o valor dos pinos que está mudando antes de definir os bits.

O valor de redefinição de GPIOA_CRL é 0x4444 4444. Portanto, cada pino é inicializado com 0b0100, se você fizer um | = 0b0011, acabará com 0b0111, que é uma saída de dreno aberta. O mesmo com 0b1011 se torna 0b1111 e essa é uma drenagem aberta de função alternativa.

Então, você precisa fazer algo assim:

// 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 isso!! Muito obrigado, eu sabia que seria algo tão simples. Deveria ter lido a primeira linha no GPIOA_CRL da folha de dados, apenas assumi que o valor de redefinição era todos os zeros. Agora funciona um encanto.
jjpprr

@jjpprr bem, demorei um pouco para perceber :-) Fico feliz em poder ajudar. Se você vai usar o I²C no F103, esteja pronto para uma viagem difícil, lembro que isso foi horrível.
Arsenal

: O levará isso em conta, depois de colocar o USART em funcionamento, será a vez dos I2Cs. Obrigado pela atenção.
jjpprr

A coisa que se destaca mais profundamente nas interrupções que eu recebia sem nenhuma fonte de interrupção que atrapalhasse minha máquina de estado. No final, eu optei por uma abordagem que não usa interrupções de I²C (mas a DMA interrompe o final da transmissão) e apenas seleciona os bits de I²C para iniciar e outras coisas, mas meu aplicativo teve que esperar que o I²C terminasse de qualquer maneira , então eu não estava ganhando tempo com interrupções de qualquer maneira.
Arsenal

Isso foi apenas com o F103 ou também com outros chips stm32? Porque meu plano era usá-lo apenas para pegar o IC stm32, mas depois passar para o F091 para pequenos projetos e o F446 para coisas mais exigentes.
Jjpprr 28/05/19
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.