cancel
Showing results for 
Search instead for 
Did you mean: 

Call to HAL_UART_Transmit() not sending the expected amount of data?

SKarl.19
Associate II

I have a strange issue here. I'm trying to do a short, blocking, UART transmission.

I have a 23 byte uint8_t array ( MSG ) that I construct before calling the HAL_UART_Transmit() function to send the data. (SLAVE_MSG_SIZE = 23, UART is a pointer to the UART4 object)

HAL_UART_Transmit(UART, &MSG, SLAVE_MSG_SIZE, 1);

The problem is that it never sends just 23 bytes, its sends more, sometimes less, but almost always more. Most I've seen is around 46 bytes, which is close to 2x, which may be a clue to what is going on.

(The receiver side can handle extra bytes at the end because it just doesn't look at them, but when the TX packet is too short, the 2 CRC bytes are absent and the CRC check fails.)

The strange thing is that if I manually set the "data size" parameter in the HAL call to 15 bytes or less, I get the expected, truncated data of the correct length. However, if the size argument is >15 bytes, the amount of transmitted data is always more than the expected value.

My code is the following:

void Slave_Transmit(struct bhg5_slave_message MSG_Content, UART_HandleTypeDef *UART){
 
	uint8_t MSG[SLAVE_MSG_SIZE];
  
	//build message packet
 	MSG[0] = 0xAA;
 	MSG[1] = MSG_Content.address;
 	MSG[2] = MSG_Content.node_address;
 	MSG[3] = MSG_Content.protocol_version;
 	MSG[4] = MSG_Content.message_type;
 	MSG[5] = (MSG_Content.payload1) & 0xFF;				//low payload byte
 	MSG[6] = (MSG_Content.payload1 >> 8) & 0xFF;		//...shift right and mask
 	MSG[7] = (MSG_Content.payload1 >> 16) & 0xFF;		//...shift right and mask
 	MSG[8] = (MSG_Content.payload1 >> 24) & 0xFF;		//high payload byte
 	MSG[9] = (MSG_Content.payload2) & 0xFF;				//low payload byte
 	MSG[10] = (MSG_Content.payload2 >> 8) & 0xFF;		//...shift right and mask
 	MSG[11] = (MSG_Content.payload2 >> 16) & 0xFF;		//...shift right and mask
 	MSG[12] = (MSG_Content.payload2 >> 24) & 0xFF;		//high payload byte
 	MSG[13] = (MSG_Content.payload3) & 0xFF;			//low payload byte
 	MSG[14] = (MSG_Content.payload3 >> 8) & 0xFF;		//...shift right and mask
 	MSG[15] = (MSG_Content.payload3 >> 16) & 0xFF;		//...shift right and mask
 	MSG[16] = (MSG_Content.payload3 >> 24) & 0xFF;		//high payload byte
 	MSG[17] = (MSG_Content.payload4) & 0xFF;			//low payload byte
 	MSG[18] = (MSG_Content.payload4 >> 8) & 0xFF;		//...shift right and mask
 	MSG[19] = (MSG_Content.payload4 >> 16) & 0xFF;		//...shift right and mask
 	MSG[20] = (MSG_Content.payload4 >> 24) & 0xFF;		//high payload byte
   
	// compute CRC to place into last 2 bytes
 	uint32_t calculatedCRC = HAL_CRC_Calculate(&hcrc, MSG, 21);		
	calculatedCRC = calculatedCRC & 0xFFFF;							// only lower 2 bytes will be used
  
	MSG[21] = calculatedCRC & 0xFF;				//low CRC byte
 	MSG[22] = (calculatedCRC >> 8) & 0xFF;			//high CRC byte
  
	HAL_UART_Transmit(UART, &MSG, SLAVE_MSG_SIZE, 1);// Sending in normal mode
 	//HAL_UART_Transmit(UART, &MSG, 16, 1);// Sending in normal mode
 }

The UART initialization create by HAL is the following:

static void MX_UART4_Init(void)
{
  /* USER CODE BEGIN UART4_Init 0 */
  /* USER CODE END UART4_Init 0 */
  /* USER CODE BEGIN UART4_Init 1 */
  /* USER CODE END UART4_Init 1 */
  huart4.Instance = UART4;
  huart4.Init.BaudRate = 230400;
  huart4.Init.WordLength = UART_WORDLENGTH_8B;
  huart4.Init.StopBits = UART_STOPBITS_1;
  huart4.Init.Parity = UART_PARITY_NONE;
  huart4.Init.Mode = UART_MODE_TX_RX;
  huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart4.Init.OverSampling = UART_OVERSAMPLING_16;
  huart4.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart4.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart4) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN UART4_Init 2 */
  /* USER CODE END UART4_Init 2 */
}

What could be going on here?

Any help appreciated.

7 REPLIES 7
Karl Yamashita
Lead III

I tried your code and I get less bytes sent. Then I noticed your timeout was 1 so i changed it to 100 and it works.

Now as for you seeing more bytes being sent most of the time, what is calling your function? Do you see your start byte 0xAA being sent twice? I think with the timeout of 1 and the function being called twice you're seeing a combination of two short sends that looks like more than 32 bytes. Have you looked on an oscilloscope to see if that is true?

Also, your checksum starts at index 21 but you have 10 more bytes after that. Are those 10 bytes don't care?

Tips and Tricks with TimerCallback https://www.youtube.com/@eebykarl
If you find my solution useful, please click the Accept as Solution so others see the solution.

Hi,

I am experiencing a similar problem. We have extra bytes sent, I tried changing the baudrate to slower one and it did not solve the problem, in bold the extra bytes:

=~=~=~=~=~=~=~=~=~=~=~= PuTTY log 2024.04.09 16:34:02 =~=~=~=~=~=~=~=~=~=~=~=
ô?ò To +1660011 :PA_POW      StopAll from : FoxMan
å”2¯ûÏýô?ò sµ +1668017 :PA_POW      StopAll from : FoxMan
Ö5v,¯ûÏýô?ò sÈ 1668026 :MEAS        PaGan_1 : 48      PaGan_2 : 49      PaInputCurrent : 29      PaOutputCurrent : 10      PaInputVoltage : 0       AnalogPaEdge : 2829    
ÌÐ 0¯ûÏýô?ò tQ I{"PROC":"Temperature","List":[28,28,27,27,28,28,29,28,28,27,26,27,27,26]}|ïSV¯ûÏýô?ò tR {{"PROC":"Analog","AnalogPaEdge":2829,"PaGan_1":48,"PaGan_2":49,"PaInputCurrent":29,"PaInputVoltage":0,"PaOutputCurrent":10}Í»8o¯ûÏýô?ò w° 1669026 :MEAS        PaGan_1 : 49      PaGan_2 : 49      PaInputCurrent : 29      PaOutputCurrent : 10      PaInputVoltage : 0       AnalogPaEdge : 2829    
¶ÞìÓ¯ûÏýô?ò x9 I{"PROC":"Temperature","List":[28,28,27,27,28,28,29,28,28,27,26,27,27,26]}–|ÏJ¯ûÏýô?ò x: {{"PROC":"Analog","AnalogPaEdge":2829,"PaGan_1":49,"PaGan_2":49,"PaInputCurrent":29,"PaInputVoltage":0,"PaOutputCurrent":10}·¯ûÏýô?ò { +1670011 :PA_POW      StopAll from : FoxMan
{á5¯¯ûÏýô?ò {˜ 
 
The code use to initialize the uart :

 

/* UART4 init function */
void MX_UART4_Init(void)
{
  /* USER CODE BEGIN UART4_Init 0 */

  /* USER CODE END UART4_Init 0 */

  /* USER CODE BEGIN UART4_Init 1 */

  /* USER CODE END UART4_Init 1 */
  huart4.Instance = UART4;
  huart4.Init.BaudRate = 115200;
  huart4.Init.WordLength = UART_WORDLENGTH_8B;
  huart4.Init.StopBits = UART_STOPBITS_1;
  huart4.Init.Parity = UART_PARITY_NONE;
  huart4.Init.Mode = UART_MODE_TX_RX;
  huart4.Init.HwFlowCtl = UART_HWCONTROL_NONE;
  huart4.Init.OverSampling = UART_OVERSAMPLING_16;
  huart4.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
  huart4.Init.ClockPrescaler = UART_PRESCALER_DIV1;
  huart4.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
  if (HAL_UART_Init(&huart4) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetTxFifoThreshold(&huart4, UART_TXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_SetRxFifoThreshold(&huart4, UART_RXFIFO_THRESHOLD_1_8) != HAL_OK)
  {
    Error_Handler();
  }
  if (HAL_UARTEx_DisableFifoMode(&huart4) != HAL_OK)
  {
    Error_Handler();
  }
  /* USER CODE BEGIN UART4_Init 2 */

  /* USER CODE END UART4_Init 2 */
}

 

We did validate that the length of the logs and content in valid when calling uart:

 

    HAL_UART_Transmit(&huart4, (uint8_t *) str.data(), str.size(), 100);

 

Should we use a longer timeout than 100 and what does it implies?

Regards,

Sylvain

Pavel A.
Evangelist III

@SylvainQuaze What are str.data(), str.size() ? If you use C++, there's lot of moving parts under the cover. Constructors, destructors, overloaded functions... 

100 = 100 milli-seconds

Usually the UART shouldn't timeout, or give underflow problems in a polled sense. You should perhaps also pay attention to the error/status the function returns to see if it was successful.

The timeout should be longer than it takes to send the message content over the wire at the baud rate you've chosen.

At 115200, 87 micro-seconds per byte?

Binary data packets aren't going to appear as readable ASCII in a terminal window, control characters may also impact how the pane scrolls. Perhaps find a terminal that allows your bytes to be presented as hex pairs, like RealTerm ?

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

Hi @Pavel A., it seems as I found the issue, I am new to the company and I have a undocumented source code. It seems as that a protocol header is added by our software, explaining the undesired bytes.

Hi @Tesla DeLorean , it seems as I found the issue, I am new to the company and I have a undocumented source code. It seems as that a protocol header is added by our software, explaining the undesired bytes.

Great - please mark that as the solution.

Note that all replies are visible to everyone - there's no need to repeat for each contributor!

You can '@' mention multiple people in one post; eg,  @SylvainQuaze  @Andrew Neil