SPI sur STM32 ne fonctionnera pas sans résistances de pullup et même alors fonctionne mal

8

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.

Résistances de rappel 10 kΩ et horloge 250 kHz

Les résistances pull-up de 330 Ω et 250 kHz rendent la forme d'onde beaucoup plus agréable

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;
jjpprr
la source
Quelle est votre configuration? Comment vos fils sont-ils connectés? Utilisez-vous une planche personnalisée ou une planche à pain?
Tarick Welling
J'utilise une planche à pain. Le 74hc595 est alimenté par le 3,3 V de la carte de pilule bleue (celle-ci pour être précis: revspace.nl/File:Bluepill.jpg ). Les seuls fils allant de et vers le registre à décalage sont MOSI, SCK et SS. Je suis certain que le câblage est correct, je l'ai vérifié plusieurs fois (et encore une fois avant de vous répondre).
jjpprr

Réponses:

12

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:

// 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
Arsenal
la source
C'était ça!! Merci beaucoup, je savais que ça allait être quelque chose de si simple. J'aurais dû lire la première ligne sur GPIOA_CRL de la fiche technique, je supposais simplement que la valeur de réinitialisation était uniquement des zéros. Cela fonctionne maintenant un charme.
jjpprr
@jjpprr eh bien il m'a fallu un certain temps pour réaliser aussi :-) Heureux d'avoir pu aider. Si vous allez utiliser I²C sur le F103, soyez prêt pour un tour difficile, je me souviens que c'était horrible.
Arsenal
: O en tiendra compte, après avoir démarré et exécuté USART, ce sera au tour des I2C. Merci pour l'information.
jjpprr
La chose qui se démarque le plus profondément où les interruptions que j'obtenais sans aucune source d'interruption qui a gâché ma machine d'état. En fin de compte, j'ai opté pour une approche qui n'utilise pas du tout d'interruptions I²C (mais l'interruption DMA pour la fin de la transmission) et interroge simplement les bits I²C pour le démarrage et tout ça, mais mon application a dû attendre que I²C se termine de toute façon , donc je ne gagnais pas de temps avec les interruptions de toute façon.
Arsenal
Était-ce uniquement avec le F103 ou d'autres puces stm32? Parce que mon plan était de l'utiliser uniquement pour obtenir le coup des circuits intégrés stm32, puis passer au F091 pour les petits projets et au F446 pour les choses plus exigeantes.
jjpprr