Skip to main content
Associate II
September 23, 2024
Solved

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

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?

This topic has been closed for replies.
Andrew Neil
Andrew NeilBest answer
Super User
September 23, 2024

@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).

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.

21 replies

Andrew Neil
Super User
September 23, 2024

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

 

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
ManhPhamAuthor
Associate II
September 23, 2024

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?

Andrew Neil
Super User
September 23, 2024

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...

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
Senior III
September 23, 2024

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""."
Andrew Neil
Super User
September 23, 2024

@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.

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.
Andrew Neil
Andrew NeilBest answer
Super User
September 23, 2024

@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).

A complex system that works is invariably found to have evolved from a simple system that worked.A complex system designed from scratch never works and cannot be patched up to make it work.