cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 UART using interrupt transmitts by byte or data elements array?

ManhPham
Associate III

Hello everyone,

I sent the data by UART with command:

uint16_t Size[8];

HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size)

Question: Size on this command is 16 bytes or Size is 8 data elements of array?

1 ACCEPTED SOLUTION

Accepted Solutions

@Andrew Neil wrote:


The setting is based on the current configuration of the UART


It's tested at runtime:

    /* In case of 9bits/No Parity transfer, pData needs to be handled as a uint16_t pointer */
    if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
    {
      pdata8bits  = NULL;
      pdata16bits = (const uint16_t *) pData;
    }
    else
    {
      pdata8bits  = pData;
      pdata16bits = NULL;
    }

this is where it makes the decision to treat the buffer as 8 or 16 bits.

 


@Andrew Neil wrote:
 whether it is sending 9-bit data frames, or 8-bit data frames.

Clearly, you can't fill a 9-bit data frame from a single 8-bit buffer entry - you need something at least 9 bits.

C doesn't provide a 9-bit datatype - the next available option after 8 bits (single byte) is 16 bits (two bytes).

View solution in original post

21 REPLIES 21

See the documentation:

 

/**
  * @brief Send an amount of data in interrupt mode.
  * @note   When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
  *         the sent data is handled as a set of u16. In this case, Size must indicate the number
  *         of u16 provided through pData.
  * @note   When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
  *         address of user data buffer containing data to be sent, should be aligned on a half word frontier (16 bits)
  *         (as sent data will be handled using u16 pointer cast). Depending on compilation chain,
  *         use of specific alignment compilation directives or pragmas might be required
  *         to ensure proper alignment for pData.
  *  huart UART handle.
  *  pData Pointer to data buffer (u8 or u16 data elements).
  *  Size  Amount of data elements (u8 or u16) to be sent.
  * @retval HAL status
  */
HAL_StatusTypeDef HAL_UART_Transmit_IT(UART_HandleTypeDef *huart, const uint8_t *pData, uint16_t Size)

 

See also the User Manual for the HAL; eg,

https://www.st.com/resource/en/user_manual/um2217-description-of-stm32h7-hal-and-lowlayer-drivers-stmicroelectronics.pdf#page=1876

 

I read this but I fill data elements, the received data is lost

I fill the byte, I received all data

So this document is not clearly, Size must be 2*data element arry (u16) or 4*data element arry (u32), right?

As it says, you use u16 when the UART frame's data payload size is larger than 8 bits - therefore can't be filled using a single u8 item.

So, if you are receiving complete data byte-by-byte, that means your data must fit in 8 bit payloads - so you should not be using a u16 buffer.

Show a minimal but complete complete example which illustrates your issue.

PS:

See also the device Reference Manual - see how the parity and extra data payload bits are handled...

My example:

uint16_t tx_data[7];

HAL_UART_Transmit_IT(&huart1, tx_data, 7);

or

HAL_UART_Transmit_IT(&huart1, tx_data, 14);

Which transmit command is correct?

 

that's not a complete example - is it?

 


@ManhPham wrote:

Which transmit command is correct?


As the documentation says, It depends on how you UART is configured - 8-bit (or smaller) data, or 9-bit data.

For 9-bit data, you need two buffer bytes for each transmitted UART Frame:

        |<-------------------------------------u16------------------------------------->|
+---------------------------------------+---------------------------------------+
Buffer: | -- : -- : -- : -- : -- : -- : -- : b8 | b7 : b6 : b5 : b4 : b3 : b2 : b1 : b0 |
+---------------------------------------+---------------------------------------+

 

PS - disclaimer: I don't know if that's the right bit/byte ordering - but you see how it takes two buffer bytes to contain the 9-bit payload?

 

PPS:

It's exactly the same when you use the non-interrupt method:

/**
  * @brief Send an amount of data in blocking mode.
  * @note   When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
  *         the sent data is handled as a set of u16. In this case, Size must indicate the number
  *         of u16 provided through pData.
  * @note   When UART parity is not enabled (PCE = 0), and Word Length is configured to 9 bits (M1-M0 = 01),
  *         address of user data buffer containing data to be sent, should be aligned on a half word frontier (16 bits)
  *         (as sent data will be handled using u16 pointer cast). Depending on compilation chain,
  *         use of specific alignment compilation directives or pragmas might be required
  *         to ensure proper alignment for pData.
  * @PAram huart   UART handle.
  * @PAram pData   Pointer to data buffer (u8 or u16 data elements).
  * @PAram Size    Amount of data elements (u8 or u16) to be sent.
  * @PAram Timeout Timeout duration.
  * @retval HAL status
  */

 

AndrewNeil_0-1727079333199.png

 

AndrewNeil_1-1727079789001.png

 

Techn
Senior III

By default it is uint8_t which is transmitted via uart. If you want to send integers, convert them to uint8_t and send . in the receiving side you have to take care to assemble it again. Does it answer your question?

If you feel a post has answered your question, please click "Accept as Solution".

@Techn wrote:

By default it is uint8_t ?


No.

The setting is based on the current configuration of the UART - whether it is sending 9-bit data frames, or 8-bit data frames.


@Andrew Neil wrote:


The setting is based on the current configuration of the UART


It's tested at runtime:

    /* In case of 9bits/No Parity transfer, pData needs to be handled as a uint16_t pointer */
    if ((huart->Init.WordLength == UART_WORDLENGTH_9B) && (huart->Init.Parity == UART_PARITY_NONE))
    {
      pdata8bits  = NULL;
      pdata16bits = (const uint16_t *) pData;
    }
    else
    {
      pdata8bits  = pData;
      pdata16bits = NULL;
    }

this is where it makes the decision to treat the buffer as 8 or 16 bits.

 


@Andrew Neil wrote:
 whether it is sending 9-bit data frames, or 8-bit data frames.

Clearly, you can't fill a 9-bit data frame from a single 8-bit buffer entry - you need something at least 9 bits.

C doesn't provide a 9-bit datatype - the next available option after 8 bits (single byte) is 16 bits (two bytes).