smt32 f10x caracteres no válidos sobre uart

Actualmente estoy trabajando en un quadcopter usando el STM32F103 . En lugar de usar el controlador de periféricos estándar proporcionado, que es grande, estoy creando mi propio controlador de periféricos que está orientado a objetos, lo que también me ayuda a comprender mejor el procesador.

Llegué a la etapa en la que tengo el núcleo funcionando y pasé a la USART. Recreé la unidad estándar USART siguiendo los procedimientos de espacio establecidos tanto en el código como en el manual de referencia.

PRODUCCIÓN:

ingrese la descripción de la imagen aquí

Como puede ver, algunos caracteres no se muestran correctamente. Revisé todas las funciones llamadas y todas las variables utilizadas muchas veces y todas se pagaron. Estoy fuera de las ideas. ¿Hay algo que esté haciendo mal, o OO programando un no no incrustado porque eso es lo único que se me ocurre?

El resultado de lo anterior es el siguiente.

Aquí está el código para USART-:

USART.h AQUÍ

USART.cpp AQUÍ

PRINCIPAL.cpp

#include "SysCore.h"
#include "USART.h"
/**
* @brief  Public/global hall instance, use extern to use in another 
                    file (can't be used in C). By having it this as a reference, 
                    it removes the worry or having to check it for a null reference
*/
System::Hal *globalHal;

//usart config
System::USARTConfig *usartConfig;


extern "C" void SysTick_Handler (void)
{
   /*Call HAL tick to increment its tocks*/
   globalHal->Tick();
}

void SendChar(uint8_t character, System::USART *usart)
{
   //send the character
   usart->SendData(usartConfig, (uint8_t)character);        
   while(usart->GetFlagStatus(usartConfig, USART_FLAG_TC) == RESET)
   {}
}

void SendMessage(char MESSAGE[], uint8_t length, System::USART *usart )
{
   for(uint8_t i = 0; i < length; i++)
   {
        SendChar((uint8_t)MESSAGE[i], usart);
   }
}

int main(void)
{
//Creates the instance of HAl (singleton please)
System::Hal *hal = new System::Hal();
//Set global extern Hal pointer
globalHal = hal;

//Init the Hal 
hal->Hal_init();
//Init the system tick
hal->InitTick();


//enable rcc for ports
hal->Rcc->APB2PeriphClock(System::APB2Peripheral::Gpioc | 
System::APB2Peripheral::Gpioa  | 
System::APB2Peripheral::Usart1 |
System::APB2Peripheral::Afio, HAL_Enable);


/*----------------USART----------------*/
//TX pin 9
System::GPIOConfig *usartTxPort = new System::GPIOConfig(GPIO_Pin_9, GPIOA, GPIO_Mode_AF_PP, GPIO_Speed_50MHz);
//RX pin 10
System::GPIOConfig *usartRxPort = new System::GPIOConfig(GPIO_Pin_10, GPIOA, GPIO_Mode_IN_FLOATING, GPIO_Speed_50MHz);

//initalize the gpio
hal->Gpio->Init_GPIO(usartTxPort);
hal->Gpio->Init_GPIO(usartRxPort);


usartConfig = new System::USARTConfig();

//configure usartConfig     
usartConfig->USARTx = USART1;
usartConfig->BuadRate = 9600;
usartConfig->Mode = USART_Mode_Rx |USART_Mode_Tx ;
usartConfig->StopBits = USART_StopBits_1;
usartConfig->Parity = USART_Parity_No;
usartConfig->HardwareFlowControl = USART_HardwareFlowControl_None;
usartConfig->WordLength = USART_WordLength_8b;

//passing usartConfig will initalize the usart
System::USART *usart = new System::USART(usartConfig);

usart->UsartCmd(usartConfig, HAL_Enable);

SendChar('\r', usart);
SendChar('\n', usart);
SendChar('a', usart);
SendChar('b', usart);
SendChar('c', usart);
SendChar('d', usart);
SendChar('e', usart);
SendChar('f', usart);
SendChar('g', usart);
SendChar('h', usart);
SendChar('i', usart);
SendChar('j', usart);
SendChar('k', usart);
SendChar('l', usart);
SendChar('m', usart);
SendChar('n', usart);
SendChar('o', usart);
SendChar('p', usart);
SendChar('q', usart);
SendChar('r', usart);
SendChar('s', usart);
SendChar('t', usart);
SendChar('u', usart);
SendChar('v', usart);
SendChar('w', usart);
SendChar('x', usart);
SendChar('y', usart);
SendChar('z', usart);

SendChar('A', usart);
SendChar('B', usart);
SendChar('C', usart);
SendChar('D', usart);
SendChar('E', usart);
SendChar('F', usart);
SendChar('G', usart);
SendChar('H', usart);
SendChar('I', usart);
SendChar('J', usart);
SendChar('K', usart);
SendChar('L', usart);
SendChar('M', usart);
SendChar('N', usart);
SendChar('O', usart);
SendChar('P', usart);
SendChar('Q', usart);
SendChar('R', usart);
SendChar('S', usart);
SendChar('T', usart);
SendChar('U', usart);
SendChar('V', usart);
SendChar('W', usart);
SendChar('X', usart);
SendChar('Y', usart);
SendChar('Z', usart);

while(true);
}

HalModule, HAL y GPIOConfig funcionan bien, e incluso si no lo fueran, no los necesito ya que no se usan cuando se usa USART.

Las bibliotecas periféricas estándar quedarán obsoletas pronto. Ahora ST migra a bibliotecas HAL y de bajo nivel.
¿Son siempre los mismos personajes los que se equivocan? Si reordena los caracteres, ¿el problema se mueve con el carácter o permanece en ese desplazamiento? ¿Cambia algo el retraso adicional entre caracteres?
@kkrombo, sí, siempre son los mismos personajes los que están mal. Cambiar el orden no les afecta a los tres personajes; finalmente agregar un retraso tampoco ayuda. También intenté enviar un carácter individual que no parece funcionar.
También he estado mirando el reloj y los únicos relojes que funcionan son el tic del sistema, que si no inicio el usart no envía ningún dato.

Respuestas (3)

Los caracteres que se corrompen son los que tienen tiradas largas del mismo bit en su representación binaria. Parece que cuatro bits idénticos consecutivos es aproximadamente el número que se necesita para confundir su línea serial.

Esto suele ser un problema con los flujos de datos en serie sin reloj, donde se requieren transiciones (0-> 1 o 1-> 0) para volver a sincronizar el reloj del receptor con el del remitente antes de que se desvíe demasiado. Sin embargo, normalmente se necesitan más de cuatro bits seguidos para perder la sincronización, lo que sugiere que los dos extremos de su línea serial tienen relojes que no están sincronizados entre sí.

También debe leer la respuesta de Twilight, que propone una razón por la que podría estar viendo que los dos extremos pierden la sincronización del reloj tan rápido y qué podría hacer al respecto.

Como puede ver, algunos caracteres no se muestran correctamente.

en lugar de que otras personas traten de ver lo que está mal, tal vez deberías decir lo que está mal.

Revisé todas las funciones llamadas y todas las variables utilizadas muchas veces y todas se pagaron. Estoy fuera de las ideas.

Intentaría asegurarme de que tenga la velocidad de transmisión correcta en ambos extremos; por ejemplo, ¿su oscilador interno, si se usa aquí, es lo suficientemente preciso? o si su cristal externo tiene una frecuencia que produce una tasa de error demasiado alta para la tasa de baudios deseada? ...

una cosa menor para su código es que puede acelerar la transmisión si verifica si el búfer está lleno al comienzo de sendchar() en lugar de esperar a que la transmisión se complete al final.

¿Hay algo que esté haciendo mal, o OO programando un no no incrustado porque eso es lo único que se me ocurre?

nada intrínsecamente malo con OO, especialmente para un chip tan rico en recursos.

Cambié el usot usado cualquier reloj, el clockconfig se está ejecutando de manera predeterminada. No me he metido con el oscilador interno o el cristal externo, por lo que todo funciona de forma predeterminada. Todavía estoy aprendiendo stm32 (o programación integrada en general), por lo que no sabría si esto es exactamente una falla de hardware o software. Las tarifas son las mismas 9600 en la MCU y la terminal.

Mencionaste en un comentario que:

No me he metido con el oscilador interno o el cristal externo, por lo que todo funciona de forma predeterminada.

Esta es probablemente la fuente de su problema. El oscilador HSI interno no es especialmente preciso; con la calibración de fábrica, tiene una tolerancia de aproximadamente ±2 %, que es demasiado amplia para un UART.

Si abre el cristal HSE y lo activa como fuente de reloj, el UART debería comenzar a comportarse por sí mismo.