Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
10 changes: 8 additions & 2 deletions examples/serial/mb_serial_master/main/serial_master.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,7 @@ enum {
CID_HOLD_DATA_1,
CID_INP_DATA_2,
CID_HOLD_DATA_2,
CID_HOLD_CUSTOM1,
CID_HOLD_TEST_REG,
CID_RELAY_P1,
CID_RELAY_P2,
Expand Down Expand Up @@ -133,6 +134,10 @@ const mb_parameter_descriptor_t device_parameters[] = {
TEST_HOLD_REG_START(holding_data2), TEST_HOLD_REG_SIZE(holding_data2),
HOLD_OFFSET(holding_data2), PARAM_TYPE_FLOAT, 4,
OPTS( TEST_HUMI_MIN, TEST_HUMI_MAX, 0 ), PAR_PERMS_READ_WRITE_TRIGGER },
{ CID_HOLD_CUSTOM1, STR("CustomHoldReg"), STR("__"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING,
TEST_HOLD_REG_START(holding_area1_end), 1,
HOLD_OFFSET(holding_area1_end), PARAM_TYPE_U16, 2,
OPTS( 0x03, 0x06, 0x5555 ), PAR_PERMS_READ_WRITE_CUST_CMD },
{ CID_HOLD_TEST_REG, STR("Test_regs"), STR("__"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING,
TEST_HOLD_REG_START(test_regs), TEST_ARR_REG_SZ,
HOLD_OFFSET(test_regs), PARAM_TYPE_ASCII, (TEST_ARR_REG_SZ * 2),
Expand Down Expand Up @@ -320,8 +325,9 @@ static void master_operation_func(void *arg)
if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) {
void *temp_data_ptr = master_get_param_data(param_descriptor);
assert(temp_data_ptr);
if ((param_descriptor->param_type == PARAM_TYPE_ASCII) &&
(param_descriptor->cid == CID_HOLD_TEST_REG)) {
if ((param_descriptor->cid >= CID_HOLD_CUSTOM1)
&& (param_descriptor->cid <= CID_HOLD_TEST_REG)) {
// Check test parameters
if (TEST_VERIFY_VALUES(master_handle, param_descriptor, (uint32_t *)temp_data_ptr) == ESP_OK) {
ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = (0x%" PRIx32 ") read successful.",
(int)param_descriptor->cid,
Expand Down
10 changes: 8 additions & 2 deletions examples/tcp/mb_tcp_master/main/tcp_master.c
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ enum {
CID_HOLD_DATA_1,
CID_INP_DATA_2,
CID_HOLD_DATA_2,
CID_HOLD_CUSTOM1,
CID_HOLD_TEST_REG,
CID_RELAY_P1,
CID_RELAY_P2,
Expand Down Expand Up @@ -162,6 +163,10 @@ const mb_parameter_descriptor_t device_parameters[] = {
TEST_HOLD_REG_START(holding_data2), TEST_HOLD_REG_SIZE(holding_data2),
HOLD_OFFSET(holding_data2), PARAM_TYPE_FLOAT, 4,
OPTS( TEST_HUMI_MIN, TEST_HUMI_MAX, 0 ), PAR_PERMS_READ_WRITE_TRIGGER },
{ CID_HOLD_CUSTOM1, STR("CustomHoldReg"), STR("__"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING,
TEST_HOLD_REG_START(holding_area1_end), 1,
HOLD_OFFSET(holding_area1_end), PARAM_TYPE_U16, 2,
OPTS( 0x03, 0x06, 0x5555 ), PAR_PERMS_READ_WRITE_CUST_CMD },
{ CID_HOLD_TEST_REG, STR("Test_regs"), STR("__"), MB_DEVICE_ADDR1, MB_PARAM_HOLDING,
TEST_HOLD_REG_START(test_regs), TEST_ARR_REG_SZ,
HOLD_OFFSET(test_regs), PARAM_TYPE_ASCII, (TEST_ARR_REG_SZ * 2),
Expand Down Expand Up @@ -460,8 +465,9 @@ static void master_operation_func(void *arg)
if ((err != ESP_ERR_NOT_FOUND) && (param_descriptor != NULL)) {
void *temp_data_ptr = master_get_param_data(param_descriptor);
assert(temp_data_ptr);
if ((param_descriptor->param_type == PARAM_TYPE_ASCII) &&
(param_descriptor->cid == CID_HOLD_TEST_REG)) {
if ((param_descriptor->cid >= CID_HOLD_CUSTOM1)
&& (param_descriptor->cid <= CID_HOLD_TEST_REG)) {
// Check test parameters
if (TEST_VERIFY_VALUES(master_handle, param_descriptor, (uint32_t *)temp_data_ptr) == ESP_OK) {
ESP_LOGI(TAG, "Characteristic #%d %s (%s) value = (0x%" PRIx32 ") read successful.",
(int)param_descriptor->cid,
Expand Down
46 changes: 46 additions & 0 deletions modbus/mb_controller/common/esp_modbus_master.c
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
#include "mbc_master.h" // for master interface define
#include "esp_modbus_master.h" // for public interface defines

// Helper macro to set custom command
#define SET_CMD(mode, rd_cmd, wr_cmd) ((mode == MB_PARAM_WRITE) ? wr_cmd : (mode == MB_PARAM_READ) ? rd_cmd : 0)

static const char TAG[] __attribute__((unused)) = "MB_CONTROLLER_MASTER";

// This file implements public API for Modbus master controller.
Expand Down Expand Up @@ -714,3 +717,46 @@ esp_err_t mbc_master_set_param_data(void* dest, void* src, mb_descr_type_t param
}
return err;
}

// Helper function to get configured Modbus command for each type of Modbus register area.
// Supports custom command options using the PAR_PERMS_CUST_CMD permission.
uint8_t mbc_master_get_command(const mb_parameter_descriptor_t *pdescr, mb_param_mode_t mode)
{
MB_RETURN_ON_FALSE((pdescr), 0, TAG, "incorrect data pointer.");
uint8_t command = 0;
switch(pdescr->mb_param_type)
{
case MB_PARAM_HOLDING:
if (pdescr->access & PAR_PERMS_CUST_CMD) {
command = SET_CMD(mode, (uint8_t)pdescr->param_opts.cust_cmd_read, (uint8_t)pdescr->param_opts.cust_cmd_write);
} else {
command = SET_CMD(mode, MB_FUNC_READ_HOLDING_REGISTER, MB_FUNC_WRITE_MULTIPLE_REGISTERS);
}
break;
case MB_PARAM_INPUT:
if (pdescr->access & PAR_PERMS_CUST_CMD) {
command = SET_CMD(mode, (uint8_t)pdescr->param_opts.cust_cmd_read, 0);
} else {
command = SET_CMD(mode, MB_FUNC_READ_INPUT_REGISTER, 0);
}
break;
case MB_PARAM_COIL:
if (pdescr->access & PAR_PERMS_CUST_CMD) {
command = SET_CMD(mode, (uint8_t)pdescr->param_opts.cust_cmd_read, (uint8_t)pdescr->param_opts.cust_cmd_write);
} else {
command = SET_CMD(mode, MB_FUNC_READ_COILS, MB_FUNC_WRITE_MULTIPLE_COILS);
}
break;
case MB_PARAM_DISCRETE:
if (pdescr->access & PAR_PERMS_CUST_CMD) {
command = SET_CMD(mode, (uint8_t)pdescr->param_opts.cust_cmd_read, 0);
} else {
command = SET_CMD(mode, MB_FUNC_READ_DISCRETE_INPUTS, 0);
}
break;
default:
ESP_LOGE(TAG, "%s: Incorrect param type (%u)", __FUNCTION__, (unsigned)pdescr->mb_param_type);
break;
}
return command;
}
63 changes: 46 additions & 17 deletions modbus/mb_controller/common/include/esp_modbus_master.h
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,37 @@ extern "C" {
#define MB_EACH_ELEM(psrc, pdest, arr_size, elem_size) \
(int i = 0; (i < (arr_size / elem_size)); i++, pdest += elem_size, psrc += elem_size)

/**
* @brief Request mode for parameter to use in data dictionary
*/
typedef enum {
MB_PARAM_READ, /*!< Read parameter values. */
MB_PARAM_WRITE /*!< Write parameter values. */
} mb_param_mode_t;


/*!
* \brief Modbus parameter options for description table
*/
typedef union {
struct {
int opt1; /*!< Parameter option1 */
int opt2; /*!< Parameter option2 */
int opt3; /*!< Parameter option3 */
};
struct {
int min; /*!< Parameter minimum value */
int max; /*!< Parameter maximum value */
int step; /*!< Step of parameter change tracking */
};
struct {
int cust_cmd_read; /*!< Parameter custom read request command */
int cust_cmd_write; /*!< Parameter custom write request command */
int cust_cmd_not_used; /*!< Not used option for custom request */
};
} mb_parameter_opt_t;


/*!
* \brief Modbus descriptor table parameter type defines.
*/
Expand Down Expand Up @@ -109,36 +140,22 @@ typedef enum {
PARAM_MAX_SIZE
} mb_descr_size_t;

/*!
* \brief Modbus parameter options for description table (associated with the characteristic).
* and can be used in user application to process data.
*/
typedef union {
struct {
int opt1; /*!< Parameter option1 */
int opt2; /*!< Parameter option2 */
int opt3; /*!< Parameter option3 */
}; /*!< Parameter options version 1 */
struct {
int min; /*!< Parameter minimum value */
int max; /*!< Parameter maximum value */
int step; /*!< Step of parameter change tracking */
}; /*!< Parameter options version 2 */
} mb_parameter_opt_t;

/**
* @brief Permissions for the characteristics
*/
typedef enum {
PAR_PERMS_READ = 1 << BIT0, /**< the characteristic of the device are readable */
PAR_PERMS_WRITE = 1 << BIT1, /**< the characteristic of the device are writable*/
PAR_PERMS_TRIGGER = 1 << BIT2, /**< the characteristic of the device are triggerable */
PAR_PERMS_CUST_CMD = 1 << BIT3, /**< the characteristic uses custom commands */
PAR_PERMS_READ_WRITE = PAR_PERMS_READ | PAR_PERMS_WRITE, /**< the characteristic of the device are readable & writable */
PAR_PERMS_READ_TRIGGER = PAR_PERMS_READ | PAR_PERMS_TRIGGER, /**< the characteristic of the device are readable & triggerable */
PAR_PERMS_WRITE_TRIGGER = PAR_PERMS_WRITE | PAR_PERMS_TRIGGER, /**< the characteristic of the device are writable & triggerable */
PAR_PERMS_READ_WRITE_TRIGGER = PAR_PERMS_READ_WRITE | PAR_PERMS_TRIGGER, /**< the characteristic of the device are readable & writable & triggerable */
PAR_PERMS_READ_WRITE_CUST_CMD = PAR_PERMS_READ_WRITE | PAR_PERMS_CUST_CMD /**< the characteristic supports custom read/write commands */
} mb_param_perms_t;


/**
* @brief Characteristics descriptor type is used to describe characteristic and
* link it with Modbus parameters that reflect its data.
Expand Down Expand Up @@ -466,6 +483,18 @@ mb_err_enum_t mbc_reg_coils_master_cb(mb_base_t *inst, uint8_t *reg_buffer, uint
*/
esp_err_t mbc_master_set_param_data(void* dest, void* src, mb_descr_type_t param_type, size_t param_size);

/**
* @brief The helper function to get supported modbus function code (command) according to parameter type
*
* @param[in] pdescr the pointer to the characteristic descriptor in data dictionary
* @param[in] mode access mode for characteristic
*
* @return
* - modbus function code, if the command is correctly configured
* - 0 - invalid argument or command not found
*/
uint8_t mbc_master_get_command(const mb_parameter_descriptor_t *pdescr, mb_param_mode_t mode);

#ifdef __cplusplus
}
#endif
Expand Down
8 changes: 0 additions & 8 deletions modbus/mb_controller/common/mbc_master.h
Original file line number Diff line number Diff line change
Expand Up @@ -31,14 +31,6 @@ extern "C" {
// will be dependent on response time set by timer + convertion time if the command is received
#define MB_MAX_RESP_DELAY_MS (3000)

/**
* @brief Request mode for parameter to use in data dictionary
*/
typedef enum {
MB_PARAM_READ, /*!< Read parameter values. */
MB_PARAM_WRITE /*!< Write parameter values. */
} mb_param_mode_t;

/**
* @brief Modbus controller handler structure
*/
Expand Down
36 changes: 1 addition & 35 deletions modbus/mb_controller/serial/mbc_serial_master.c
Original file line number Diff line number Diff line change
Expand Up @@ -312,40 +312,6 @@ static esp_err_t mbc_serial_master_get_cid_info(void *ctx, uint16_t cid, const m
return ESP_OK;
}

// Helper function to get modbus command for each type of Modbus register area
static uint8_t mbc_serial_master_get_command(mb_param_type_t param_type, mb_param_mode_t mode)
{
uint8_t command = 0;
switch (param_type)
{
case MB_PARAM_HOLDING:
command = (mode == MB_PARAM_WRITE) ? MB_FUNC_WRITE_MULTIPLE_REGISTERS : MB_FUNC_READ_HOLDING_REGISTER;
break;
case MB_PARAM_INPUT:
command = MB_FUNC_READ_INPUT_REGISTER;
break;
case MB_PARAM_COIL:
command = (mode == MB_PARAM_WRITE) ? MB_FUNC_WRITE_MULTIPLE_COILS : MB_FUNC_READ_COILS;
break;
case MB_PARAM_DISCRETE:
if (mode != MB_PARAM_WRITE)
{
command = MB_FUNC_READ_DISCRETE_INPUTS;
}
else
{
ESP_LOGE(TAG, "%s: Incorrect mode (%u)",
__FUNCTION__, (unsigned)mode);
}
break;
default:
ESP_LOGE(TAG, "%s: Incorrect param type (%u)",
__FUNCTION__, (unsigned)param_type);
break;
}
return command;
}

// Helper to search parameter by name in the parameter description table
// and fills Modbus request fields accordingly
static esp_err_t mbc_serial_master_set_request(void *ctx, uint16_t cid, mb_param_mode_t mode,
Expand All @@ -365,7 +331,7 @@ static esp_err_t mbc_serial_master_set_request(void *ctx, uint16_t cid, mb_param
request->slave_addr = reg_ptr->mb_slave_addr;
request->reg_start = reg_ptr->mb_reg_start;
request->reg_size = reg_ptr->mb_size;
request->command = mbc_serial_master_get_command(reg_ptr->mb_param_type, mode);
request->command = mbc_master_get_command(reg_ptr, mode);
MB_RETURN_ON_FALSE((request->command > 0), ESP_ERR_INVALID_ARG, TAG, "mb incorrect command or parameter type.");
if (reg_data)
{
Expand Down
37 changes: 1 addition & 36 deletions modbus/mb_controller/tcp/mbc_tcp_master.c
Original file line number Diff line number Diff line change
Expand Up @@ -317,41 +317,6 @@ static esp_err_t mbc_tcp_master_get_cid_info(void *ctx, uint16_t cid, const mb_p
return ESP_OK;
}

// Helper function to get modbus command for each type of Modbus register area
static uint8_t mbc_tcp_master_get_command(mb_param_type_t param_type, mb_param_mode_t mode)
{
uint8_t command = 0;
switch(param_type){ // Check commands
case MB_PARAM_HOLDING:
command = (mode == MB_PARAM_WRITE) ?
MB_FUNC_WRITE_MULTIPLE_REGISTERS :
MB_FUNC_READ_HOLDING_REGISTER;
break;
case MB_PARAM_INPUT:
command = MB_FUNC_READ_INPUT_REGISTER;
break;
case MB_PARAM_COIL:
command = (mode == MB_PARAM_WRITE) ?
MB_FUNC_WRITE_MULTIPLE_COILS :
MB_FUNC_READ_COILS;
break;
case MB_PARAM_DISCRETE:
if (mode != MB_PARAM_WRITE) {
command = MB_FUNC_READ_DISCRETE_INPUTS;
} else {
ESP_LOGE(TAG, "%s: Incorrect mode (%u)",
__FUNCTION__, (unsigned)mode);
}
break;
default:
ESP_LOGE(TAG, "%s: Incorrect param type (%u)",
__FUNCTION__, (unsigned)param_type);
break;
}
return command;
}


// Helper to search parameter in the parameter description table and fills Modbus request fields accordingly
static esp_err_t mbc_tcp_master_set_request(void *ctx, uint16_t cid, mb_param_mode_t mode, mb_param_request_t *request,
mb_parameter_descriptor_t *reg_data)
Expand All @@ -368,7 +333,7 @@ static esp_err_t mbc_tcp_master_set_request(void *ctx, uint16_t cid, mb_param_mo
request->slave_addr = reg_ptr->mb_slave_addr;
request->reg_start = reg_ptr->mb_reg_start;
request->reg_size = reg_ptr->mb_size;
request->command = mbc_tcp_master_get_command(reg_ptr->mb_param_type, mode);
request->command = mbc_master_get_command(reg_ptr, mode);
MB_RETURN_ON_FALSE((request->command > 0), ESP_ERR_INVALID_ARG, TAG, "mb incorrect command or parameter type.");
if (reg_data) {
*reg_data = *reg_ptr; // Set the cid registered parameter data
Expand Down