J'essaie depuis longtemps de faire fonctionner correctement le SPI1 sur la STM32F103C8 (carte Blue Pill ). Comme je commence tout juste à apprendre l'ARM, j'essaie simplement de décaler les données vers un registre à décalage 74HC595 et de le verrouiller pour allumer un octet de LED. Je ne relis aucune donnée, donc je n'ai que des lignes MOSI, SCK et SS.
Au début, je n'obtenais rien, mais en lisant quelques exemples en ligne, je pouvais résoudre ces premiers problèmes pour démarrer la communication (j'avais besoin de définir correctement les broches GPIOA et de définir le logiciel SS).
Le problème principal en ce moment est que si je n'inclus pas de résistances de rappel sur toutes les lignes (MOSI, SCK et SS), le microcontrôleur ne produit rien sur aucune ligne (vérifié avec une portée). En plus de cela, après avoir ajouté des résistances de pull-up, le temps de montée sur les impulsions est très lent, donc je ne peux pas utiliser une fréquence trop élevée (avec des résistances de pull-up de 10 kΩ, je suis limité à environ 250 kHz SCK, et la commutation à 330 Ω environ 4 MHz). Je travaille sur une planche à pain, mais même avec un AVR et un câblage plus compliqué, je pouvais obtenir un SPI de 4 MHz sans problème sans résistance supplémentaire et les formes d'onde étaient plus propres.
Voici deux images (désolé pour l'état abyssal de mon écran de visée) transmettant l'octet 0b01110010 à une horloge de 250 kHz. La trace du haut est SCK et celle du bas est MOSI. La première image est avec des résistances de pull-up de 10 kΩ et la seconde avec des résistances de pull-up de 330 Ω qui rendent les formes d'onde beaucoup plus agréables (mais elles ne devraient pas être nécessaires).
J'apprécierais un peu d'aide pour comprendre ce qui se passe.
Les parties pertinentes de mon code sont:
#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;
Réponses:
Vous devez réinitialiser la valeur des broches que vous modifiez avant de définir les bits.
La valeur de réinitialisation de GPIOA_CRL est 0x4444 4444. Ainsi, chaque broche est initialisée avec 0b0100, si vous faites un | = 0b0011, vous vous retrouvez avec 0b0111 qui est une sortie de drain ouvert. Idem avec 0b1011 devient 0b1111 et c'est un drain ouvert à fonction alternative.
Vous devez donc faire quelque chose comme ceci:
la source