2025-11-30 6:51 AM - edited 2025-12-01 11:26 PM
I am trying to configure STM32 Nucleo-64 G070RB Board as Modbus RTU Master to send commands to a slave and receive response. I have connected MAX485 - TTL to RS485 board. Powered with 5V, DE and RE connected to USART1 DE Pin. Board's A and B are connected to slave (VFD) at a distance of less than 2 meters.
I am able to send commands and slave works fine. The response from salve received is not echo of the command as expected. UART reports Parity error and Noise error :1h and 2h => 3h.
When the slave was connected to PC and same commands were sent using QModBus, slave works the same way (as expected) and response received is correct (echo of the command).
UART1 configuration:
huart1.Instance = USART1;
huart1.Init.BaudRate = 9600;
huart1.Init.WordLength = UART_WORDLENGTH_9B;
huart1.Init.StopBits = UART_STOPBITS_1;
huart1.Init.Parity = UART_PARITY_EVEN;
huart1.Init.Mode = UART_MODE_TX_RX;
huart1.Init.HwFlowCtl = UART_HWCONTROL_NONE;
huart1.Init.OverSampling = UART_OVERSAMPLING_16;
huart1.Init.OneBitSampling = UART_ONE_BIT_SAMPLE_DISABLE;
huart1.Init.ClockPrescaler = UART_PRESCALER_DIV1;
huart1.AdvancedInit.AdvFeatureInit = UART_ADVFEATURE_NO_INIT;
if (HAL_RS485Ex_Init(&huart1, UART_DE_POLARITY_HIGH, 0, 0) != HAL_OK)This is the send receive function and code:
void send_modbus_write_register(UART_HandleTypeDef *huart, uint16_t reg_addr,
uint16_t reg_value, const char* cmd_name)
{
uint8_t request[8], response[8];
int uart_receive_error = HAL_ERROR;
// Build Modbus frame
...
// TX PHASE
HAL_StatusTypeDef tx_status = HAL_UART_Transmit(huart, request, 8, 100);
if (tx_status != HAL_OK) {
printf("%s: UART Transmit Error[%d]\r\n", cmd_name, tx_status);
}
// RX PHASE
// RX PHASE - HAL manages DE automatically. You still need a small delay
// for the VFD *processing time* (Modbus turnaround delay).
// Add VFD *processing time* delay only (no pin switching delay needed)
HAL_Delay(50); // Increased delay to 100ms for safety
uart_receive_error = HAL_UART_Receive(huart, response, 8, 200);
// Debug print
printf("%s Request: ", cmd_name);
printHexArray(request, 8);
printf("%s Response: ", cmd_name);
printHexArray(response, 8);
if (uart_receive_error != HAL_OK) {
printf("%s: UART Receive Error[%d]\r\n", cmd_name, uart_receive_error);
...
}This is the debug message:
Setting 40.00 Hertz
SET SPEED Request: Hex values to / from VFD: 0x01 0x06 0x20 0x01 0x0F 0xA0 0xD6 0x42
SET SPEED Response: Hex values to / from VFD: 0x1C 0x00 0x00 0x20 0x0A 0x00 0x00 0x00
SET SPEED: UART Receive Error[3]
Sending START signal
START Request: Hex values to / from VFD: 0x01 0x06 0x20 0x00 0x00 0x01 0x43 0xCA
START Response: Hex values to / from VFD: 0xF1 0x4F 0x00 0x08 0x68 0x02 0x00 0x20
START: UART Receive Error[3]
Sending STOP signal
STOP Request: Hex values to / from VFD: 0x01 0x06 0x20 0x00 0x00 0x05 0x42 0x09
STOP Response: Hex values to / from VFD: 0xF1 0x4F 0x00 0x08 0x68 0x02 0x00 0x20
STOP: UART Receive Error[3]
------------------------------------
I do not want to use manual DE / RE controlling / RTOS and Interrupt handling of UART Tx / Rx to make it simple.
Data sent by STM32 are received by slave but STM32 does not receive data sent by slave.
Any pointers?
Edited to apply source code formatting - please see How to insert source code for future reference.
2025-11-30 8:29 AM
>The response from slave received ->UART reports Parity error and Noise error
Did you check with a scope, what signal really comes back to master ?
+
Do you have error handling , on receive : ( one (!) error stops uart, until you start it again ) ?
2025-12-01 2:58 AM
Welcome to the forum.
You need to give more details - please see:
How to write your question to maximize your chances to find a solution
As @AScha.3 said, have you checked with a scope what's actually arriving at your UART RX pin?
This doesn't look right:
// RX PHASE - HAL manages DE automatically. You still need a small delay
// for the VFD *processing time* (Modbus turnaround delay).
// Add VFD *processing time* delay only (no pin switching delay needed)
HAL_Delay(50); // Increased delay to 100ms for safety
uart_receive_error = HAL_UART_Receive(huart, response, 8, 200);Are you sure that the data isn't arriving before you make the HAL_UART_Receive call ?
If the data transmission has finished before you call HAL_UART_Receive, it will not see that data!
2025-12-01 5:38 AM
RE is tied with DE. As hardware is supposed to RESET DE when transmission is complete which would be the value of RE. Slave would start sending response only after receiving the master's data (DE is SET during this time) and after RE is RESET, according to the Modbus protocol.
So data from slave sent data would arrive after master sending data and changing value of DE & RE as they are tied.
What is the UART receive buffer size?
2025-12-01 5:46 AM
Slave sends data which was verified using QModBus (master) and slave : STM32 not in picture in this setup.
I am about to test what signal is sent by slave using TTL Analyzer (I don't have scope) and would keep posted. I would keep in mind "one (!) error stops uart, until you start it again".
By the way, I might also try using UART ISR for receiving.
2025-12-01 5:58 AM - edited 2025-12-01 6:09 AM
As recommended above, take a scope a check the actual transmission with the STM32 master.
The Modbus RTU protocol is timing-based, a rather unfortunate circumstance tied to it's origins in the '70s.
Here a relevent snippet from the current spec:
Following the last transmitted character, a similar interval of at least 3.5 character times marks the end of the message. A new message can begin after this interval.
The entire message frame must be transmitted as a continuous stream. If a silent interval of more than 1.5 character times occurs before completion of the frame, the receiving device flushes the incomplete message and assumes that the next byte will be the address field of a new message.
I know from experience that many devices on the market do not very strictly adhere to this requirements.
In this case, you can either widen the tolerance band of the STM32 master, use another slave device, or switch to Modbus ASCII.
2025-12-01 6:12 AM
@arunachalamram wrote:What is the UART receive buffer size?
See the Reference Manual for details of the UART and its operation.
STM32G080RB doesn't seem to exist - did you mean STM32G081RB ?
via: https://www.st.com/en/microcontrollers-microprocessors/stm32g081rb.html#documentation
2025-12-01 6:39 AM
> RE is tied with DE. As hardware is supposed to RESET DE when transmission is complete which would be the value of RE. Slave would start sending response only after receiving the master's data (DE is SET during this time) and after RE is RESET, according to the Modbus protocol.
You are mixing up things here that are unrelated to each other. DE and RE have nothing to do with the Modbus protocol, but with the RS485 driver.
How these are managed is unrelated to Modbus.
The critical factor in the Modbus RTU HAL driver (HAL in a general sense not ST's interpretation) is the inter-character timer. Some STM32 UART/USART peripherals have direct support for idle time measurements, others not. In the latter case, a general timer could be used, tied e.g. to the UART TxE interrupt.
> I am able to send commands and slave works fine. The response from salve received is not echo of the command as expected. UART reports Parity error and Noise error :1h and 2h => 3h.
I recommend to check by setting breakpoints in the interrupt handler, where those errors are handled.
Perhaps your managment of the DE/RE pin states is not correct.
2025-12-01 11:38 PM
MCU is G070RB. Sorry that I wasted your time on this. Corrected / updated title and description now. Thank you as well.
Slave (VFD) is fixed for the application. Replies from you all point to and confirm reception issue. I shall investigate using logic analyzer and post the result.
2025-12-01 11:43 PM
Would go through Modbus RTU protocol and MCU Manual in detail and shall test using scope / logic analyzer.
Slave user Modbus RTU. I should make STM32 G070RB receive response from slave or move to some other MCU / PLC / HMI. Would keep posted. Thank you.