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:
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-:
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.
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.
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.
jakub rakus
krambo
kelvin mac
kelvin mac