3 votes

Problème de transmission de données sur UART dans le STM32F103C8 ('Blue Pill')

Je suis débutant en systèmes embarqués. J'essaie d'écrire des données sur le UART2 du STM32F103C8 (c'est-à-dire le Pilule bleue ) et je veux voir les données dans l'un des ports de mon ordinateur à l'aide d'une carte à puce. FTDI qui est connecté à UART2 de la carte STM32F103C8. Mais sur ma console, je recevoir un bloc carré aléatoire au lieu du caractère que je veux transmettre.

Voici mon code écrit en Keil IDE.

#include "stm32f10x.h"                  // Device header

void usart2_init(void);
void USART_write(int data);
void delayMs(int delay);

int main(void)
{
    usart2_init();
    while(1)
    {
       USART_write('A');
       delayMs(5000);
    }
}

void usart2_init(void)
{
       // Enable clock source for USART2
       RCC->APB1ENR |= 0x20000;           // 0b 0000 0000 0000 0010 0000 0000 0000 0000
       RCC->APB2ENR |= 0x4;
       GPIOA->CRL |= 0x900;               // Set PA2 as TX pin (AF)
       USART2->BRR  = 0x341;              // Setting Baudrate to 9600 @8 MHz.
       USART2->CR1 |= 0x00008;            // Enable TX only
       USART2->CR1 |= 0x02000;            // Enable USART module by setting bit 13 to 1 i
       USART->CR1 register
}

void USART_write(int data)
{
    // We need to wait until Tx buffer is empty for sending data.
    while(!(USART2->SR & 0x0080));        // 0x0080
    USART2->DR = (data & 0xFF);
}

void delayMs(int delay)
{
    int i;
    for( ; delay>0 ; delay--)
    {
        for(i=0; i<3195; i++)
        {
        }
    }
}

J'ai joint ci-dessous la capture d'écran pendant le débogage.

Cliquez ici pour voir la capture d'écran .

Vous pouvez voir le bloc carré indésirable au lieu d'un caractère au lieu des caractères que je veux transmettre. Dans l'image, vous pouvez également voir les registres UART et leurs valeurs. J'utilise ST-LINK2 pour télécharger le micrologiciel.

Est-ce qu'il me manque des informations ou est-ce que je fais une erreur en traitant avec FTDI et Terme Tera ? Voici ma configuration Tera Term :

  • Taux de bauds = 9600
  • Données = 8 bits
  • Parité = aucune
  • Bit d'arrêt = 1
  • Flux de contrôle = aucun

Comment puis-je réparer cela ?

1voto

Frankie_C Points 2349

Lorsque vous travaillez avec ces appareils, vous devez lire attentivement les fiches techniques/manuels de référence et éventuellement les notes d'application (AN) disponibles sur le site du fabricant.

Dans ce cas précis, la famille STM32F10x fonctionne généralement avec une horloge système de 72 MHz générée par un oscillateur PLL interne qui utilise le cristal externe, dont la fréquence est de 8 MHz sur la pilule bleue, comme référence pour le circuit PLL (boucle à verrouillage de phase) qui le contrôle. L'oscillateur à cristal de 8 MHz est appelé HSE, ce qui signifie High Speed External oscillator.

J'ai dit "généralement" parce que l'utilisateur peut sélectionner différentes fréquences d'horloge système en programmant les prescalers spécifiques et les circuits d'horloge internes, ce qui peut devenir très compliqué à première vue (et même à la seconde ).

Supposons maintenant la configuration standard des interfaces périphériques, où l'horloge système est sélectionnée à 72 MHz et le prescaler AHB à 1, les deux horloges périphériques (PCLCKx) sont réglées à 36 MHz (PCLCK1 : prescaler = 2) et 72 MHz (PCLCK2), respectivement.

Sur les puces STM32F10x, seul USART1 est cadencé par PCLCK2, et tous les autres sont cadencés par PCKLK1 (36 MHz maximum).

Donc votre appareil est vraisemblablement cadencé à 36 MHz. Pour avoir un taux de 9600 bauds, nous avons besoin d'un diviseur global de 36 MHz / (9600 * 16) = 234,375 .

Le générateur de débit en bauds peut gérer les divisions fractionnaires en considérant séparément les parties entières et fractionnaires. On obtient :

DIV_Fraction = 16 * 0.375 = 6 = 0x06
DIV_Mantissa = 234 = 0xEA
USART_BRR = (DIV_Mantissa << 4) | DIV_Fraction = 0xEA6

La notation 0dxx est tiré de la documentation ST et correspond à la représentation décimale.

Conclusion

Pour fonctionner sur ces appareils, lisez attentivement la documentation avant de commencer à programmer, utilisez si possible des bibliothèques d'aide. Personnellement, je préfère libopencm3 sur les bibliothèques HAL standard, ce qui en simplifie l'utilisation.

0voto

Eldho Abraham Points 1

Ça va marcher, je l'ai testé

void init_Usart(void)
{
  // Enable clock source for USART2
  RCC->APB1ENR |= 0x20000;           // 0b 0000 0000 0000 0010 0000 0000 0000 0000
  RCC->APB2ENR |= 0x4;
  GPIOA->CRL |= 0x900;               // Set PA2 as TX pin (AF)
  USART2->BRR  = 0xEA6;              // Setting Baudrate to 9600 @8 MHz.
  USART2->CR1 |= 0x00008;            // Enable TX only
  USART2->CR1 |= 0x02000;            // Enable USART module 

}

void USART_write(int data)
{
  // We need to wait until Tx buffer is empty for sending data.
  while(!(USART2->SR & 0x0080));        // 0x0080
  USART2->DR = (data & 0xFF);
}

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X