4

I'm currently working on a quadcopter using the STM32F103. Instead of using the provided Std Periph Driver which is big I'm creating my own Periph Driver which is object oriented which also helps me understand the processor better.

I've gotten to stage where I have the core working and moved on to the USART. I've recreated the USART standard drive following the space procedures stated both in the code and the reference manual.

OUTPUT:

enter image description here

As you can see some characters aren't displayed right. I've checked every function called and every variable used a lot of times and they all checkout. I'm out of ideas. Is there anything I'm doing wrong, or OO porgramming a no no in embedded because that's the only other thing i can think of.

The output for the above is as follows.

Here is the code for USART-:

USART.h HERE

USART.cpp HERE

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 and GPIOConfig are working fine, and even if they weren't I don't need them since there's no use of them when using USART.

Rohat Kılıç
  • 26,954
  • 3
  • 25
  • 67
kelvinmac
  • 90
  • 4
  • Standard Peripheral Libraries will be obsolete soon. Now ST migrates to HAL and Low Level libraries. – Jakub Rakus Jul 28 '17 at 17:00
  • Is it always the same characters that are wrong? If you reorder the characters does the problem move with the character or stay at that offset? Does extra delay between characters change anything? – kkrambo Jul 29 '17 at 03:37
  • @kkrombo, yeah it's always the same characters that are wrong. Changing the order doesn't affect you three characters; finally adding a delay doesn't help either. I've also tried sending an invidual character which doesn't seem to work. – kelvinmac Jul 29 '17 at 08:56
  • I've also been looking at the clock and the only clocks running is the system tick, which if I don't initiate the usart doesn't send any data. – kelvinmac Jul 29 '17 at 08:57

3 Answers3

0

As you can see some characters aren't displayed right.

instead of having other people trying to see what's wrong, maybe you should just state what's wrong.

I've checked every function called and every variable used a lot of times and they all checkout. I'm out of ideas.

I would try to make sure that you got the baud rate right on both ends; for example, is your internal oscillator, if used here, accurate enough? or if your external crystal is at a frequency that produces too high of an error rate for the desired baud rate? ...

one minor thing for your code is you can speed up the transmission if you check for buffer full at beginning of sendchar() rather than wait for the transmission to complete at end of it.

Is there anything I'm doing wrong, or OO porgramming a no no in embedded because that's the only other thing i can think of.

nothing inherently wrong with OO, especially for such a resource rich chip.

dannyf
  • 4,272
  • 1
  • 7
  • 9
  • I changed the usart used any clocks, the clockconfig is running defaults. I haven't messed with the internal oscillator or external crystal so everything is running defualt. I'm still learning stm32 (or embedded programming in general) so i wouldn't know if this is exactly a hardware fault or software. Buadrates are the same 9600 on the MCU and terminal. – kelvinmac Jul 28 '17 at 15:43
0

You mentioned in a comment that:

I haven't messed with the internal oscillator or external crystal so everything is running defualt.

This is probably the source of your problem. The internal HSI oscillator is not especially accurate; with the factory calibration, it has a tolerance of roughly ±2%, which is too broad for a UART.

If you bring up the HSE crystal and activate it as the clock source, the UART should start behaving itself.

0

The characters that are being corrupted are the ones that have long runs of the same bit in their binary representation. It seems like four consecutive identical bits is roughly the number it takes to confuse your serial line.

This is often a problem with non-clocked serial data streams, where transitions (0->1 or 1->0) are required to re-synchronize the receiver's clock with the sender's before it drifts too far. However, normally it takes a lot more than four bits in a row to lose sync, which suggests that the two ends of your serial line have clocks that are way out of sync with each other.

You should also read duskwuff's answer, which proposes a reason you might be seeing the two ends lose clock synchronization so quickly, and what you could do about it.

Glenn Willen
  • 2,250
  • 1
  • 11
  • 15