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.
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;
Respostas:
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:
fonte