cancel
Showing results for 
Search instead for 
Did you mean: 

STM32 Modbus incorrect slave response to read holding register command

LPetr.1
Senior

Hello. I am trying to implement my own MODBUS write registers and read registers commands. I have connected serial analyzer to A and B pins of the transceiver and can monitor what I send and what I receive.

The stm32 that I am programming is acting as a master and I use modbus slave simulator on my pc to simulate slave device:

https://www.modbustools.com/modbus_slave.html

I have connect RS485 -> USB converter from my A B pins to PC via the USB cable.

  1. I write to modbus holding register using the following function:
uint8_t MODBUS_write_holding(uint8_t slave_id,uint16_t start_address,uint16_t value){
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, 1); // ENABLE THE TRANSCEIVER
 
	uint8_t message_buffer[20];
	message_buffer[0] = 	slave_id;
	message_buffer[1] = 	WRITE_SINGLE_HOLDING;
	message_buffer[2] =   	((uint16_t)start_address >> 8) & 0xFF;
	message_buffer[3] = 	((uint16_t)start_address >> 0) & 0xFF;
	message_buffer[4] =   	((uint16_t)value >> 8) & 0xFF;
	message_buffer[5] = 	((uint16_t)value >> 0) & 0xFF;
	uint16_t crc = MODBUS_CRC16_v3(message_buffer,6);
	message_buffer[6] = 	((uint16_t)crc >> 0) & 0xFF;
	message_buffer[7] = 	((uint16_t)crc >> 8) & 0xFF;
 
	HAL_UART_Transmit(&huart4, message_buffer, 8, 10);
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, 0); // DISABLE THE TRANSCEIVER
	return 0;
}

and I call it as following:

MODBUS_write_holding(1,4,0x1234);

The function is supposed to write value 0x1234 to holding register with an offset of 4.

Serial analyzer:

0693W00000QNMVQQA5.png 

Modbus slave simulator:

0693W00000QNMVLQA5.png 

As you can see from above, the value on the modbus simulator has been updated to 4660 when I have executed the command so everything seems to be working fine.

However, I have issues when I try to read back the register. I use the following command:

uint8_t MODBUS_read_multiple_holding(uint8_t slave_id,uint16_t start_address,uint16_t number_of_registers){
	//printf("Reading multiple holding register \n");
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, 1); // PULL LCD CS PIN HIGH
	uint8_t message_buffer[20];
	message_buffer[0] = 	slave_id;
	message_buffer[1] = 	READ_MULTIPLE_HOLDING;
	message_buffer[2] =   	((uint16_t)start_address >> 8) & 0xFF;
	message_buffer[3] = 	((uint16_t)start_address >> 0) & 0xFF;
	message_buffer[4] =   	((uint16_t)number_of_registers >> 8) & 0xFF;
	message_buffer[5] = 	((uint16_t)number_of_registers >> 0) & 0xFF;
	uint16_t crc = MODBUS_CRC16_v3(message_buffer,6);
	message_buffer[6] = 	((uint16_t)crc >> 0) & 0xFF;
	message_buffer[7] = 	((uint16_t)crc >> 8) & 0xFF;
 
 
	HAL_UART_Transmit(&huart4, message_buffer, 8, 10);
	HAL_GPIO_WritePin(GPIOA, GPIO_PIN_15, 0); // PULL LCD CS PIN HIGH
	return 0;
}

and I call it my main as following:

MODBUS_read_multiple_holding(1,4,1);

If I implemented the command correctly, this command should read 1 register at offset 4 from the slave ID = 1.

The serial analyzer output:

0693W00000QNMX2QAP.pngAs you can see from above, the serial analyzer picked up signal and received a response after 50ms.

If I zoom in to modbus request to read register:

0693W00000QNMXCQA5.png 

This is modbus response 50ms after the request:

0693W00000QNMSNQA5.pngThe response does not seem to be correct. I would like to understanding what is happening here and what could be the issue. I would appreciate a lot if someone could help me out here thanks in advance.

0 REPLIES 0