49 #define AGILE_MODBUS_MSG_LENGTH_UNDEFINED -1
226 int remain_len = msg_length;
314 if ((msg_length <= 0) || (msg_length > ctx->
read_bufsz))
344 uint8_t *rsp,
int rsp_length)
347 int rsp_length_computed;
349 const int function = rsp[offset];
360 if (
function >= 0x80) {
361 if (rsp_length == (offset + 2 + (
int)ctx->
backend->
checksum_length) && req[offset] == (rsp[offset] - 0x80))
362 return (-128 - rsp[offset + 1]);
373 if (
function != req[offset])
383 req_nb_value = (req[offset + 3] << 8) + req[offset + 4];
384 req_nb_value = (req_nb_value / 8) + ((req_nb_value % 8) ? 1 : 0);
385 rsp_nb_value = rsp[offset + 1];
392 req_nb_value = (req[offset + 3] << 8) + req[offset + 4];
393 rsp_nb_value = (rsp[offset + 1] / 2);
399 req_nb_value = (req[offset + 3] << 8) + req[offset + 4];
400 rsp_nb_value = (rsp[offset + 3] << 8) | rsp[offset + 4];
405 req_nb_value = rsp_nb_value = rsp[offset + 1];
410 req_nb_value = rsp_nb_value = 1;
413 if (req_nb_value == rsp_nb_value)
466 if ((msg_length <= 0) || (msg_length > ctx->
read_bufsz))
484 offset_end = offset + rc;
487 for (i = offset; i < offset_end; i++) {
491 for (bit = 0x01; (bit & 0xff) && (pos < nb);) {
492 dest[pos++] = (temp & bit) ? 1 : 0;
521 if ((msg_length <= 0) || (msg_length > ctx->
read_bufsz))
539 offset_end = offset + rc;
542 for (i = offset; i < offset_end; i++) {
546 for (bit = 0x01; (bit & 0xff) && (pos < nb);) {
547 dest[pos++] = (temp & bit) ? 1 : 0;
576 if ((msg_length <= 0) || (msg_length > ctx->
read_bufsz))
591 for (i = 0; i < rc; i++) {
593 dest[i] = (ctx->
read_buf[offset + 2 + (i << 1)] << 8) | ctx->
read_buf[offset + 3 + (i << 1)];
620 if ((msg_length <= 0) || (msg_length > ctx->
read_bufsz))
635 for (i = 0; i < rc; i++) {
637 dest[i] = (ctx->
read_buf[offset + 2 + (i << 1)] << 8) | ctx->
read_buf[offset + 3 + (i << 1)];
661 if ((msg_length <= 0) || (msg_length > ctx->
read_bufsz))
691 if ((msg_length <= 0) || (msg_length > ctx->
read_bufsz))
719 byte_count = (nb / 8) + ((nb % 8) ? 1 : 0);
721 min_req_length += (1 + byte_count);
725 ctx->
send_buf[req_length++] = byte_count;
726 for (i = 0; i < byte_count; i++) {
732 while ((bit & 0xFF) && (bit_check++ < nb)) {
753 if ((msg_length <= 0) || (msg_length > ctx->
read_bufsz))
781 min_req_length += (1 + byte_count);
785 ctx->
send_buf[req_length++] = byte_count;
786 for (i = 0; i < nb; i++) {
787 ctx->
send_buf[req_length++] = src[i] >> 8;
788 ctx->
send_buf[req_length++] = src[i] & 0x00FF;
801 if ((msg_length <= 0) || (msg_length > ctx->
read_bufsz))
825 ctx->
send_buf[req_length++] = and_mask >> 8;
826 ctx->
send_buf[req_length++] = and_mask & 0x00ff;
827 ctx->
send_buf[req_length++] = or_mask >> 8;
828 ctx->
send_buf[req_length++] = or_mask & 0x00ff;
840 if ((msg_length <= 0) || (msg_length > ctx->
read_bufsz))
853 int write_addr,
int write_nb,
855 int read_addr,
int read_nb)
872 byte_count = write_nb * 2;
874 min_req_length += (5 + byte_count);
878 ctx->
send_buf[req_length++] = write_addr >> 8;
879 ctx->
send_buf[req_length++] = write_addr & 0x00ff;
880 ctx->
send_buf[req_length++] = write_nb >> 8;
881 ctx->
send_buf[req_length++] = write_nb & 0x00ff;
882 ctx->
send_buf[req_length++] = byte_count;
883 for (i = 0; i < write_nb; i++) {
884 ctx->
send_buf[req_length++] = src[i] >> 8;
885 ctx->
send_buf[req_length++] = src[i] & 0x00FF;
898 if ((msg_length <= 0) || (msg_length > ctx->
read_bufsz))
913 for (i = 0; i < rc; i++) {
915 dest[i] = (ctx->
read_buf[offset + 2 + (i << 1)] << 8) | ctx->
read_buf[offset + 3 + (i << 1)];
941 if ((msg_length <= 0) || (msg_length > ctx->
read_bufsz))
961 for (i = 0; i < rc && i < max_dest; i++) {
962 dest[i] = ctx->
read_buf[offset + i];
989 switch (req[offset]) {
993 int nb = (req[offset + 3] << 8) | req[offset + 4];
994 length = 2 + (nb / 8) + ((nb % 8) ? 1 : 0);
1001 length = 2 + 2 * (req[offset + 3] << 8 | req[offset + 4]);
1033 if (raw_req_length < 2) {
1048 sft.
slave = raw_req[0];
1055 if (raw_req_length > 2) {
1057 memcpy(ctx->
send_buf + req_length, raw_req + 2, raw_req_length - 2);
1058 req_length += raw_req_length - 2;
1078 if ((msg_length <= 0) || (msg_length > ctx->
read_bufsz))
1120 ctx->
send_buf[rsp_length++] = exception_code;
1141 int offset = index / 8;
1142 int shift = index % 8;
1145 buf[offset] |= (0x01 << shift);
1147 buf[offset] &= ~(0x01 << shift);
1158 int offset = index / 8;
1159 int shift = index % 8;
1161 uint8_t status = (buf[offset] & (0x01 << shift)) ? 1 : 0;
1174 buf[index * 2] = data >> 8;
1175 buf[index * 2 + 1] = data & 0xFF;
1186 uint16_t data = (buf[index * 2] << 8) + buf[index * 2 + 1];
1214 *frame_length = req_length;
1221 int exception_code = 0;
1229 slave = req[offset - 1];
1230 function = req[offset];
1231 address = (req[offset + 1] << 8) + req[offset + 2];
1250 int nb = (req[offset + 3] << 8) + req[offset + 4];
1256 int end_address = (int)
address +
nb - 1;
1257 if (end_address > 0xFFFF) {
1263 slave_info.
nb = (
nb / 8) + ((
nb % 8) ? 1 : 0);
1276 int nb = (req[offset + 3] << 8) + req[offset + 4];
1282 int end_address = (int)
address +
nb - 1;
1283 if (end_address > 0xFFFF) {
1289 slave_info.
nb =
nb << 1;
1309 reg_data = (req[offset + 3] << 8) + req[offset + 4];
1310 if (reg_data == 0xFF00 || reg_data == 0x0)
1311 reg_data = reg_data ? 1 : 0;
1317 slave_info.
buf = (uint8_t *)®_data;
1323 memcpy(rsp, req, req_length);
1335 reg_data = (req[offset + 3] << 8) + req[offset + 4];
1337 slave_info.
buf = (uint8_t *)®_data;
1343 memcpy(rsp, req, req_length);
1347 int nb = (req[offset + 3] << 8) + req[offset + 4];
1348 int nb_bits = req[offset + 5];
1354 int end_address = (int)
address +
nb - 1;
1355 if (end_address > 0xFFFF) {
1362 slave_info.
buf = &req[offset + 6];
1373 int nb = (req[offset + 3] << 8) + req[offset + 4];
1374 int nb_bytes = req[offset + 5];
1380 int end_address = (int)
address +
nb - 1;
1381 if (end_address > 0xFFFF) {
1388 slave_info.
buf = &req[offset + 6];
1418 rsp[byte_count_pos] =
rsp_length - byte_count_pos - 1;
1434 slave_info.
buf = &req[offset + 3];
1440 memcpy(rsp, req, req_length);
1444 int nb = (req[offset + 3] << 8) + req[offset + 4];
1445 uint16_t address_write = (req[offset + 5] << 8) + req[offset + 6];
1446 int nb_write = (req[offset + 7] << 8) + req[offset + 8];
1447 int nb_write_bytes = req[offset + 9];
1450 nb_write_bytes != nb_write * 2) {
1455 int end_address = (int)
address +
nb - 1;
1456 int end_address_write = (int)address_write + nb_write - 1;
1457 if (end_address > 0xFFFF || end_address_write > 0xFFFF) {
1464 slave_info.
buf = &req[offset + 3];
1474 if (slave_cb == NULL)
1479 slave_info.
buf = &req[offset + 1];
1480 slave_info.
nb = req_length - offset - 1;
1489 int ret = slave_cb(ctx, &slave_info, slave_data);
Agile Modbus software package common header file.
void agile_modbus_set_compute_data_length_after_meta_cb(agile_modbus_t *ctx, int(*cb)(agile_modbus_t *ctx, uint8_t *msg, int msg_length, agile_modbus_msg_type_t msg_type))
sets the data length callback function to be received after calculating the data element of the modbu...
void agile_modbus_common_init(agile_modbus_t *ctx, uint8_t *send_buf, int send_bufsz, uint8_t *read_buf, int read_bufsz)
initialize modbus handle
int agile_modbus_receive_judge(agile_modbus_t *ctx, int msg_length, agile_modbus_msg_type_t msg_type)
Verify the correctness of received data.
int agile_modbus_set_slave(agile_modbus_t *ctx, int slave)
set address
void agile_modbus_set_compute_meta_length_after_function_cb(agile_modbus_t *ctx, uint8_t(*cb)(agile_modbus_t *ctx, int function, agile_modbus_msg_type_t msg_type))
sets the data element length callback function to be received after calculating the function code of ...
agile_modbus_msg_type_t
Modbus received message type.
@ AGILE_MODBUS_EXCEPTION_UNKNOW
@ AGILE_MODBUS_EXCEPTION_ILLEGAL_FUNCTION
@ AGILE_MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE
@ AGILE_MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS
@ AGILE_MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE
@ AGILE_MODBUS_BACKEND_TYPE_RTU
RTU.
@ AGILE_MODBUS_MSG_CONFIRMATION
Server-side request message.
@ AGILE_MODBUS_MSG_INDICATION
Host-side request message.
#define AGILE_MODBUS_MSG_LENGTH_UNDEFINED
The corresponding function code data length is undefined.
static int agile_modbus_receive_msg_judge(agile_modbus_t *ctx, uint8_t *msg, int msg_length, agile_modbus_msg_type_t msg_type)
Check the correctness of received data.
static uint8_t agile_modbus_compute_meta_length_after_function(agile_modbus_t *ctx, int function, agile_modbus_msg_type_t msg_type)
The length of the data element to be received after calculating the function code.
static int agile_modbus_compute_data_length_after_meta(agile_modbus_t *ctx, uint8_t *msg, int msg_length, agile_modbus_msg_type_t msg_type)
The length of data to be received after calculating the data element.
int agile_modbus_serialize_write_register(agile_modbus_t *ctx, int addr, const uint16_t value)
int agile_modbus_serialize_write_and_read_registers(agile_modbus_t *ctx, int write_addr, int write_nb, const uint16_t *src, int read_addr, int read_nb)
int agile_modbus_deserialize_write_and_read_registers(agile_modbus_t *ctx, int msg_length, uint16_t *dest)
int agile_modbus_deserialize_mask_write_register(agile_modbus_t *ctx, int msg_length)
int agile_modbus_deserialize_write_registers(agile_modbus_t *ctx, int msg_length)
int agile_modbus_deserialize_write_bit(agile_modbus_t *ctx, int msg_length)
int agile_modbus_serialize_read_registers(agile_modbus_t *ctx, int addr, int nb)
int agile_modbus_deserialize_read_input_bits(agile_modbus_t *ctx, int msg_length, uint8_t *dest)
int agile_modbus_serialize_write_bits(agile_modbus_t *ctx, int addr, int nb, const uint8_t *src)
int agile_modbus_serialize_read_bits(agile_modbus_t *ctx, int addr, int nb)
int agile_modbus_serialize_write_registers(agile_modbus_t *ctx, int addr, int nb, const uint16_t *src)
int agile_modbus_deserialize_report_slave_id(agile_modbus_t *ctx, int msg_length, int max_dest, uint8_t *dest)
int agile_modbus_deserialize_read_input_registers(agile_modbus_t *ctx, int msg_length, uint16_t *dest)
int agile_modbus_deserialize_read_bits(agile_modbus_t *ctx, int msg_length, uint8_t *dest)
int agile_modbus_serialize_write_bit(agile_modbus_t *ctx, int addr, int status)
int agile_modbus_deserialize_write_register(agile_modbus_t *ctx, int msg_length)
int agile_modbus_serialize_mask_write_register(agile_modbus_t *ctx, int addr, uint16_t and_mask, uint16_t or_mask)
int agile_modbus_deserialize_write_bits(agile_modbus_t *ctx, int msg_length)
int agile_modbus_serialize_read_input_registers(agile_modbus_t *ctx, int addr, int nb)
int agile_modbus_deserialize_read_registers(agile_modbus_t *ctx, int msg_length, uint16_t *dest)
int agile_modbus_serialize_report_slave_id(agile_modbus_t *ctx)
int agile_modbus_serialize_read_input_bits(agile_modbus_t *ctx, int addr, int nb)
static int agile_modbus_check_confirmation(agile_modbus_t *ctx, uint8_t *req, uint8_t *rsp, int rsp_length)
Check and confirm the slave response data.
int agile_modbus_compute_response_length_from_request(agile_modbus_t *ctx, uint8_t *req)
Calculate the expected response data length.
int agile_modbus_deserialize_raw_response(agile_modbus_t *ctx, int msg_length)
parses the original response data
int agile_modbus_serialize_raw_request(agile_modbus_t *ctx, const uint8_t *raw_req, int raw_req_length)
Pack the original data into a request message.
#define AGILE_MODBUS_BROADCAST_ADDRESS
Modbus broadcast address.
#define AGILE_MODBUS_MAX_READ_BITS
#define AGILE_MODBUS_VERSION_STRING
Agile Modbus version number.
#define AGILE_MODBUS_MAX_WRITE_REGISTERS
#define AGILE_MODBUS_MAX_WRITE_BITS
#define AGILE_MODBUS_MAX_WR_WRITE_REGISTERS
#define AGILE_MODBUS_MAX_READ_REGISTERS
#define AGILE_MODBUS_MAX_WR_READ_REGISTERS
#define AGILE_MODBUS_FC_MASK_WRITE_REGISTER
#define AGILE_MODBUS_FC_READ_COILS
#define AGILE_MODBUS_FC_WRITE_SINGLE_REGISTER
#define AGILE_MODBUS_FC_WRITE_MULTIPLE_COILS
#define AGILE_MODBUS_FC_WRITE_SINGLE_COIL
#define AGILE_MODBUS_FC_READ_HOLDING_REGISTERS
#define AGILE_MODBUS_FC_WRITE_AND_READ_REGISTERS
#define AGILE_MODBUS_FC_READ_INPUT_REGISTERS
#define AGILE_MODBUS_FC_REPORT_SLAVE_ID
#define AGILE_MODBUS_FC_WRITE_MULTIPLE_REGISTERS
#define AGILE_MODBUS_FC_READ_EXCEPTION_STATUS
#define AGILE_MODBUS_FC_READ_DISCRETE_INPUTS
int(* agile_modbus_slave_callback_t)(agile_modbus_t *ctx, struct agile_modbus_slave_info *slave_info, const void *data)
Slave callback function.
int agile_modbus_slave_handle(agile_modbus_t *ctx, int msg_length, uint8_t slave_strict, agile_modbus_slave_callback_t slave_cb, const void *slave_data, int *frame_length)
slave data processing
uint8_t agile_modbus_slave_io_get(uint8_t *buf, int index)
Read slave IO status.
void agile_modbus_slave_io_set(uint8_t *buf, int index, int status)
slave IO settings
uint16_t agile_modbus_slave_register_get(uint8_t *buf, int index)
Read slave register data.
void agile_modbus_slave_register_set(uint8_t *buf, int index, uint16_t data)
slave register settings
static int agile_modbus_serialize_response_exception(agile_modbus_t *ctx, agile_modbus_sft_t *sft, int exception_code)
packaged exception response data
int(* check_integrity)(agile_modbus_t *ctx, uint8_t *msg, const int msg_length)
Check the receive data integrity interface.
int(* set_slave)(agile_modbus_t *ctx, int slave)
Set address interface.
int(* pre_check_confirmation)(agile_modbus_t *ctx, const uint8_t *req, const uint8_t *rsp, int rsp_length)
Pre-check confirmation interface.
int(* build_response_basis)(agile_modbus_sft_t *sft, uint8_t *rsp)
Build a basic response message interface.
uint32_t header_length
Header length, excluding function code.
uint32_t backend_type
Backend type.
int(* send_msg_pre)(uint8_t *req, int req_length)
Pre-send data interface.
int(* prepare_response_tid)(const uint8_t *req, int *req_length)
Prepare response interface.
int(* build_request_basis)(agile_modbus_t *ctx, int function, int addr, int nb, uint8_t *req)
Build a basic request message interface.
uint32_t checksum_length
Check data length.
contains the modbus header parameter structure
int t_id
Transaction identifier.
int function
function code
Agile Modbus slave information structure.
uint8_t * buf
Data fields required for different function codes.
int send_index
Current index of sending buffer.
agile_modbus_sft_t * sft
sft structure pointer
int address
Register address.
int * rsp_length
Response data length pointer.
int(* compute_data_length_after_meta)(agile_modbus_t *ctx, uint8_t *msg, int msg_length, agile_modbus_msg_type_t msg_type)
Customized calculation data length interface.
uint8_t(* compute_meta_length_after_function)(agile_modbus_t *ctx, int function, agile_modbus_msg_type_t msg_type)
Customized calculation data element length interface.
int send_bufsz
Send buffer size.
uint8_t * send_buf
Send buffer.
uint8_t * read_buf
Receive buffer.
const agile_modbus_backend_t * backend
Backend interface.
int read_bufsz
Receive buffer size.