Hello @SergeyV,
In the master/slave stack examples the register addresses are zero based. in the example if you need to address the 4x register area (Holding register) = 40002 the stack will have the offset = 0x0002
Modbus Master:
The address of the register is defined in the object dictionary
Code: Select all
// Example Data (Object) Dictionary for Modbus parameters:
// The CID field in the table must be unique.
// Modbus Slave Addr field defines slave address of the device with correspond parameter.
// Modbus Reg Type - Type of Modbus register area (Holding register, Input Register and such).
// Reg Start field defines the start Modbus register number and Reg Size defines the number of registers for the characteristic accordingly.
// The Instance Offset defines offset in the appropriate parameter structure that will be used as instance to save parameter value.
// Data Type, Data Size specify type of the characteristic and its data size.
// Parameter Options field specifies the options that can be used to process parameter value (limits or masks).
// Access Mode - can be used to implement custom options for processing of characteristic (Read/Write restrictions, factory mode values and etc).
const mb_parameter_descriptor_t device_parameters[] = {
// { CID, Param Name, Units, Modbus Slave Addr, Modbus Reg Type, Reg Start, Reg Size, Instance Offset, Data Type, Data Size, Parameter Options, Access Mode}
{ CID_HOLD_DATA_0, STR("Humidity_1"), STR("%rH"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING, 2 /*(for address 40002)*/, 2,
HOLD_OFFSET(holding_data0), PARAM_TYPE_FLOAT, 4, OPTS( 0, 65535, 1 ), PAR_PERMS_READ_WRITE_TRIGGER },
....
}
Code: Select all
mb_reg_start = 2 (Relative register address of the characteristic in the register area.)
Modbus Slave:
Register definition example:
Code: Select all
#define MB_REG_INPUT_START_AREA0 (0)
#define MB_REG_HOLDING_START_AREA0 (0) // <<<<<<<<<<< register offset for the area
#define MB_REG_HOLD_CNT (100)
#define MB_REG_INPUT_CNT (100)
mb_register_area_descriptor_t reg_area; // Modbus register area descriptor structure
unit16_t holding_reg_area[MB_REG_HOLD_CNT] = {0}; // storage area for holding registers
unit16_t input_reg_area[MB_REG_INPUT_CNT] = {0}; // storage area for input registers
reg_area.type = MB_PARAM_HOLDING; // Set type of register area
reg_area.start_offset = MB_REG_HOLDING_START_AREA0; // Offset of register area in Modbus protocol (<<<< register offset)
reg_area.address = (void*)&holding_reg_area[0]; // Set pointer to storage instance
reg_area.size = sizeof(holding_reg_area) << 1; // Set the size of register storage area in bytes
ESP_ERROR_CHECK(mbc_slave_set_descriptor(reg_area));
reg_area.type = MB_PARAM_INPUT;
reg_area.start_offset = MB_REG_INPUT_START_AREA0;
reg_area.address = (void*)&input_reg_area[0];
reg_area.size = sizeof(input_reg_area) << 1;
ESP_ERROR_CHECK(mbc_slave_set_descriptor(reg_area));
The function mbc_modbus_slave.c::mbc_slave_find_reg_descriptor(mb_param_type_t type, uint16_t addr, size_t regs)
https://github.com/espressif/esp-idf/bl ... lave.c#L62
is called from each function handler to check if the register being read by master corresponds to defined register area.
The slave code supports definition of several register areas of each type.
In your question it is not clear if you going to define register with offset 4000 in master or slave and the address looks very similar to Modicon notation of registers and my answer follows this notation. Register types and reference ranges recognized with Modicon notation are as follows:
0x = Coil = 00001-09999
1x = Discrete Input = 10001-19999
3x = Input Register = 30001-39999
4x = Holding Register = 40001-49999
Please let me know if you need more information. Thanks.