smt32 f10x ungültige Zeichen über uart

Ich arbeite derzeit an einem Quadcopter mit dem STM32F103 . Anstatt den mitgelieferten Std Periph Driver zu verwenden, der groß ist, erstelle ich meinen eigenen Periph Driver, der objektorientiert ist, was mir auch dabei hilft, den Prozessor besser zu verstehen.

Ich habe die Phase erreicht, in der der Kern funktioniert, und bin zum USART übergegangen. Ich habe das USART-Standardlaufwerk nach den im Code und im Referenzhandbuch angegebenen Leerzeichenverfahren neu erstellt.

AUSGANG:

Geben Sie hier die Bildbeschreibung ein

Wie Sie sehen können, werden einige Zeichen nicht richtig angezeigt. Ich habe jede aufgerufene Funktion und jede verwendete Variable viele Male überprüft und alle ausgecheckt. Mir gehen die Ideen aus. Gibt es etwas, das ich falsch mache, oder OO-Programmierung ein Nein, Nein, eingebettet, weil das das einzige andere ist, was mir einfällt.

Die Ausgabe für das obige ist wie folgt.

Hier ist der Code für USART-:

USART.h HIER

USART.cpp HIER

MAIN.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 und GPIOConfig funktionieren gut, und selbst wenn sie es nicht wären, brauche ich sie nicht, da sie bei der Verwendung von USART nicht verwendet werden.

Standardbibliotheken für Peripheriegeräte werden bald veraltet sein. Jetzt migriert ST zu HAL- und Low-Level-Bibliotheken.
Sind es immer die gleichen Zeichen, die falsch sind? Wenn Sie die Zeichen neu anordnen, bewegt sich das Problem mit dem Zeichen oder bleibt es bei diesem Offset? Ändert eine zusätzliche Verzögerung zwischen den Zeichen etwas?
@kkrombo, ja, es sind immer die gleichen Zeichen, die falsch sind. Das Ändern der Reihenfolge wirkt sich nicht auf Sie drei Charaktere aus; Schließlich hilft auch das Hinzufügen einer Verzögerung nicht. Ich habe auch versucht, ein einzelnes Zeichen zu senden, was nicht zu funktionieren scheint.
Ich habe auch auf die Uhr geschaut und die einzige laufende Uhr ist der Systemtick, der keine Daten sendet, wenn ich den usart nicht initiiere.

Antworten (3)

Die beschädigten Zeichen sind diejenigen, die lange Folgen des gleichen Bits in ihrer binären Darstellung haben. Es scheint, als wären vier aufeinanderfolgende identische Bits ungefähr die Anzahl, die erforderlich ist, um Ihre serielle Leitung zu verwirren.

Dies ist häufig ein Problem bei nicht getakteten seriellen Datenströmen, bei denen Übergänge (0->1 oder 1->0) erforderlich sind, um die Uhr des Empfängers mit der des Senders neu zu synchronisieren, bevor sie zu weit driftet. Normalerweise sind jedoch viel mehr als vier Bits hintereinander erforderlich, um die Synchronisierung zu verlieren, was darauf hindeutet, dass die beiden Enden Ihrer seriellen Leitung Uhren haben, die nicht miteinander synchron sind.

Sie sollten auch die Antwort von Dämmerungswuff lesen, die einen Grund vorschlägt, warum Sie sehen könnten, dass die beiden Enden die Uhrensynchronisation so schnell verlieren, und was Sie dagegen tun können.

Wie Sie sehen können, werden einige Zeichen nicht richtig angezeigt.

Anstatt dass andere Leute versuchen zu sehen, was falsch ist, sollten Sie vielleicht einfach sagen, was falsch ist.

Ich habe jede aufgerufene Funktion und jede verwendete Variable viele Male überprüft und alle ausgecheckt. Mir gehen die Ideen aus.

Ich würde versuchen, sicherzustellen, dass Sie an beiden Enden die richtige Baudrate haben. Ist beispielsweise Ihr interner Oszillator, falls er hier verwendet wird, genau genug? oder wenn Ihr externer Quarz eine Frequenz hat, die eine zu hohe Fehlerrate für die gewünschte Baudrate erzeugt? ...

Eine Kleinigkeit für Ihren Code ist, dass Sie die Übertragung beschleunigen können, wenn Sie zu Beginn von sendchar() prüfen, ob der Puffer voll ist, anstatt zu warten, bis die Übertragung am Ende abgeschlossen ist.

Gibt es etwas, das ich falsch mache, oder OO-Programmierung ein Nein, Nein, eingebettet, weil das das einzige andere ist, was mir einfällt.

An OO ist grundsätzlich nichts auszusetzen, insbesondere für einen so ressourcenreichen Chip.

Ich habe in der usart keine Uhren verwendet, die clockconfig läuft defaults. Ich habe nicht mit dem internen Oszillator oder dem externen Kristall herumgespielt, also läuft alles standardmäßig. Ich lerne immer noch stm32 (oder eingebettete Programmierung im Allgemeinen), daher würde ich nicht wissen, ob dies genau ein Hardwarefehler oder eine Software ist. Die Buadraten sind die gleichen 9600 auf der MCU und dem Terminal.

Sie haben in einem Kommentar erwähnt, dass:

Ich habe nicht mit dem internen Oszillator oder dem externen Kristall herumgespielt, also läuft alles standardmäßig.

Dies ist wahrscheinlich die Ursache Ihres Problems. Der interne HSI-Oszillator ist nicht besonders genau; mit der Werkskalibrierung hat es eine Toleranz von ungefähr ±2%, was für einen UART zu breit ist.

Wenn Sie den HSE-Kristall aufrufen und ihn als Taktquelle aktivieren, sollte der UART beginnen, sich selbst zu verhalten.