How to Receive Variable-Length Data Over RS485 Using HAL_UART_Receive_IT on STM32F4?

Hello everyone, So I have this custom STM32F4 MCU board and need to receive various data sequences from a Master board over an RS485 network. The lengths of the data sequences are variable, such as 10 bytes, 25 bytes, etc. I need to handle each sequence and respond accordingly.

How can I effectively use the HAL functions HAL_UART_Receive_IT and HAL_UART_RxCpltCallback to properly receive variable-length data?

I noticed that the third argument of HAL_UART_Receive_IT requires a fixed number of bytes, like this:

HAL_UART_Receive_IT(&huart1, &uart1_rx_byte, no_of_bytes);


Can you suggest a good implementation for this?

The frame format for receiving data is as follows:
| Start byte | Slave Addr | Byte count | Func. ID | Data1 | Data2 | ... | Data n | Checksum byte 1 | Checksum byte 2 |

Where Byte count represents the number of bytes from Func. ID to Checksum byte 2.
Solution
define the states for your state machine
typedef enum {
    RX_STATE_WAIT_FOR_HEADER,
    RX_STATE_WAIT_FOR_PAYLOAD
} RxState;

RxState rx_state = RX_STATE_WAIT_FOR_HEADER;

define buffers and variables to store the received data
#define HEADER_SIZE

uint8_t uart_rx_header[HEADER_SIZE];
uint8_t uart_rx_payload[256];
uint8_t uart_rx_byte;
uint8_t byte_count = 0;

Initialize UART reception in the main function
HAL_UART_Receive_IT(&huart1, &uart_rx_byte, 1);

Implement the HAL_UART_RxCpltCallback to handle the reception
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
    static uint8_t header_index = 0;
    static uint8_t payload_index = 0;

    if (huart->Instance == USART1) {
        switch (rx_state) {
            case RX_STATE_WAIT_FOR_HEADER:
                uart_rx_header[header_index++] = uart_rx_byte;

                if (header_index == HEADER_SIZE) {
                    byte_count = uart_rx_header[2];
                    rx_state = RX_STATE_WAIT_FOR_PAYLOAD;
                    header_index = 0;
                    payload_index = 0;

                    HAL_UART_Receive_IT(huart, uart_rx_payload, byte_count + 2);
                } else {
                    HAL_UART_Receive_IT(huart, &uart_rx_byte, 1);
                }
                break;

            case RX_STATE_WAIT_FOR_PAYLOAD;

                rx_state = RX_STATE_WAIT_FOR_HEADER;
                HAL_UART_Receive_IT(huart, &uart_rx_byte, 1);
                break;
        }
    }
}
Was this page helpful?