cancel
Showing results for 
Search instead for 
Did you mean: 

Problem with STM32L4 USART and RS485. MCU misreads bytes in the line

GDeto
Associate II

Problem is solved when I put termination resistors in the stard and end of the bus but when I do not do I have a strange behavior of the MCU that I cannot explain/understand.

Below you see the screenshot of Yellow: RS485 bus, Blue: The RX Line on the MCU.

0690X00000Arg3wQAB.png

This is a 115200 Baudrate, Even Parity, 1 Stop Bit, 8 bit communication.

All the bytes are translated correctly every time (10mil messages exchanged) BUT the very last one sometimes it is not interpreted correctly.

You see that the oscilloscope finds this message as 0x04 or 0b00100000.

The MCU finds it 0x82 or 0b01000001. I looks like shifted by one bit to the left, including its parity bit.

I consider that this is caused by the glitch at the end of the message.... but if you see this is after the stop bit! So I do not really understand this behavior...

I am not using DMA, this is a byte by byte reading, and a quick interrupt handler.

It is true that the overrun flag is triggered but I cannot really tell why..

This is when the last byte is not received properly

0690X00000Arg5FQAR.png

This is when the last byte is received properly.

0690X00000Arg6WQAR.png

So my main question is...

Since this is coming from the datasheet of the MCU:

0690X00000Arg6qQAB.png

Why something in the Next Start bit which is clearly not valid is overwriting my message creating an overrun error?

Kind Regards,

Georgios Detorakis

19 REPLIES 19

Overrun tends to imply a data byte not extracted quickly enough. Would avoid doing message processing in interrupt/callback.

Review pin state as sampled by processor, look at GPIO IDR, check not seen as oscillating. Set pin with internal pull-up.​

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..
Ozone
Lead

> It is true that the overrun flag is triggered but I cannot really tell why..

As noted, it looks like you spend too much time in the handler.

Perhaps triggering some elaborate cecks/calculations on receiving a message-end character.

GDeto
Associate II

The Byte is collected in the --> void HAL_UART_RxCpltCallback(UART_HandleTypeDef* huart)

It is added to a buffer and there is another loop in the background that process this buffer with different priority of course.

The Serial Interrupts have higher Priority.

The Reason that I do not believe has to do with the handler time spent is because when I put the termination resistor I never see this problem again.... and the issue then seems to be related with the glitch. I cannot understand how the glitch can cause an overrun..

It is already using a pull up resistor.

I am using the 64MHz Clock Configuration.

Since it is using oversampling of 16 I cannot see how to check that the value is oscillating on the GPIO IDR.

I am not really sure I understood the last sentence above from Ozone:

"Perhaps triggering some elaborate cecks/calculations on receiving a message-end character"

Thanks

> The Reason that I do not believe has to do with the handler time spent is because when I put the termination resistor I never see this problem again.... and the issue then seems to be related with the glitch. I cannot understand how the glitch can cause an overrun..

Only if the glitch causes the noise to be interpreted as valid frame by the UART peripheral.

Is the cable properly twisted or shielded ?

How long is it ?

A rectangular signal at 112500 bps requires frequency components at least up to 10MHz, thus more then appr. 20cm are already a "long cable".

> I am not really sure I understood the last sentence above from Ozone:

> "Perhaps triggering some elaborate cecks/calculations on receiving a message-end character"

Other, seemingly inexperienced users present code were things like "printf ('received characters')" appear in the interrupt context (usually an interrupt callback), breaking the code.

Your post does not look like you falling into this easy trap. Just saying.

GDeto
Associate II

Hi Ozone,

In this thread I am not trying to solve the glitch from the Bus.

I am trying to understand why the USART is not working in the same way as I would expect a USART to work...

The Code was stripped down to the following to find it again when it happens:

void HAL_UART_RxCpltCallback(UART_HandleTypeDef* huart)

 {

 if(huart->Instance == USART1)

  {

uint8_t _ReceivedValue = IDCPrxbyte; // Get the Actual Received Value

if(_ReceivedValue == 0x04) // Received End of Transmission Message

// Enable a GPIO

else if(_ReceivedValue == 0x82) // Received End of Transmission Message

// Enable another GPIO

HAL_UART_Receive_IT(phidcp,&IDCPrxbyte,1);

  }

 }

I would not expect that this would consume any time..... But it still happens!

My Question how can it be any valid frame if the graph below is showing the following0690X00000ArhCkQAJ.png

The Glitch Duration is as shown below:

0690X00000ArhCuQAJ.png

This is 264ns.... the duration of each oversampling 16 is already double 562ns and it needs to find a few to identify this is an actual start bit...

Am I seeing something wrong here?

Additionally if I connect an FTDI 3.3V to USB I do not see any additional messages reported by the PC Serial Port and the message is interpreted correctly (I understand that the MCU does not have a Buffer / FIFO but at least it confirms that the proper message is sent in the BUS and my PC Serial Port does not see the "additional messages" the MCU sees in the bus)

What's your primary clock source, HSE or MSI?

JW

I am using the HSI.

I am new to the ST family so I hope I am not doing something wrong with the timing.

I post the complete System Clock Configuration

void SystemClock_Config(void)

{

RCC_OscInitTypeDef RCC_OscInitStruct = {0};

RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};

RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};

RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSI|RCC_OSCILLATORTYPE_LSI; //64MHz

RCC_OscInitStruct.HSIState = RCC_HSI_ON;

RCC_OscInitStruct.HSICalibrationValue = RCC_HSICALIBRATION_DEFAULT;

RCC_OscInitStruct.LSIState = RCC_LSI_ON;

RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;

RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSI;

RCC_OscInitStruct.PLL.PLLM = 1;

RCC_OscInitStruct.PLL.PLLN = 8;

RCC_OscInitStruct.PLL.PLLP = RCC_PLLP_DIV7;

RCC_OscInitStruct.PLL.PLLQ = RCC_PLLQ_DIV2;

RCC_OscInitStruct.PLL.PLLR = RCC_PLLR_DIV2;

if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK|RCC_CLOCKTYPE_SYSCLK|RCC_CLOCKTYPE_PCLK1|RCC_CLOCKTYPE_PCLK2;

RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;

RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;

RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV1;

RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;

if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK) //if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)

{

}

PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_USART1|RCC_PERIPHCLK_LPUART1|RCC_PERIPHCLK_I2C1;

PeriphClkInit.Usart1ClockSelection = RCC_USART1CLKSOURCE_PCLK2;

PeriphClkInit.Lpuart1ClockSelection = RCC_LPUART1CLKSOURCE_PCLK1;

PeriphClkInit.I2c1ClockSelection = RCC_I2C1CLKSOURCE_PCLK1;

// PeriphClkInit.UsbClockSelection = RCC_USBCLKSOURCE_MSI;

if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

if (HAL_PWREx_ControlVoltageScaling(PWR_REGULATOR_VOLTAGE_SCALE1) != HAL_OK)

{

_Error_Handler(__FILE__, __LINE__);

}

HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq()/1000); // Configure the Systick interrupt time //

HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); // Configure the Systick //

//  /* Enable MSI Auto calibration */

// HAL_RCCEx_EnableMSIPLLMode();

HAL_NVIC_SetPriority(SysTick_IRQn, 3, 0); // SysTick_IRQn interrupt configuration //

}

GDeto
Associate II

Some Additional Information.

I added two debug Points for the Interrupts ( Green & Pink Signals )

Yellow: The RS485 Bus

Green: void USART1_IRQHandler_TX_RX(void)

Pink: void HAL_UART_RxCpltCallback(UART_HandleTypeDef* huart)

Blue: Rx

Scenario with the glich[Problem on Last Measurement]

0690X00000AriJrQAJ.png

Scenario without the glich[Correct Information]

0690X00000AriK1QAJ.png

What you can see over here is that the interrupt when I have a glich is happening much later than when there is no glich.

I want to believe that there is a configuration I have is wrong but for the moment I do not know where shall I look into.

The Start Bit, the Data the Parity and the Stop Bit are all there and there is a glich ... so why the original message is shifted? Looks like the timing is not very well respected or I do not understand something in the manual.

What else could be causing a service delay in the IRQ Handler firing? Interrupt for ORE or NE rather than RXNE? If the USART has a FIFO make sure to loop to ensure it is empty.

Does look to have a large negative spike on the top trace view.

I've seen line noise generate spurious characters, not sure I've seen overruns.

Tips, Buy me a coffee, or three.. PayPal Venmo
Up vote any posts that you find helpful, it shows what's working..