He estado tratando de hacer que el SPI1 en el STM32F103C8 ( tablero de píldora azul ) funcione correctamente desde hace algún tiempo. Cuando recién estoy comenzando a aprender ARM, simplemente estoy tratando de cambiar los datos a un registro de desplazamiento 74HC595 y bloquearlo para encender un byte de LED. No estoy leyendo ningún dato, así que solo tengo líneas MOSI, SCK y SS.
Al principio no estaba obteniendo nada, pero leyendo algunos ejemplos en línea podría solucionar estos primeros problemas para que la comunicación funcionara (necesitaba configurar correctamente los pines GPIOA y el software SS).
El principal problema en este momento es que si no incluyo resistencias pull-up en todas las líneas (MOSI, SCK y SS), el microcontrolador no genera nada en ninguna línea (verificado con un osciloscopio). Además de esto, después de agregar resistencias pull-up, el tiempo de aumento en los pulsos es muy lento, por lo que no puedo usar una frecuencia demasiado alta (con resistencias pull-up de 10 kΩ estoy limitado a aproximadamente 250 kHz SCK y conmutación a 330 Ω aproximadamente 4 MHz). Estoy trabajando en una placa de pruebas, pero incluso entonces con AVR y cableado más desordenado pude obtener un SPI de 4 MHz sin ningún problema sin resistencias adicionales y las formas de onda estaban más limpias.
Aquí hay dos imágenes (perdón por el estado abismal de mi pantalla de alcance) que transmiten el byte 0b01110010 a un reloj de 250 kHz. La traza superior es SCK y la inferior es MOSI. La primera imagen es con resistencias pull-up de 10 kΩ y la segunda con resistencias pull-up de 330 Ω que hacen que las formas de onda sean mucho más agradables (pero no deberían ser necesarias).
Agradecería un poco de ayuda para descubrir qué está pasando.
Las partes relevantes de mi código son:
#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;
Respuestas:
Debe restablecer el valor de los pines que está cambiando antes de configurar los bits.
El valor de reinicio de GPIOA_CRL es 0x4444 4444. Por lo tanto, cada pin se inicializa con 0b0100, si hace un | = 0b0011, termina con 0b0111, que es una salida de drenaje abierta. Lo mismo con 0b1011 se convierte en 0b1111 y esa es una función alternativa de drenaje abierto.
Entonces necesitas hacer algo como esto:
fuente