
Part 7 focuses on the slave firmware responsible for receiving and processing Modbus write requests. In this section, the slave parses the incoming frame and stores the transmitted register values into the internal register map so that they can be used by the application.
In this guide, we shall cover the following:
- Firmware Development.
- Results.
1. Firmware Development:
Open the slave project.
In main.c file, we start by declaring the following defines:
#define SingleWrite 0x06 #define MultiWrite 0x10
These are for single and multiple write to register, this is the same which has been used in part 6.
Also, define how many registers does the slave should have as follows:
#define REGMAP_SIZE 2
This guide shall use 2 register.
Next, declare the register array as follows:
uint16_t regMap[REGMAP_SIZE]={0};Next, declare variables to hold the following:
- Starting address
- Number of data.
- Counts.
uint16_t startAdd=0; uint16_t NumberOfData=0; uint16_t ByteCount=0;
In HAL_UARTEx_RxEventCallback function:
After checking if the packet is read request, we shall handle if it is write request.
First if the function code is Write single or Write multiple as follows:
if(rs485_buffer[1]==SingleWrite||rs485_buffer[1]==MultiWrite)
Within the if condition, first get starting address as follows:
startAdd = rs485_buffer[2] << 8 | rs485_buffer[3];
Get number of data ( number of registers to write to):
NumberOfData = rs485_buffer[4] << 8 | rs485_buffer[5];
Number of total bytes as follows:
ByteCount = rs485_buffer[6];
Most important part is to check the boundaries to ensure no corruption to data will happen as follows:
if(startAdd + NumberOfData - 1 <= REGMAP_SIZE) //Check the memory boundaries.
If it is within boundaries, fill the registers with the configuration data as follows:
for (int i = 0; i < NumberOfData; i++)
{
regMap[startAdd - 1 + i] =
(rs485_buffer[7 + i*2] << 8) |
rs485_buffer[8 + i*2];
}Hence, the updated function as follows:
void HAL_UARTEx_RxEventCallback(UART_HandleTypeDef *huart, uint16_t Size)
{ if(huart->Instance==USART1)
{
if(rs485_buffer[0]==address)
{
if(rs485_buffer[1]==Read)
{
modbus_receive(rs485_buffer,&modbusFrame);
newData=1;
}
if(rs485_buffer[1]==SingleWrite||rs485_buffer[1]==MultiWrite)
{
startAdd = rs485_buffer[2] << 8 | rs485_buffer[3];
NumberOfData = rs485_buffer[4] << 8 | rs485_buffer[5];
ByteCount = rs485_buffer[6];
if(startAdd + NumberOfData - 1 <= REGMAP_SIZE) //Check the memory boundaries.
{
for (int i = 0; i < NumberOfData; i++)
{
regMap[startAdd - 1 + i] =
(rs485_buffer[7 + i*2] << 8) |
rs485_buffer[8 + i*2];
}
}
}
}
}
HAL_UARTEx_ReceiveToIdle_IT(&huart1, rs485_buffer, bufferSize);
}Thats all for the slave configuration.
Save the project, build it and run it in debugging mode on your board.

2. Results:

Notice that when 1 register is being requested to write to, only one is being updated, for 2, both shall be updated. Once the master requested to write more than 2, 4 in this case, no update shall occur. This will ensure stable operation of the sensor.
Now, you can improve the code and feel free to comment with your feedback.
Happy coding 😉
Add Comment