当前位置: 首页 > news >正文

做采集网站难不黑龙江建设工程招标网

做采集网站难不,黑龙江建设工程招标网,免费扑克网站,松桃和兴建设公司网站前言 一直以来上位软件比如C等和西门子等其他品牌PLC之间的数据交换都是大家比较头疼的问题#xff0c;尤其是C上位软件程序员。传统的方法一般有OPC、Socket 等#xff0c;直到LibModbus 开源库出现后这种途径对程序袁来说又有了新的选择。 Modbus简介 Modbus特点 1 #… 前言 一直以来上位软件比如C等和西门子等其他品牌PLC之间的数据交换都是大家比较头疼的问题尤其是C上位软件程序员。传统的方法一般有OPC、Socket 等直到LibModbus 开源库出现后这种途径对程序袁来说又有了新的选择。 Modbus简介 Modbus特点 1 使用简单利用MUDBUS库文件简单的几条指令就能实现与智能仪表变频器打印机等设备进行通讯且无需加其他硬件上的成本MODBUS总线广泛应用于仪器仪表、智能高低压电器、变送器、可编程控制器、人机界面、变频器、现场智能设备等诸多领域。MODBUS与其他的现场总线和工业网络相比有以下几个显著特点。 2标准、开放:用户可以免费放心的使用 MODBUS协议不用缴纳许可费用不会涉及侵犯知识产权。目前支持MODBUS的厂一家超过400家支持MODBUS的产品超过600种。在中国MODBUS已经成为国家标准GB/T19582-2008。据不完全统 计截止到2007年MODBUS的节点安装数量已经超过了1000万个。 3应用广泛凡MODBUS协议设备具有RS232/485接口的都可以使用本产品实现与现场总线PROFIBUS的互连。如具有MODBUS协议接口的变频器、智能高低压电器、电机启动保护装置、电量测量装置、智能现场测量设备、各种变送器及仪表等。 4MODBUS可以支持较多类型的电气接口MODBUS 总线协议采用主站查询从站的方式物理接口可以是RS232、RS485、RS422、RJ45还可以在各种介质上传送如双绞线、光纤、无线射频等。 5MODBUS的帧格式较为简单、紧凑格式规范易于传输通俗易懂。用户使用容易厂商开发简单。用户不必了解PROFIBUS和MODBUS技术细节只需参考说明手册及提供的应用实例按要求完成配置不需要复杂的编程即可在短时间内实现设备间的连接通信。 6透明通信用户可以依照PROFIBUS通信数据区和MODBUS通信数据区的映射关系实现PROFIBUS到MODBUS之间的数据透明通信。 LibModbus库下载 https://libmodbus.org/https://libmodbus.org/ https://gitcode.com/stephane/libmodbus/overview?utm_sourcecsdn_github_acceleratorisLogin1https://gitcode.com/stephane/libmodbus/overview?utm_sourcecsdn_github_acceleratorisLogin1https://github.com/stephane/libmodbushttps://github.com/stephane/libmodbushttps://download.csdn.net/download/lzc881012/88695801https://download.csdn.net/download/lzc881012/88695801 LibModbus库Windows版本的编译 1、进入到libmodbus\src\win32文件夹下。 2、双击configure.js文件进行编译,成功后会弹出编译完成窗口,点击关闭。 3、然后在双击modbus-9.sln通过VS打开项目,打开项目完成后编译即可。 4、编译完成后libmodbus\src\win32文件夹下就会出现modbus.dll和modbus.lib两个文件。 将上述步骤中生成的modbus.lib文件和libmodbus\src中所有的.h文件通过VS包含到自己的项目中即可。 在程序中包含libModbus/modbus.h一个头文件即可。 将上述步骤在生成的modbus.dll放到你的项目生成目录下,例如Debug/Release目录下。 LibModbus库modbus.h头文件 /** Copyright © 2001-2013 Stéphane Raimbault stephane.raimbaultgmail.com** SPDX-License-Identifier: LGPL-2.1*/#ifndef MODBUS_H #define MODBUS_H/* Add this for macros that defined unix flavor */ #if (defined(__unix__) || defined(unix)) !defined(USG) #include sys/param.h #endif#ifndef _MSC_VER #include stdint.h #else #include stdint.h #endif#include modbus-version.h#if defined(_MSC_VER) # if defined(DLLBUILD) /* define DLLBUILD when building the DLL */ # define MODBUS_API __declspec(dllexport) # else # define MODBUS_API __declspec(dllimport) # endif #else # define MODBUS_API #endif#ifdef __cplusplus # define MODBUS_BEGIN_DECLS extern C { # define MODBUS_END_DECLS } #else # define MODBUS_BEGIN_DECLS # define MODBUS_END_DECLS #endifMODBUS_BEGIN_DECLS#ifndef FALSE #define FALSE 0 #endif#ifndef TRUE #define TRUE 1 #endif#ifndef OFF #define OFF 0 #endif#ifndef ON #define ON 1 #endif/* Modbus function codes */ #define MODBUS_FC_READ_COILS 0x01 #define MODBUS_FC_READ_DISCRETE_INPUTS 0x02 #define MODBUS_FC_READ_HOLDING_REGISTERS 0x03 #define MODBUS_FC_READ_INPUT_REGISTERS 0x04 #define MODBUS_FC_WRITE_SINGLE_COIL 0x05 #define MODBUS_FC_WRITE_SINGLE_REGISTER 0x06 #define MODBUS_FC_READ_EXCEPTION_STATUS 0x07 #define MODBUS_FC_WRITE_MULTIPLE_COILS 0x0F #define MODBUS_FC_WRITE_MULTIPLE_REGISTERS 0x10 #define MODBUS_FC_REPORT_SLAVE_ID 0x11 #define MODBUS_FC_MASK_WRITE_REGISTER 0x16 #define MODBUS_FC_WRITE_AND_READ_REGISTERS 0x17#define MODBUS_BROADCAST_ADDRESS 0/* Modbus_Application_Protocol_V1_1b.pdf (chapter 6 section 1 page 12)* Quantity of Coils to read (2 bytes): 1 to 2000 (0x7D0)* (chapter 6 section 11 page 29)* Quantity of Coils to write (2 bytes): 1 to 1968 (0x7B0)*/ #define MODBUS_MAX_READ_BITS 2000 #define MODBUS_MAX_WRITE_BITS 1968/* Modbus_Application_Protocol_V1_1b.pdf (chapter 6 section 3 page 15)* Quantity of Registers to read (2 bytes): 1 to 125 (0x7D)* (chapter 6 section 12 page 31)* Quantity of Registers to write (2 bytes) 1 to 123 (0x7B)* (chapter 6 section 17 page 38)* Quantity of Registers to write in R/W registers (2 bytes) 1 to 121 (0x79)*/ #define MODBUS_MAX_READ_REGISTERS 125 #define MODBUS_MAX_WRITE_REGISTERS 123 #define MODBUS_MAX_WR_WRITE_REGISTERS 121 #define MODBUS_MAX_WR_READ_REGISTERS 125/* The size of the MODBUS PDU is limited by the size constraint inherited from* the first MODBUS implementation on Serial Line network (max. RS485 ADU 256* bytes). Therefore, MODBUS PDU for serial line communication 256 - Server* address (1 byte) - CRC (2 bytes) 253 bytes.*/ #define MODBUS_MAX_PDU_LENGTH 253/* Consequently:* - RTU MODBUS ADU 253 bytes Server address (1 byte) CRC (2 bytes) 256* bytes.* - TCP MODBUS ADU 253 bytes MBAP (7 bytes) 260 bytes.* so the maximum of both backend in 260 bytes. This size can used to allocate* an array of bytes to store responses and it will be compatible with the two* backends.*/ #define MODBUS_MAX_ADU_LENGTH 260/* Random number to avoid errno conflicts */ #define MODBUS_ENOBASE 112345678/* Protocol exceptions */ enum {MODBUS_EXCEPTION_ILLEGAL_FUNCTION 0x01,MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS,MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE,MODBUS_EXCEPTION_SLAVE_OR_SERVER_FAILURE,MODBUS_EXCEPTION_ACKNOWLEDGE,MODBUS_EXCEPTION_SLAVE_OR_SERVER_BUSY,MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE,MODBUS_EXCEPTION_MEMORY_PARITY,MODBUS_EXCEPTION_NOT_DEFINED,MODBUS_EXCEPTION_GATEWAY_PATH,MODBUS_EXCEPTION_GATEWAY_TARGET,MODBUS_EXCEPTION_MAX };#define EMBXILFUN (MODBUS_ENOBASE MODBUS_EXCEPTION_ILLEGAL_FUNCTION) #define EMBXILADD (MODBUS_ENOBASE MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS) #define EMBXILVAL (MODBUS_ENOBASE MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE) #define EMBXSFAIL (MODBUS_ENOBASE MODBUS_EXCEPTION_SLAVE_OR_SERVER_FAILURE) #define EMBXACK (MODBUS_ENOBASE MODBUS_EXCEPTION_ACKNOWLEDGE) #define EMBXSBUSY (MODBUS_ENOBASE MODBUS_EXCEPTION_SLAVE_OR_SERVER_BUSY) #define EMBXNACK (MODBUS_ENOBASE MODBUS_EXCEPTION_NEGATIVE_ACKNOWLEDGE) #define EMBXMEMPAR (MODBUS_ENOBASE MODBUS_EXCEPTION_MEMORY_PARITY) #define EMBXGPATH (MODBUS_ENOBASE MODBUS_EXCEPTION_GATEWAY_PATH) #define EMBXGTAR (MODBUS_ENOBASE MODBUS_EXCEPTION_GATEWAY_TARGET)/* Native libmodbus error codes */ #define EMBBADCRC (EMBXGTAR 1) #define EMBBADDATA (EMBXGTAR 2) #define EMBBADEXC (EMBXGTAR 3) #define EMBUNKEXC (EMBXGTAR 4) #define EMBMDATA (EMBXGTAR 5) #define EMBBADSLAVE (EMBXGTAR 6)extern const unsigned int libmodbus_version_major; extern const unsigned int libmodbus_version_minor; extern const unsigned int libmodbus_version_micro;typedef struct _modbus modbus_t;typedef struct _modbus_mapping_t {int nb_bits;int start_bits;int nb_input_bits;int start_input_bits;int nb_input_registers;int start_input_registers;int nb_registers;int start_registers;uint8_t *tab_bits;uint8_t *tab_input_bits;uint16_t *tab_input_registers;uint16_t *tab_registers; } modbus_mapping_t;typedef enum {MODBUS_ERROR_RECOVERY_NONE 0,MODBUS_ERROR_RECOVERY_LINK (11),MODBUS_ERROR_RECOVERY_PROTOCOL (12) } modbus_error_recovery_mode;MODBUS_API int modbus_set_slave(modbus_t* ctx, int slave); MODBUS_API int modbus_get_slave(modbus_t* ctx); MODBUS_API int modbus_set_error_recovery(modbus_t *ctx, modbus_error_recovery_mode error_recovery); MODBUS_API int modbus_set_socket(modbus_t *ctx, int s); MODBUS_API int modbus_get_socket(modbus_t *ctx);MODBUS_API int modbus_get_response_timeout(modbus_t *ctx, uint32_t *to_sec, uint32_t *to_usec); MODBUS_API int modbus_set_response_timeout(modbus_t *ctx, uint32_t to_sec, uint32_t to_usec);MODBUS_API int modbus_get_byte_timeout(modbus_t *ctx, uint32_t *to_sec, uint32_t *to_usec); MODBUS_API int modbus_set_byte_timeout(modbus_t *ctx, uint32_t to_sec, uint32_t to_usec);MODBUS_API int modbus_get_indication_timeout(modbus_t *ctx, uint32_t *to_sec, uint32_t *to_usec); MODBUS_API int modbus_set_indication_timeout(modbus_t *ctx, uint32_t to_sec, uint32_t to_usec);MODBUS_API int modbus_get_header_length(modbus_t *ctx);MODBUS_API int modbus_connect(modbus_t *ctx); MODBUS_API void modbus_close(modbus_t *ctx);MODBUS_API void modbus_free(modbus_t *ctx);MODBUS_API int modbus_flush(modbus_t *ctx); MODBUS_API int modbus_set_debug(modbus_t *ctx, int flag);MODBUS_API const char *modbus_strerror(int errnum);MODBUS_API int modbus_read_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest); MODBUS_API int modbus_read_input_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest); MODBUS_API int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest); MODBUS_API int modbus_read_input_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest); MODBUS_API int modbus_write_bit(modbus_t *ctx, int coil_addr, int status); MODBUS_API int modbus_write_register(modbus_t *ctx, int reg_addr, const uint16_t value); MODBUS_API int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *data); MODBUS_API int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *data); MODBUS_API int modbus_mask_write_register(modbus_t *ctx, int addr, uint16_t and_mask, uint16_t or_mask); MODBUS_API int modbus_write_and_read_registers(modbus_t *ctx, int write_addr, int write_nb,const uint16_t *src, int read_addr, int read_nb,uint16_t *dest); MODBUS_API int modbus_report_slave_id(modbus_t *ctx, int max_dest, uint8_t *dest);MODBUS_API modbus_mapping_t* modbus_mapping_new_start_address(unsigned int start_bits, unsigned int nb_bits,unsigned int start_input_bits, unsigned int nb_input_bits,unsigned int start_registers, unsigned int nb_registers,unsigned int start_input_registers, unsigned int nb_input_registers);MODBUS_API modbus_mapping_t* modbus_mapping_new(int nb_bits, int nb_input_bits,int nb_registers, int nb_input_registers); MODBUS_API void modbus_mapping_free(modbus_mapping_t *mb_mapping);MODBUS_API int modbus_send_raw_request(modbus_t *ctx, const uint8_t *raw_req, int raw_req_length);MODBUS_API int modbus_receive(modbus_t *ctx, uint8_t *req);MODBUS_API int modbus_receive_confirmation(modbus_t *ctx, uint8_t *rsp);MODBUS_API int modbus_reply(modbus_t *ctx, const uint8_t *req,int req_length, modbus_mapping_t *mb_mapping); MODBUS_API int modbus_reply_exception(modbus_t *ctx, const uint8_t *req,unsigned int exception_code);/*** UTILS FUNCTIONS**/#define MODBUS_GET_HIGH_BYTE(data) (((data) 8) 0xFF) #define MODBUS_GET_LOW_BYTE(data) ((data) 0xFF) #define MODBUS_GET_INT64_FROM_INT16(tab_int16, index) \(((int64_t)tab_int16[(index) ] 48) \((int64_t)tab_int16[(index) 1] 32) \((int64_t)tab_int16[(index) 2] 16) \(int64_t)tab_int16[(index) 3]) #define MODBUS_GET_INT32_FROM_INT16(tab_int16, index) ((tab_int16[(index)] 16) tab_int16[(index) 1]) #define MODBUS_GET_INT16_FROM_INT8(tab_int8, index) ((tab_int8[(index)] 8) tab_int8[(index) 1]) #define MODBUS_SET_INT16_TO_INT8(tab_int8, index, value) \do { \tab_int8[(index)] (value) 8; \tab_int8[(index) 1] (value) 0xFF; \} while (0) #define MODBUS_SET_INT32_TO_INT16(tab_int16, index, value) \do { \tab_int16[(index) ] (value) 16; \tab_int16[(index) 1] (value); \} while (0) #define MODBUS_SET_INT64_TO_INT16(tab_int16, index, value) \do { \tab_int16[(index) ] (value) 48; \tab_int16[(index) 1] (value) 32; \tab_int16[(index) 2] (value) 16; \tab_int16[(index) 3] (value); \} while (0)MODBUS_API void modbus_set_bits_from_byte(uint8_t *dest, int idx, const uint8_t value); MODBUS_API void modbus_set_bits_from_bytes(uint8_t *dest, int idx, unsigned int nb_bits,const uint8_t *tab_byte); MODBUS_API uint8_t modbus_get_byte_from_bits(const uint8_t *src, int idx, unsigned int nb_bits); MODBUS_API float modbus_get_float(const uint16_t *src); MODBUS_API float modbus_get_float_abcd(const uint16_t *src); MODBUS_API float modbus_get_float_dcba(const uint16_t *src); MODBUS_API float modbus_get_float_badc(const uint16_t *src); MODBUS_API float modbus_get_float_cdab(const uint16_t *src);MODBUS_API void modbus_set_float(float f, uint16_t *dest); MODBUS_API void modbus_set_float_abcd(float f, uint16_t *dest); MODBUS_API void modbus_set_float_dcba(float f, uint16_t *dest); MODBUS_API void modbus_set_float_badc(float f, uint16_t *dest); MODBUS_API void modbus_set_float_cdab(float f, uint16_t *dest);#include modbus-tcp.h #include modbus-rtu.hMODBUS_END_DECLS#endif /* MODBUS_H */LibModbus库Modbus.h头文件 /** Copyright © 2001-2011 Stéphane Raimbault stephane.raimbaultgmail.com** SPDX-License-Identifier: LGPL-2.1** This library implements the Modbus protocol.* http://libmodbus.org/*/#include stdio.h #include string.h #include stdlib.h #include stdarg.h #include errno.h #include limits.h #include time.h #ifndef _MSC_VER #include unistd.h #endif#include config.h#include modbus.h #include modbus-private.h/* Internal use */ #define MSG_LENGTH_UNDEFINED -1/* Exported version */ const unsigned int libmodbus_version_major LIBMODBUS_VERSION_MAJOR; const unsigned int libmodbus_version_minor LIBMODBUS_VERSION_MINOR; const unsigned int libmodbus_version_micro LIBMODBUS_VERSION_MICRO;/* Max between RTU and TCP max adu length (so TCP) */ #define MAX_MESSAGE_LENGTH 260/* 3 steps are used to parse the query */ typedef enum {_STEP_FUNCTION,_STEP_META,_STEP_DATA } _step_t;const char *modbus_strerror(int errnum) {switch (errnum) {case EMBXILFUN:return Illegal function;case EMBXILADD:return Illegal data address;case EMBXILVAL:return Illegal data value;case EMBXSFAIL:return Slave device or server failure;case EMBXACK:return Acknowledge;case EMBXSBUSY:return Slave device or server is busy;case EMBXNACK:return Negative acknowledge;case EMBXMEMPAR:return Memory parity error;case EMBXGPATH:return Gateway path unavailable;case EMBXGTAR:return Target device failed to respond;case EMBBADCRC:return Invalid CRC;case EMBBADDATA:return Invalid data;case EMBBADEXC:return Invalid exception code;case EMBMDATA:return Too many data;case EMBBADSLAVE:return Response not from requested slave;default:return strerror(errnum);} }void _error_print(modbus_t *ctx, const char *context) {if (ctx-debug) {fprintf(stderr, ERROR %s, modbus_strerror(errno));if (context ! NULL) {fprintf(stderr, : %s\n, context);} else {fprintf(stderr, \n);}} }static void _sleep_response_timeout(modbus_t *ctx) {/* Response timeout is always positive */ #ifdef _WIN32/* usleep doesnt exist on Windows */Sleep((ctx-response_timeout.tv_sec * 1000) (ctx-response_timeout.tv_usec / 1000)); #else/* usleep source code */struct timespec request, remaining;request.tv_sec ctx-response_timeout.tv_sec;request.tv_nsec ((long int)ctx-response_timeout.tv_usec) * 1000;while (nanosleep(request, remaining) -1 errno EINTR) {request remaining;} #endif }int modbus_flush(modbus_t *ctx) {int rc;if (ctx NULL) {errno EINVAL;return -1;}rc ctx-backend-flush(ctx);if (rc ! -1 ctx-debug) {/* Not all backends are able to return the number of bytes flushed */printf(Bytes flushed (%d)\n, rc);}return rc; }/* Computes the length of the expected response */ static unsigned int compute_response_length_from_request(modbus_t *ctx, uint8_t *req) {int length;const int offset ctx-backend-header_length;switch (req[offset]) {case MODBUS_FC_READ_COILS:case MODBUS_FC_READ_DISCRETE_INPUTS: {/* Header nb values (code from write_bits) */int nb (req[offset 3] 8) | req[offset 4];length 2 (nb / 8) ((nb % 8) ? 1 : 0);}break;case MODBUS_FC_WRITE_AND_READ_REGISTERS:case MODBUS_FC_READ_HOLDING_REGISTERS:case MODBUS_FC_READ_INPUT_REGISTERS:/* Header 2 * nb values */length 2 2 * (req[offset 3] 8 | req[offset 4]);break;case MODBUS_FC_READ_EXCEPTION_STATUS:length 3;break;case MODBUS_FC_REPORT_SLAVE_ID:/* The response is device specific (the header provides thelength) */return MSG_LENGTH_UNDEFINED;case MODBUS_FC_MASK_WRITE_REGISTER:length 7;break;default:length 5;}return offset length ctx-backend-checksum_length; }/* Sends a request/response */ static int send_msg(modbus_t *ctx, uint8_t *msg, int msg_length) {int rc;int i;msg_length ctx-backend-send_msg_pre(msg, msg_length);if (ctx-debug) {for (i 0; i msg_length; i)printf([%.2X], msg[i]);printf(\n);}/* In recovery mode, the write command will be issued until to besuccessful! Disabled by default. */do {rc ctx-backend-send(ctx, msg, msg_length);if (rc -1) {_error_print(ctx, NULL);if (ctx-error_recovery MODBUS_ERROR_RECOVERY_LINK) {int saved_errno errno;if ((errno EBADF || errno ECONNRESET || errno EPIPE)) {modbus_close(ctx);_sleep_response_timeout(ctx);modbus_connect(ctx);} else {_sleep_response_timeout(ctx);modbus_flush(ctx);}errno saved_errno;}}} while ((ctx-error_recovery MODBUS_ERROR_RECOVERY_LINK) rc -1);if (rc 0 rc ! msg_length) {errno EMBBADDATA;return -1;}return rc; }int modbus_send_raw_request(modbus_t *ctx, const uint8_t *raw_req, int raw_req_length) {sft_t sft;uint8_t req[MAX_MESSAGE_LENGTH];int req_length;if (ctx NULL) {errno EINVAL;return -1;}if (raw_req_length 2 || raw_req_length (MODBUS_MAX_PDU_LENGTH 1)) {/* The raw request must contain function and slave at least andmust not be longer than the maximum pdu length plus the slaveaddress. */errno EINVAL;return -1;}sft.slave raw_req[0];sft.function raw_req[1];/* The t_id is left to zero */sft.t_id 0;/* This response function only set the header so its convenient here */req_length ctx-backend-build_response_basis(sft, req);if (raw_req_length 2) {/* Copy data after function code */memcpy(req req_length, raw_req 2, raw_req_length - 2);req_length raw_req_length - 2;}return send_msg(ctx, req, req_length); }/** ---------- Request Indication ----------* | Client | ----------------------| Server |* ---------- Confirmation Response ----------*//* Computes the length to read after the function received */ static uint8_t compute_meta_length_after_function(int function,msg_type_t msg_type) {int length;if (msg_type MSG_INDICATION) {if (function MODBUS_FC_WRITE_SINGLE_REGISTER) {length 4;} else if (function MODBUS_FC_WRITE_MULTIPLE_COILS ||function MODBUS_FC_WRITE_MULTIPLE_REGISTERS) {length 5;} else if (function MODBUS_FC_MASK_WRITE_REGISTER) {length 6;} else if (function MODBUS_FC_WRITE_AND_READ_REGISTERS) {length 9;} else {/* MODBUS_FC_READ_EXCEPTION_STATUS, MODBUS_FC_REPORT_SLAVE_ID */length 0;}} else {/* MSG_CONFIRMATION */switch (function) {case MODBUS_FC_WRITE_SINGLE_COIL:case MODBUS_FC_WRITE_SINGLE_REGISTER:case MODBUS_FC_WRITE_MULTIPLE_COILS:case MODBUS_FC_WRITE_MULTIPLE_REGISTERS:length 4;break;case MODBUS_FC_MASK_WRITE_REGISTER:length 6;break;default:length 1;}}return length; }/* Computes the length to read after the meta information (address, count, etc) */ static int compute_data_length_after_meta(modbus_t *ctx, uint8_t *msg,msg_type_t msg_type) {int function msg[ctx-backend-header_length];int length;if (msg_type MSG_INDICATION) {switch (function) {case MODBUS_FC_WRITE_MULTIPLE_COILS:case MODBUS_FC_WRITE_MULTIPLE_REGISTERS:length msg[ctx-backend-header_length 5];break;case MODBUS_FC_WRITE_AND_READ_REGISTERS:length msg[ctx-backend-header_length 9];break;default:length 0;}} else {/* MSG_CONFIRMATION */if (function MODBUS_FC_READ_INPUT_REGISTERS ||function MODBUS_FC_REPORT_SLAVE_ID ||function MODBUS_FC_WRITE_AND_READ_REGISTERS) {length msg[ctx-backend-header_length 1];} else {length 0;}}length ctx-backend-checksum_length;return length; }/* Waits a response from a modbus server or a request from a modbus client.This function blocks if there is no replies (3 timeouts).The function shall return the number of received characters and the receivedmessage in an array of uint8_t if successful. Otherwise it shall return -1and errno is set to one of the values defined below:- ECONNRESET- EMBBADDATA- EMBUNKEXC- ETIMEDOUT- read() or recv() error codes */int _modbus_receive_msg(modbus_t *ctx, uint8_t *msg, msg_type_t msg_type) {int rc;fd_set rset;struct timeval tv;struct timeval *p_tv;int length_to_read;int msg_length 0;_step_t step;if (ctx-debug) {if (msg_type MSG_INDICATION) {printf(Waiting for an indication...\n);} else {printf(Waiting for a confirmation...\n);}}/* Add a file descriptor to the set */FD_ZERO(rset);FD_SET(ctx-s, rset);/* We need to analyse the message step by step. At the first step, we want* to reach the function code because all packets contain this* information. */step _STEP_FUNCTION;length_to_read ctx-backend-header_length 1;if (msg_type MSG_INDICATION) {/* Wait for a message, we dont know when the message will be* received */if (ctx-indication_timeout.tv_sec 0 ctx-indication_timeout.tv_usec 0) {/* By default, the indication timeout isnt set */p_tv NULL;} else {/* Wait for an indication (name of a received request by a server, see schema) */tv.tv_sec ctx-indication_timeout.tv_sec;tv.tv_usec ctx-indication_timeout.tv_usec;p_tv tv;}} else {tv.tv_sec ctx-response_timeout.tv_sec;tv.tv_usec ctx-response_timeout.tv_usec;p_tv tv;}while (length_to_read ! 0) {rc ctx-backend-select(ctx, rset, p_tv, length_to_read);if (rc -1) {_error_print(ctx, select);if (ctx-error_recovery MODBUS_ERROR_RECOVERY_LINK) {int saved_errno errno;if (errno ETIMEDOUT) {_sleep_response_timeout(ctx);modbus_flush(ctx);} else if (errno EBADF) {modbus_close(ctx);modbus_connect(ctx);}errno saved_errno;}return -1;}rc ctx-backend-recv(ctx, msg msg_length, length_to_read);if (rc 0) {errno ECONNRESET;rc -1;}if (rc -1) {_error_print(ctx, read);if ((ctx-error_recovery MODBUS_ERROR_RECOVERY_LINK) (errno ECONNRESET || errno ECONNREFUSED ||errno EBADF)) {int saved_errno errno;modbus_close(ctx);modbus_connect(ctx);/* Could be removed by previous calls */errno saved_errno;}return -1;}/* Display the hex code of each character received */if (ctx-debug) {int i;for (i0; i rc; i)printf(%.2X, msg[msg_length i]);}/* Sums bytes received */msg_length rc;/* Computes remaining bytes */length_to_read - rc;if (length_to_read 0) {switch (step) {case _STEP_FUNCTION:/* Function code position */length_to_read compute_meta_length_after_function(msg[ctx-backend-header_length],msg_type);if (length_to_read ! 0) {step _STEP_META;break;} /* else switches straight to the next step */case _STEP_META:length_to_read compute_data_length_after_meta(ctx, msg, msg_type);if ((msg_length length_to_read) (int)ctx-backend-max_adu_length) {errno EMBBADDATA;_error_print(ctx, too many data);return -1;}step _STEP_DATA;break;default:break;}}if (length_to_read 0 (ctx-byte_timeout.tv_sec 0 || ctx-byte_timeout.tv_usec 0)) {/* If there is no character in the buffer, the allowed timeoutinterval between two consecutive bytes is defined bybyte_timeout */tv.tv_sec ctx-byte_timeout.tv_sec;tv.tv_usec ctx-byte_timeout.tv_usec;p_tv tv;}/* else timeout isnt set again, the full response must be read beforeexpiration of response timeout (for CONFIRMATION only) */}if (ctx-debug)printf(\n);return ctx-backend-check_integrity(ctx, msg, msg_length); }/* Receive the request from a modbus master */ int modbus_receive(modbus_t *ctx, uint8_t *req) {if (ctx NULL) {errno EINVAL;return -1;}return ctx-backend-receive(ctx, req); }/* Receives the confirmation.The function shall store the read response in rsp and return the number ofvalues (bits or words). Otherwise, its shall return -1 and errno is set.The function doesnt check the confirmation is the expected response to theinitial request. */ int modbus_receive_confirmation(modbus_t *ctx, uint8_t *rsp) {if (ctx NULL) {errno EINVAL;return -1;}return _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION); }static int check_confirmation(modbus_t *ctx, uint8_t *req,uint8_t *rsp, int rsp_length) {int rc;int rsp_length_computed;const int offset ctx-backend-header_length;const int function rsp[offset];if (ctx-backend-pre_check_confirmation) {rc ctx-backend-pre_check_confirmation(ctx, req, rsp, rsp_length);if (rc -1) {if (ctx-error_recovery MODBUS_ERROR_RECOVERY_PROTOCOL) {_sleep_response_timeout(ctx);modbus_flush(ctx);}return -1;}}rsp_length_computed compute_response_length_from_request(ctx, req);/* Exception code */if (function 0x80) {if (rsp_length (offset 2 (int)ctx-backend-checksum_length) req[offset] (rsp[offset] - 0x80)) {/* Valid exception code received */int exception_code rsp[offset 1];if (exception_code MODBUS_EXCEPTION_MAX) {errno MODBUS_ENOBASE exception_code;} else {errno EMBBADEXC;}_error_print(ctx, NULL);return -1;} else {errno EMBBADEXC;_error_print(ctx, NULL);return -1;}}/* Check length */if ((rsp_length rsp_length_computed ||rsp_length_computed MSG_LENGTH_UNDEFINED) function 0x80) {int req_nb_value;int rsp_nb_value;/* Check function code */if (function ! req[offset]) {if (ctx-debug) {fprintf(stderr,Received function not corresponding to the request (0x%X ! 0x%X)\n,function, req[offset]);}if (ctx-error_recovery MODBUS_ERROR_RECOVERY_PROTOCOL) {_sleep_response_timeout(ctx);modbus_flush(ctx);}errno EMBBADDATA;return -1;}/* Check the number of values is corresponding to the request */switch (function) {case MODBUS_FC_READ_COILS:case MODBUS_FC_READ_DISCRETE_INPUTS:/* Read functions, 8 values in a byte (nb* of values in the request and byte count in* the response. */req_nb_value (req[offset 3] 8) req[offset 4];req_nb_value (req_nb_value / 8) ((req_nb_value % 8) ? 1 : 0);rsp_nb_value rsp[offset 1];break;case MODBUS_FC_WRITE_AND_READ_REGISTERS:case MODBUS_FC_READ_HOLDING_REGISTERS:case MODBUS_FC_READ_INPUT_REGISTERS:/* Read functions 1 value 2 bytes */req_nb_value (req[offset 3] 8) req[offset 4];rsp_nb_value (rsp[offset 1] / 2);break;case MODBUS_FC_WRITE_MULTIPLE_COILS:case MODBUS_FC_WRITE_MULTIPLE_REGISTERS:/* N Write functions */req_nb_value (req[offset 3] 8) req[offset 4];rsp_nb_value (rsp[offset 3] 8) | rsp[offset 4];break;case MODBUS_FC_REPORT_SLAVE_ID:/* Report slave ID (bytes received) */req_nb_value rsp_nb_value rsp[offset 1];break;default:/* 1 Write functions others */req_nb_value rsp_nb_value 1;}if (req_nb_value rsp_nb_value) {rc rsp_nb_value;} else {if (ctx-debug) {fprintf(stderr,Quantity not corresponding to the request (%d ! %d)\n,rsp_nb_value, req_nb_value);}if (ctx-error_recovery MODBUS_ERROR_RECOVERY_PROTOCOL) {_sleep_response_timeout(ctx);modbus_flush(ctx);}errno EMBBADDATA;rc -1;}} else {if (ctx-debug) {fprintf(stderr,Message length not corresponding to the computed length (%d ! %d)\n,rsp_length, rsp_length_computed);}if (ctx-error_recovery MODBUS_ERROR_RECOVERY_PROTOCOL) {_sleep_response_timeout(ctx);modbus_flush(ctx);}errno EMBBADDATA;rc -1;}return rc; }static int response_io_status(uint8_t *tab_io_status,int address, int nb,uint8_t *rsp, int offset) {int shift 0;/* Instead of byte (not allowed in Win32) */int one_byte 0;int i;for (i address; i address nb; i) {one_byte | tab_io_status[i] shift;if (shift 7) {/* Byte is full */rsp[offset] one_byte;one_byte shift 0;} else {shift;}}if (shift ! 0)rsp[offset] one_byte;return offset; }/* Build the exception response */ static int response_exception(modbus_t *ctx, sft_t *sft,int exception_code, uint8_t *rsp,unsigned int to_flush,const char* template, ...) {int rsp_length;/* Print debug message */if (ctx-debug) {va_list ap;va_start(ap, template);vfprintf(stderr, template, ap);va_end(ap);}/* Flush if required */if (to_flush) {_sleep_response_timeout(ctx);modbus_flush(ctx);}/* Build exception response */sft-function sft-function 0x80;rsp_length ctx-backend-build_response_basis(sft, rsp);rsp[rsp_length] exception_code;return rsp_length; }/* Send a response to the received request.Analyses the request and constructs a response.If an error occurs, this function construct the responseaccordingly. */ int modbus_reply(modbus_t *ctx, const uint8_t *req,int req_length, modbus_mapping_t *mb_mapping) {int offset;int slave;int function;uint16_t address;uint8_t rsp[MAX_MESSAGE_LENGTH];int rsp_length 0;sft_t sft;if (ctx NULL) {errno EINVAL;return -1;}offset ctx-backend-header_length;slave req[offset - 1];function req[offset];address (req[offset 1] 8) req[offset 2];sft.slave slave;sft.function function;sft.t_id ctx-backend-prepare_response_tid(req, req_length);/* Data are flushed on illegal number of values errors. */switch (function) {case MODBUS_FC_READ_COILS:case MODBUS_FC_READ_DISCRETE_INPUTS: {unsigned int is_input (function MODBUS_FC_READ_DISCRETE_INPUTS);int start_bits is_input ? mb_mapping-start_input_bits : mb_mapping-start_bits;int nb_bits is_input ? mb_mapping-nb_input_bits : mb_mapping-nb_bits;uint8_t *tab_bits is_input ? mb_mapping-tab_input_bits : mb_mapping-tab_bits;const char * const name is_input ? read_input_bits : read_bits;int nb (req[offset 3] 8) req[offset 4];/* The mapping can be shifted to reduce memory consumption and itdoesnt always start at address zero. */int mapping_address address - start_bits;if (nb 1 || MODBUS_MAX_READ_BITS nb) {rsp_length response_exception(ctx, sft, MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp, TRUE,Illegal nb of values %d in %s (max %d)\n,nb, name, MODBUS_MAX_READ_BITS);} else if (mapping_address 0 || (mapping_address nb) nb_bits) {rsp_length response_exception(ctx, sft,MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, rsp, FALSE,Illegal data address 0x%0X in %s\n,mapping_address 0 ? address : address nb, name);} else {rsp_length ctx-backend-build_response_basis(sft, rsp);rsp[rsp_length] (nb / 8) ((nb % 8) ? 1 : 0);rsp_length response_io_status(tab_bits, mapping_address, nb,rsp, rsp_length);}}break;case MODBUS_FC_READ_HOLDING_REGISTERS:case MODBUS_FC_READ_INPUT_REGISTERS: {unsigned int is_input (function MODBUS_FC_READ_INPUT_REGISTERS);int start_registers is_input ? mb_mapping-start_input_registers : mb_mapping-start_registers;int nb_registers is_input ? mb_mapping-nb_input_registers : mb_mapping-nb_registers;uint16_t *tab_registers is_input ? mb_mapping-tab_input_registers : mb_mapping-tab_registers;const char * const name is_input ? read_input_registers : read_registers;int nb (req[offset 3] 8) req[offset 4];/* The mapping can be shifted to reduce memory consumption and itdoesnt always start at address zero. */int mapping_address address - start_registers;if (nb 1 || MODBUS_MAX_READ_REGISTERS nb) {rsp_length response_exception(ctx, sft, MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp, TRUE,Illegal nb of values %d in %s (max %d)\n,nb, name, MODBUS_MAX_READ_REGISTERS);} else if (mapping_address 0 || (mapping_address nb) nb_registers) {rsp_length response_exception(ctx, sft, MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, rsp, FALSE,Illegal data address 0x%0X in %s\n,mapping_address 0 ? address : address nb, name);} else {int i;rsp_length ctx-backend-build_response_basis(sft, rsp);rsp[rsp_length] nb 1;for (i mapping_address; i mapping_address nb; i) {rsp[rsp_length] tab_registers[i] 8;rsp[rsp_length] tab_registers[i] 0xFF;}}}break;case MODBUS_FC_WRITE_SINGLE_COIL: {int mapping_address address - mb_mapping-start_bits;if (mapping_address 0 || mapping_address mb_mapping-nb_bits) {rsp_length response_exception(ctx, sft, MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, rsp, FALSE,Illegal data address 0x%0X in write_bit\n,address);} else {int data (req[offset 3] 8) req[offset 4];if (data 0xFF00 || data 0x0) {mb_mapping-tab_bits[mapping_address] data ? ON : OFF;memcpy(rsp, req, req_length);rsp_length req_length;} else {rsp_length response_exception(ctx, sft,MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp, FALSE,Illegal data value 0x%0X in write_bit request at address %0X\n,data, address);}}}break;case MODBUS_FC_WRITE_SINGLE_REGISTER: {int mapping_address address - mb_mapping-start_registers;if (mapping_address 0 || mapping_address mb_mapping-nb_registers) {rsp_length response_exception(ctx, sft,MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, rsp, FALSE,Illegal data address 0x%0X in write_register\n,address);} else {int data (req[offset 3] 8) req[offset 4];mb_mapping-tab_registers[mapping_address] data;memcpy(rsp, req, req_length);rsp_length req_length;}}break;case MODBUS_FC_WRITE_MULTIPLE_COILS: {int nb (req[offset 3] 8) req[offset 4];int nb_bits req[offset 5];int mapping_address address - mb_mapping-start_bits;if (nb 1 || MODBUS_MAX_WRITE_BITS nb || nb_bits * 8 nb) {/* May be the indication has been truncated on reading because of* invalid address (eg. nb is 0 but the request contains values to* write) so its necessary to flush. */rsp_length response_exception(ctx, sft, MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp, TRUE,Illegal number of values %d in write_bits (max %d)\n,nb, MODBUS_MAX_WRITE_BITS);} else if (mapping_address 0 ||(mapping_address nb) mb_mapping-nb_bits) {rsp_length response_exception(ctx, sft,MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, rsp, FALSE,Illegal data address 0x%0X in write_bits\n,mapping_address 0 ? address : address nb);} else {/* 6 byte count */modbus_set_bits_from_bytes(mb_mapping-tab_bits, mapping_address, nb,req[offset 6]);rsp_length ctx-backend-build_response_basis(sft, rsp);/* 4 to copy the bit address (2) and the quantity of bits */memcpy(rsp rsp_length, req rsp_length, 4);rsp_length 4;}}break;case MODBUS_FC_WRITE_MULTIPLE_REGISTERS: {int nb (req[offset 3] 8) req[offset 4];int nb_bytes req[offset 5];int mapping_address address - mb_mapping-start_registers;if (nb 1 || MODBUS_MAX_WRITE_REGISTERS nb || nb_bytes ! nb * 2) {rsp_length response_exception(ctx, sft, MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp, TRUE,Illegal number of values %d in write_registers (max %d)\n,nb, MODBUS_MAX_WRITE_REGISTERS);} else if (mapping_address 0 ||(mapping_address nb) mb_mapping-nb_registers) {rsp_length response_exception(ctx, sft, MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, rsp, FALSE,Illegal data address 0x%0X in write_registers\n,mapping_address 0 ? address : address nb);} else {int i, j;for (i mapping_address, j 6; i mapping_address nb; i, j 2) {/* 6 and 7 first value */mb_mapping-tab_registers[i] (req[offset j] 8) req[offset j 1];}rsp_length ctx-backend-build_response_basis(sft, rsp);/* 4 to copy the address (2) and the no. of registers */memcpy(rsp rsp_length, req rsp_length, 4);rsp_length 4;}}break;case MODBUS_FC_REPORT_SLAVE_ID: {int str_len;int byte_count_pos;rsp_length ctx-backend-build_response_basis(sft, rsp);/* Skip byte count for now */byte_count_pos rsp_length;rsp[rsp_length] _REPORT_SLAVE_ID;/* Run indicator status to ON */rsp[rsp_length] 0xFF;/* LMB length of LIBMODBUS_VERSION_STRING */str_len 3 strlen(LIBMODBUS_VERSION_STRING);memcpy(rsp rsp_length, LMB LIBMODBUS_VERSION_STRING, str_len);rsp_length str_len;rsp[byte_count_pos] rsp_length - byte_count_pos - 1;}break;case MODBUS_FC_READ_EXCEPTION_STATUS:if (ctx-debug) {fprintf(stderr, FIXME Not implemented\n);}errno ENOPROTOOPT;return -1;break;case MODBUS_FC_MASK_WRITE_REGISTER: {int mapping_address address - mb_mapping-start_registers;if (mapping_address 0 || mapping_address mb_mapping-nb_registers) {rsp_length response_exception(ctx, sft, MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, rsp, FALSE,Illegal data address 0x%0X in write_register\n,address);} else {uint16_t data mb_mapping-tab_registers[mapping_address];uint16_t and (req[offset 3] 8) req[offset 4];uint16_t or (req[offset 5] 8) req[offset 6];data (data and) | (or (~and));mb_mapping-tab_registers[mapping_address] data;memcpy(rsp, req, req_length);rsp_length req_length;}}break;case MODBUS_FC_WRITE_AND_READ_REGISTERS: {int nb (req[offset 3] 8) req[offset 4];uint16_t address_write (req[offset 5] 8) req[offset 6];int nb_write (req[offset 7] 8) req[offset 8];int nb_write_bytes req[offset 9];int mapping_address address - mb_mapping-start_registers;int mapping_address_write address_write - mb_mapping-start_registers;if (nb_write 1 || MODBUS_MAX_WR_WRITE_REGISTERS nb_write ||nb 1 || MODBUS_MAX_WR_READ_REGISTERS nb ||nb_write_bytes ! nb_write * 2) {rsp_length response_exception(ctx, sft, MODBUS_EXCEPTION_ILLEGAL_DATA_VALUE, rsp, TRUE,Illegal nb of values (W%d, R%d) in write_and_read_registers (max W%d, R%d)\n,nb_write, nb, MODBUS_MAX_WR_WRITE_REGISTERS, MODBUS_MAX_WR_READ_REGISTERS);} else if (mapping_address 0 ||(mapping_address nb) mb_mapping-nb_registers ||mapping_address 0 ||(mapping_address_write nb_write) mb_mapping-nb_registers) {rsp_length response_exception(ctx, sft, MODBUS_EXCEPTION_ILLEGAL_DATA_ADDRESS, rsp, FALSE,Illegal data read address 0x%0X or write address 0x%0X write_and_read_registers\n,mapping_address 0 ? address : address nb,mapping_address_write 0 ? address_write : address_write nb_write);} else {int i, j;rsp_length ctx-backend-build_response_basis(sft, rsp);rsp[rsp_length] nb 1;/* Write first.10 and 11 are the offset of the first values to write */for (i mapping_address_write, j 10;i mapping_address_write nb_write; i, j 2) {mb_mapping-tab_registers[i] (req[offset j] 8) req[offset j 1];}/* and read the data for the response */for (i mapping_address; i mapping_address nb; i) {rsp[rsp_length] mb_mapping-tab_registers[i] 8;rsp[rsp_length] mb_mapping-tab_registers[i] 0xFF;}}}break;default:rsp_length response_exception(ctx, sft, MODBUS_EXCEPTION_ILLEGAL_FUNCTION, rsp, TRUE,Unknown Modbus function code: 0x%0X\n, function);break;}/* Suppress any responses when the request was a broadcast */return (ctx-backend-backend_type _MODBUS_BACKEND_TYPE_RTU slave MODBUS_BROADCAST_ADDRESS) ? 0 : send_msg(ctx, rsp, rsp_length); }int modbus_reply_exception(modbus_t *ctx, const uint8_t *req,unsigned int exception_code) {int offset;int slave;int function;uint8_t rsp[MAX_MESSAGE_LENGTH];int rsp_length;int dummy_length 99;sft_t sft;if (ctx NULL) {errno EINVAL;return -1;}offset ctx-backend-header_length;slave req[offset - 1];function req[offset];sft.slave slave;sft.function function 0x80;sft.t_id ctx-backend-prepare_response_tid(req, dummy_length);rsp_length ctx-backend-build_response_basis(sft, rsp);/* Positive exception code */if (exception_code MODBUS_EXCEPTION_MAX) {rsp[rsp_length] exception_code;return send_msg(ctx, rsp, rsp_length);} else {errno EINVAL;return -1;} }/* Reads IO status */ static int read_io_status(modbus_t *ctx, int function,int addr, int nb, uint8_t *dest) {int rc;int req_length;uint8_t req[_MIN_REQ_LENGTH];uint8_t rsp[MAX_MESSAGE_LENGTH];req_length ctx-backend-build_request_basis(ctx, function, addr, nb, req);rc send_msg(ctx, req, req_length);if (rc 0) {int i, temp, bit;int pos 0;int offset;int offset_end;rc _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION);if (rc -1)return -1;rc check_confirmation(ctx, req, rsp, rc);if (rc -1)return -1;offset ctx-backend-header_length 2;offset_end offset rc;for (i offset; i offset_end; i) {/* Shift reg hi_byte to temp */temp rsp[i];for (bit 0x01; (bit 0xff) (pos nb);) {dest[pos] (temp bit) ? TRUE : FALSE;bit bit 1;}}}return rc; }/* Reads the boolean status of bits and sets the array elementsin the destination to TRUE or FALSE (single bits). */ int modbus_read_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest) {int rc;if (ctx NULL) {errno EINVAL;return -1;}if (nb MODBUS_MAX_READ_BITS) {if (ctx-debug) {fprintf(stderr,ERROR Too many bits requested (%d %d)\n,nb, MODBUS_MAX_READ_BITS);}errno EMBMDATA;return -1;}rc read_io_status(ctx, MODBUS_FC_READ_COILS, addr, nb, dest);if (rc -1)return -1;elsereturn nb; }/* Same as modbus_read_bits but reads the remote device input table */ int modbus_read_input_bits(modbus_t *ctx, int addr, int nb, uint8_t *dest) {int rc;if (ctx NULL) {errno EINVAL;return -1;}if (nb MODBUS_MAX_READ_BITS) {if (ctx-debug) {fprintf(stderr,ERROR Too many discrete inputs requested (%d %d)\n,nb, MODBUS_MAX_READ_BITS);}errno EMBMDATA;return -1;}rc read_io_status(ctx, MODBUS_FC_READ_DISCRETE_INPUTS, addr, nb, dest);if (rc -1)return -1;elsereturn nb; }/* Reads the data from a remove device and put that data into an array */ static int read_registers(modbus_t *ctx, int function, int addr, int nb,uint16_t *dest) {int rc;int req_length;uint8_t req[_MIN_REQ_LENGTH];uint8_t rsp[MAX_MESSAGE_LENGTH];if (nb MODBUS_MAX_READ_REGISTERS) {if (ctx-debug) {fprintf(stderr,ERROR Too many registers requested (%d %d)\n,nb, MODBUS_MAX_READ_REGISTERS);}errno EMBMDATA;return -1;}req_length ctx-backend-build_request_basis(ctx, function, addr, nb, req);rc send_msg(ctx, req, req_length);if (rc 0) {int offset;int i;rc _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION);if (rc -1)return -1;rc check_confirmation(ctx, req, rsp, rc);if (rc -1)return -1;offset ctx-backend-header_length;for (i 0; i rc; i) {/* shift reg hi_byte to temp OR with lo_byte */dest[i] (rsp[offset 2 (i 1)] 8) |rsp[offset 3 (i 1)];}}return rc; }/* Reads the holding registers of remote device and put the data into anarray */ int modbus_read_registers(modbus_t *ctx, int addr, int nb, uint16_t *dest) {int status;if (ctx NULL) {errno EINVAL;return -1;}if (nb MODBUS_MAX_READ_REGISTERS) {if (ctx-debug) {fprintf(stderr,ERROR Too many registers requested (%d %d)\n,nb, MODBUS_MAX_READ_REGISTERS);}errno EMBMDATA;return -1;}status read_registers(ctx, MODBUS_FC_READ_HOLDING_REGISTERS,addr, nb, dest);return status; }/* Reads the input registers of remote device and put the data into an array */ int modbus_read_input_registers(modbus_t *ctx, int addr, int nb,uint16_t *dest) {int status;if (ctx NULL) {errno EINVAL;return -1;}if (nb MODBUS_MAX_READ_REGISTERS) {fprintf(stderr,ERROR Too many input registers requested (%d %d)\n,nb, MODBUS_MAX_READ_REGISTERS);errno EMBMDATA;return -1;}status read_registers(ctx, MODBUS_FC_READ_INPUT_REGISTERS,addr, nb, dest);return status; }/* Write a value to the specified register of the remote device.Used by write_bit and write_register */ static int write_single(modbus_t *ctx, int function, int addr, const uint16_t value) {int rc;int req_length;uint8_t req[_MIN_REQ_LENGTH];if (ctx NULL) {errno EINVAL;return -1;}req_length ctx-backend-build_request_basis(ctx, function, addr, (int) value, req);rc send_msg(ctx, req, req_length);if (rc 0) {/* Used by write_bit and write_register */uint8_t rsp[MAX_MESSAGE_LENGTH];rc _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION);if (rc -1)return -1;rc check_confirmation(ctx, req, rsp, rc);}return rc; }/* Turns ON or OFF a single bit of the remote device */ int modbus_write_bit(modbus_t *ctx, int addr, int status) {if (ctx NULL) {errno EINVAL;return -1;}return write_single(ctx, MODBUS_FC_WRITE_SINGLE_COIL, addr,status ? 0xFF00 : 0); }/* Writes a value in one register of the remote device */ int modbus_write_register(modbus_t *ctx, int addr, const uint16_t value) {if (ctx NULL) {errno EINVAL;return -1;}return write_single(ctx, MODBUS_FC_WRITE_SINGLE_REGISTER, addr, value); }/* Write the bits of the array in the remote device */ int modbus_write_bits(modbus_t *ctx, int addr, int nb, const uint8_t *src) {int rc;int i;int byte_count;int req_length;int bit_check 0;int pos 0;uint8_t req[MAX_MESSAGE_LENGTH];if (ctx NULL) {errno EINVAL;return -1;}if (nb MODBUS_MAX_WRITE_BITS) {if (ctx-debug) {fprintf(stderr, ERROR Writing too many bits (%d %d)\n,nb, MODBUS_MAX_WRITE_BITS);}errno EMBMDATA;return -1;}req_length ctx-backend-build_request_basis(ctx,MODBUS_FC_WRITE_MULTIPLE_COILS,addr, nb, req);byte_count (nb / 8) ((nb % 8) ? 1 : 0);req[req_length] byte_count;for (i 0; i byte_count; i) {int bit;bit 0x01;req[req_length] 0;while ((bit 0xFF) (bit_check nb)) {if (src[pos])req[req_length] | bit;elsereq[req_length] ~ bit;bit bit 1;}req_length;}rc send_msg(ctx, req, req_length);if (rc 0) {uint8_t rsp[MAX_MESSAGE_LENGTH];rc _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION);if (rc -1)return -1;rc check_confirmation(ctx, req, rsp, rc);}return rc; }/* Write the values from the array to the registers of the remote device */ int modbus_write_registers(modbus_t *ctx, int addr, int nb, const uint16_t *src) {int rc;int i;int req_length;int byte_count;uint8_t req[MAX_MESSAGE_LENGTH];if (ctx NULL) {errno EINVAL;return -1;}if (nb MODBUS_MAX_WRITE_REGISTERS) {if (ctx-debug) {fprintf(stderr,ERROR Trying to write to too many registers (%d %d)\n,nb, MODBUS_MAX_WRITE_REGISTERS);}errno EMBMDATA;return -1;}req_length ctx-backend-build_request_basis(ctx,MODBUS_FC_WRITE_MULTIPLE_REGISTERS,addr, nb, req);byte_count nb * 2;req[req_length] byte_count;for (i 0; i nb; i) {req[req_length] src[i] 8;req[req_length] src[i] 0x00FF;}rc send_msg(ctx, req, req_length);if (rc 0) {uint8_t rsp[MAX_MESSAGE_LENGTH];rc _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION);if (rc -1)return -1;rc check_confirmation(ctx, req, rsp, rc);}return rc; }int modbus_mask_write_register(modbus_t *ctx, int addr, uint16_t and_mask, uint16_t or_mask) {int rc;int req_length;/* The request length can not exceed _MIN_REQ_LENGTH - 2 and 4 bytes to* store the masks. The ugly substraction is there to remove the nb value* (2 bytes) which is not used. */uint8_t req[_MIN_REQ_LENGTH 2];req_length ctx-backend-build_request_basis(ctx,MODBUS_FC_MASK_WRITE_REGISTER,addr, 0, req);/* HACKISH, count is not used */req_length - 2;req[req_length] and_mask 8;req[req_length] and_mask 0x00ff;req[req_length] or_mask 8;req[req_length] or_mask 0x00ff;rc send_msg(ctx, req, req_length);if (rc 0) {/* Used by write_bit and write_register */uint8_t rsp[MAX_MESSAGE_LENGTH];rc _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION);if (rc -1)return -1;rc check_confirmation(ctx, req, rsp, rc);}return rc; }/* Write multiple registers from src array to remote device and read multipleregisters from remote device to dest array. */ int modbus_write_and_read_registers(modbus_t *ctx,int write_addr, int write_nb,const uint16_t *src,int read_addr, int read_nb,uint16_t *dest){int rc;int req_length;int i;int byte_count;uint8_t req[MAX_MESSAGE_LENGTH];uint8_t rsp[MAX_MESSAGE_LENGTH];if (ctx NULL) {errno EINVAL;return -1;}if (write_nb MODBUS_MAX_WR_WRITE_REGISTERS) {if (ctx-debug) {fprintf(stderr,ERROR Too many registers to write (%d %d)\n,write_nb, MODBUS_MAX_WR_WRITE_REGISTERS);}errno EMBMDATA;return -1;}if (read_nb MODBUS_MAX_WR_READ_REGISTERS) {if (ctx-debug) {fprintf(stderr,ERROR Too many registers requested (%d %d)\n,read_nb, MODBUS_MAX_WR_READ_REGISTERS);}errno EMBMDATA;return -1;}req_length ctx-backend-build_request_basis(ctx,MODBUS_FC_WRITE_AND_READ_REGISTERS,read_addr, read_nb, req);req[req_length] write_addr 8;req[req_length] write_addr 0x00ff;req[req_length] write_nb 8;req[req_length] write_nb 0x00ff;byte_count write_nb * 2;req[req_length] byte_count;for (i 0; i write_nb; i) {req[req_length] src[i] 8;req[req_length] src[i] 0x00FF;}rc send_msg(ctx, req, req_length);if (rc 0) {int offset;rc _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION);if (rc -1)return -1;rc check_confirmation(ctx, req, rsp, rc);if (rc -1)return -1;offset ctx-backend-header_length;for (i 0; i rc; i) {/* shift reg hi_byte to temp OR with lo_byte */dest[i] (rsp[offset 2 (i 1)] 8) |rsp[offset 3 (i 1)];}}return rc; }/* Send a request to get the slave ID of the device (only available in serialcommunication). */ int modbus_report_slave_id(modbus_t *ctx, int max_dest, uint8_t *dest) {int rc;int req_length;uint8_t req[_MIN_REQ_LENGTH];if (ctx NULL || max_dest 0) {errno EINVAL;return -1;}req_length ctx-backend-build_request_basis(ctx, MODBUS_FC_REPORT_SLAVE_ID,0, 0, req);/* HACKISH, addr and count are not used */req_length - 4;rc send_msg(ctx, req, req_length);if (rc 0) {int i;int offset;uint8_t rsp[MAX_MESSAGE_LENGTH];rc _modbus_receive_msg(ctx, rsp, MSG_CONFIRMATION);if (rc -1)return -1;rc check_confirmation(ctx, req, rsp, rc);if (rc -1)return -1;offset ctx-backend-header_length 2;/* Byte count, slave id, run indicator status andadditional data. Truncate copy to max_dest. */for (i0; i rc i max_dest; i) {dest[i] rsp[offset i];}}return rc; }void _modbus_init_common(modbus_t *ctx) {/* Slave and socket are initialized to -1 */ctx-slave -1;ctx-s -1;ctx-debug FALSE;ctx-error_recovery MODBUS_ERROR_RECOVERY_NONE;ctx-response_timeout.tv_sec 0;ctx-response_timeout.tv_usec _RESPONSE_TIMEOUT;ctx-byte_timeout.tv_sec 0;ctx-byte_timeout.tv_usec _BYTE_TIMEOUT;ctx-indication_timeout.tv_sec 0;ctx-indication_timeout.tv_usec 0; }/* Define the slave number */ int modbus_set_slave(modbus_t *ctx, int slave) {if (ctx NULL) {errno EINVAL;return -1;}return ctx-backend-set_slave(ctx, slave); }int modbus_get_slave(modbus_t *ctx) {if (ctx NULL) {errno EINVAL;return -1;}return ctx-slave; }int modbus_set_error_recovery(modbus_t *ctx,modbus_error_recovery_mode error_recovery) {if (ctx NULL) {errno EINVAL;return -1;}/* The type of modbus_error_recovery_mode is unsigned enum */ctx-error_recovery (uint8_t) error_recovery;return 0; }int modbus_set_socket(modbus_t *ctx, int s) {if (ctx NULL) {errno EINVAL;return -1;}ctx-s s;return 0; }int modbus_get_socket(modbus_t *ctx) {if (ctx NULL) {errno EINVAL;return -1;}return ctx-s; }/* Get the timeout interval used to wait for a response */ int modbus_get_response_timeout(modbus_t *ctx, uint32_t *to_sec, uint32_t *to_usec) {if (ctx NULL) {errno EINVAL;return -1;}*to_sec ctx-response_timeout.tv_sec;*to_usec ctx-response_timeout.tv_usec;return 0; }int modbus_set_response_timeout(modbus_t *ctx, uint32_t to_sec, uint32_t to_usec) {if (ctx NULL ||(to_sec 0 to_usec 0) || to_usec 999999) {errno EINVAL;return -1;}ctx-response_timeout.tv_sec to_sec;ctx-response_timeout.tv_usec to_usec;return 0; }/* Get the timeout interval between two consecutive bytes of a message */ int modbus_get_byte_timeout(modbus_t *ctx, uint32_t *to_sec, uint32_t *to_usec) {if (ctx NULL) {errno EINVAL;return -1;}*to_sec ctx-byte_timeout.tv_sec;*to_usec ctx-byte_timeout.tv_usec;return 0; }int modbus_set_byte_timeout(modbus_t *ctx, uint32_t to_sec, uint32_t to_usec) {/* Byte timeout can be disabled when both values are zero */if (ctx NULL || to_usec 999999) {errno EINVAL;return -1;}ctx-byte_timeout.tv_sec to_sec;ctx-byte_timeout.tv_usec to_usec;return 0; }/* Get the timeout interval used by the server to wait for an indication from a client */ int modbus_get_indication_timeout(modbus_t *ctx, uint32_t *to_sec, uint32_t *to_usec) {if (ctx NULL) {errno EINVAL;return -1;}*to_sec ctx-indication_timeout.tv_sec;*to_usec ctx-indication_timeout.tv_usec;return 0; }int modbus_set_indication_timeout(modbus_t *ctx, uint32_t to_sec, uint32_t to_usec) {/* Indication timeout can be disabled when both values are zero */if (ctx NULL || to_usec 999999) {errno EINVAL;return -1;}ctx-indication_timeout.tv_sec to_sec;ctx-indication_timeout.tv_usec to_usec;return 0; }int modbus_get_header_length(modbus_t *ctx) {if (ctx NULL) {errno EINVAL;return -1;}return ctx-backend-header_length; }int modbus_connect(modbus_t *ctx) {if (ctx NULL) {errno EINVAL;return -1;}return ctx-backend-connect(ctx); }void modbus_close(modbus_t *ctx) {if (ctx NULL)return;ctx-backend-close(ctx); }void modbus_free(modbus_t *ctx) {if (ctx NULL)return;ctx-backend-free(ctx); }int modbus_set_debug(modbus_t *ctx, int flag) {if (ctx NULL) {errno EINVAL;return -1;}ctx-debug flag;return 0; }/* Allocates 4 arrays to store bits, input bits, registers and inputsregisters. The pointers are stored in modbus_mapping structure.The modbus_mapping_new_start_address() function shall return the new allocatedstructure if successful. Otherwise it shall return NULL and set errno toENOMEM. */ modbus_mapping_t* modbus_mapping_new_start_address(unsigned int start_bits, unsigned int nb_bits,unsigned int start_input_bits, unsigned int nb_input_bits,unsigned int start_registers, unsigned int nb_registers,unsigned int start_input_registers, unsigned int nb_input_registers) {modbus_mapping_t *mb_mapping;mb_mapping (modbus_mapping_t *)malloc(sizeof(modbus_mapping_t));if (mb_mapping NULL) {return NULL;}/* 0X */mb_mapping-nb_bits nb_bits;mb_mapping-start_bits start_bits;if (nb_bits 0) {mb_mapping-tab_bits NULL;} else {/* Negative number raises a POSIX error */mb_mapping-tab_bits (uint8_t *) malloc(nb_bits * sizeof(uint8_t));if (mb_mapping-tab_bits NULL) {free(mb_mapping);return NULL;}memset(mb_mapping-tab_bits, 0, nb_bits * sizeof(uint8_t));}/* 1X */mb_mapping-nb_input_bits nb_input_bits;mb_mapping-start_input_bits start_input_bits;if (nb_input_bits 0) {mb_mapping-tab_input_bits NULL;} else {mb_mapping-tab_input_bits (uint8_t *) malloc(nb_input_bits * sizeof(uint8_t));if (mb_mapping-tab_input_bits NULL) {free(mb_mapping-tab_bits);free(mb_mapping);return NULL;}memset(mb_mapping-tab_input_bits, 0, nb_input_bits * sizeof(uint8_t));}/* 4X */mb_mapping-nb_registers nb_registers;mb_mapping-start_registers start_registers;if (nb_registers 0) {mb_mapping-tab_registers NULL;} else {mb_mapping-tab_registers (uint16_t *) malloc(nb_registers * sizeof(uint16_t));if (mb_mapping-tab_registers NULL) {free(mb_mapping-tab_input_bits);free(mb_mapping-tab_bits);free(mb_mapping);return NULL;}memset(mb_mapping-tab_registers, 0, nb_registers * sizeof(uint16_t));}/* 3X */mb_mapping-nb_input_registers nb_input_registers;mb_mapping-start_input_registers start_input_registers;if (nb_input_registers 0) {mb_mapping-tab_input_registers NULL;} else {mb_mapping-tab_input_registers (uint16_t *) malloc(nb_input_registers * sizeof(uint16_t));if (mb_mapping-tab_input_registers NULL) {free(mb_mapping-tab_registers);free(mb_mapping-tab_input_bits);free(mb_mapping-tab_bits);free(mb_mapping);return NULL;}memset(mb_mapping-tab_input_registers, 0,nb_input_registers * sizeof(uint16_t));}return mb_mapping; }modbus_mapping_t* modbus_mapping_new(int nb_bits, int nb_input_bits,int nb_registers, int nb_input_registers) {return modbus_mapping_new_start_address(0, nb_bits, 0, nb_input_bits, 0, nb_registers, 0, nb_input_registers); }/* Frees the 4 arrays */ void modbus_mapping_free(modbus_mapping_t *mb_mapping) {if (mb_mapping NULL) {return;}free(mb_mapping-tab_input_registers);free(mb_mapping-tab_registers);free(mb_mapping-tab_input_bits);free(mb_mapping-tab_bits);free(mb_mapping); }#ifndef HAVE_STRLCPY /** Function strlcpy was originally developed by* Todd C. Miller Todd.Millercourtesan.com to simplify writing secure code.* See ftp://ftp.openbsd.org/pub/OpenBSD/src/lib/libc/string/strlcpy.3* for more information.** Thank you Ulrich Drepper... not!** Copy src to string dest of size dest_size. At most dest_size-1 characters* will be copied. Always NUL terminates (unless dest_size 0). Returns* strlen(src); if retval dest_size, truncation occurred.*/ size_t strlcpy(char *dest, const char *src, size_t dest_size) {register char *d dest;register const char *s src;register size_t n dest_size;/* Copy as many bytes as will fit */if (n ! 0 --n ! 0) {do {if ((*d *s) 0)break;} while (--n ! 0);}/* Not enough room in dest, add NUL and traverse rest of src */if (n 0) {if (dest_size ! 0)*d \0; /* NUL-terminate dest */while (*s);}return (s - src - 1); /* count does not include NUL */ } #endifLibModbus库实际工程应用 首先要下载安装VisualStudio2019或者VisualStudio2022下载连接如下 https://visualstudio.microsoft.com/zh-hans/downloads/https://visualstudio.microsoft.com/zh-hans/downloads/ 1、TIA中新建项目插入PLC 1214C,PLC属性设置如上所示IP地址为192.168.1.214。DB块中数据如下图所示远程连接地址设置为192.168.1.106不设置代表任何客户端都可连接。 2、编写ModbusTCP Server端程序程序如下图所示。 3、Modbus通信数据地址隐射为M100如下图所示数据长度映射600个字。 4、监控表中添加M100开始的数据监控表。如下图所示。 5、打开VisualStudio2019新建名为“MFCApplicationMultiLineTest”的MFC项目。将modbus.h头文件增加到项目MFCApplicationMultiLineTest.CPP文件中如下图所示。 6、新建如下全局变量用于通信和线程管理。 #define LOOP 1 #define CLIENT_ID 20 #define ADDRESS_START 40001 #define ADDRESS_END 40101 #define ADDRESS_MAX 40201 #define ADDRESS_SUPERMAX 40301 #define PI 3.1415926threadInfo Info; CMutex cmtex; BOOL ThreadKiller FALSE; BOOL ForKiller FALSE; HANDLE hMyThread; BOOL ModbusThreadKiller FALSE; BOOL ModbusLoop FALSE; BOOL ServerConnectFailedFlag FALSE; int nb_fail; int nb_loop; int addr; int addr_float 100; int addr_float_supermax 200; int nb; int sel; int flnb; int spnb; int nCount; CString strfloat; modbus_t* ctx; uint8_t * tab_rq_bits; uint8_t * tab_rp_bits; uint16_t* tab_rq_registers; uint16_t* tab_rp_registers; uint16_t* tab_rw_registers; uint16_t* tab_float_registers; uint16_t* tab_float_write_registers; float * read_float_registers; float * write_float_registers; CRect rcClientOld; CRect rcClientNew;7、在OnInitDialog()初始化函数中加入如下代码。窗口打开后即可连接ModbusTCP服务器端。 ctx modbus_new_tcp(192.168.1.214, 502);modbus_set_debug(ctx, TRUE);modbus_set_slave(ctx, CLIENT_ID);modbus_set_response_timeout(ctx, 10, 1000000);if (modbus_connect(ctx) -1){fprintf(stderr, Connection failed: %s\n, modbus_strerror(errno));printf(Connection failed: %s\n, modbus_strerror(errno));OutputDebugString(_T(Connection failed : % s\n));AfxMessageBox(_T(Modbus Server Conneect Failed!), MB_ICONINFORMATION);modbus_close(ctx);modbus_free(ctx);ServerConnectFailedFlag TRUE;return -1;}else{AfxMessageBox(_T(Modbus Server Conneect Success!), MB_ICONINFORMATION);ServerConnectFailedFlag FALSE;}SetTimer(1, 1000, NULL);/*ModbusTCP通讯寄存器内存分配和内存空间初始化*/nb ADDRESS_END - ADDRESS_START;//40001-4101为intflnb ADDRESS_MAX - ADDRESS_END;//40101-40201为floatspnb ADDRESS_SUPERMAX - ADDRESS_MAX;//40201-40301为floattab_rq_bits (uint8_t*)malloc(nb * sizeof(uint8_t));memset(tab_rq_bits,0, nb * sizeof(uint8_t));tab_rp_bits (uint8_t*)malloc(nb * sizeof(uint8_t));memset(tab_rp_bits,0, nb * sizeof(uint8_t));tab_rq_registers (uint16_t*)malloc(nb * sizeof(uint16_t));memset(tab_rq_registers,0, nb * sizeof(uint16_t));tab_rp_registers (uint16_t*)malloc(nb * sizeof(uint16_t));memset(tab_rp_registers,0, nb * sizeof(uint16_t));tab_rw_registers (uint16_t*)malloc(nb * sizeof(uint16_t));memset(tab_rw_registers,0, nb * sizeof(uint16_t));tab_float_registers (uint16_t*)malloc(2 * flnb * sizeof(uint16_t));memset(tab_float_registers,0, 2 * flnb * sizeof(uint16_t));read_float_registers (float*)malloc(flnb * sizeof(float));memset(read_float_registers,0, flnb * sizeof(float));write_float_registers (float*)malloc((flnb) * sizeof(float));memset(write_float_registers,0, (flnb) * sizeof(float));tab_float_write_registers (uint16_t*)malloc(2 * flnb * sizeof(uint16_t));memset(tab_float_write_registers,0, 2 * flnb * sizeof(uint16_t));//**********************************************************************GetClientRect(rcGetold);OldClientPoint.x rcGetold.right - rcGetold.left;OldClientPoint.y rcGetold.bottom - rcGetold.top;8、编写相关的通信线程函数ModBusCommunication(LPVOID* pParam)。Libmodbus库函数说明在Libmodbus官网有详细的说明。 UINT CMFCApplicationMultiLineTestDlg::ModBusCommunication(LPVOID* pParam) {CMFCApplicationMultiLineTestDlg* modbustcp (CMFCApplicationMultiLineTestDlg*)pParam;int rc0;int n0;int qw0;int rq0;int wf 0;float rfloat 0;//COLORREF RGB;BOOL sendmsg FALSE;BOOL dspmsg FALSE;CWnd* thHwnd AfxGetApp()-GetMainWnd();CSingleLock modbuslock(cmtex);modbuslock.Lock();if (ServerConnectFailedFlag FALSE){while (ModbusLoopFALSE){if(ServerConnectFailedFlagFALSE){ if (ModbusThreadKiller)//最好让线程自行退出。{DWORD dwExitCode;GetExitCodeThread(modbustcp-ModbusTcpThread,dwExitCode);AfxEndThread(dwExitCode,TRUE);}else{for (int q 0; q 9; q){rc modbus_write_bit(ctx, q, 0);if (rc ! 1){printf(Error modbus_write_bit(%d)\n, rc);printf(Address%d,value%d\n, q, 0);nb_fail;}else{rc modbus_read_bits(ctx, q, 1, tab_rq_bits);if (rc ! 1 || tab_rq_bits[0] ! 0){printf(Error modbus_read_bit single(%d)\n, rc);printf(Address%d, q);nb_fail;}}Sleep(10);}for (qw 0; qw 9; qw){rc modbus_write_bit(ctx, qw, 1);//西门子S7-1200 I/O地址对应0对应Q0.0,1对应Q0.1,8对应Q1.0if (rc ! 1){printf(Error modbus_write_bit(%d)\n, rc);printf(Address%d,value%d\n, qw, 1);nb_fail;}else{rc modbus_read_bits(ctx, qw, 1, tab_rq_bits);if (rc ! 1 || tab_rq_bits[0] ! 1){printf(Error modbus_read_bit single(%d)\n, rc);printf(Address%d, qw);nb_fail;}}Sleep(10);}addr 0;//addr0对应西门子S7-1200 modbus寄存器400011对应40002、40001映射S7-1200 MW100,40002映射S7-1200 MW102,for (rq 0; rq nb; rq){tab_rq_registers[rq] rq 820 * sel;}//向S7-1200 MD300-MD696寄存器写入100个浮点数据MD300对应modbus寄存器40201200MD696对应寄存器40301for (wf 0;wfflnb; wf){write_float_registers[wf] (wfsel)*(float)PI;modbus_set_float_dcba(write_float_registers[wf], tab_float_write_registers 2 * wf);}rc modbus_write_registers(ctx, addr,nb,tab_rq_registers);if (rc ! nb){printf(Error modbus_write_registers(%d)\n, rc);printf(Address%d,nb%d\n, addr,nb);nb_fail;if (sendmsg FALSE){sendmsg TRUE;::PostMessage(thHwnd-GetSafeHwnd(), WM_THREAD_MONITOR, WPARAM(sendmsg), 0);}}else{rc modbus_read_registers(ctx,addr,nb,tab_rp_registers);if (rc ! nb){printf(Error modbus_read_registers(%d)\n, rc);printf(Address%d,nb%d\n, addr, nb);nb_fail;}else {for (int k 0; k nb; k){if (tab_rq_registers[k] ! tab_rp_registers[k]){printf(Error modbus_read_registers(%d)\n,nb);printf(Address%d,Value %d(0x%X!%d (0x%X))\n,addr,tab_rq_registers[k],tab_rq_registers[k],tab_rp_registers[k],tab_rp_registers[k]);nb_fail;}}}} /*S7-1200浮点数据写入格式为dcba(100-200定义为float数据对应MD300-MD496float数据需要分配2*flnb的存储空间)最大写入123个字写入前50个浮点数据写入100个浮点数据必须分两次写入*/rc modbus_write_registers(ctx,addr_float,flnb,tab_float_write_registers);if (rc!flnb){printf(Error modbus_write_registers(%d)\n,flnb);printf(Address%d,flnb%d\n,addr_float,flnb);nb_fail;}/*S7-1200浮点数据读取格式为dcba(100-200定义为float数据对应MD300-MD496float数据需要分配2*flnb的存储空间)最大写入123个字写入后50个浮点数据写入100个浮点数据必须分两次写入*/rc modbus_write_registers(ctx, addr_float_supermax, spnb, tab_float_write_registersspnb);if (rc ! spnb){printf(Error modbus_write_registers(%d)\n, spnb);printf(Address%d,flnb%d\n, addr_float_supermax, spnb);nb_fail;}/*S7-1200浮点数据读取格式为dcba(100-200定义为float数据对应MD300-MD496float数据需要分配2*flnb的存储空间)最大读取125个字读取前50个浮点数据读取数据必须分两次读取*/rc modbus_read_registers(ctx,addr_float,flnb,tab_float_registers);//读取前50个浮点if (rc!flnb){printf(Error modbus_read_registersF(%d)\n, rc);printf(Address%d,nb%d\n, addr_float, flnb);nb_fail;}rc modbus_read_registers(ctx, addr_float_supermax, spnb, tab_float_registersspnb);//读取后50个浮点if (rc ! spnb){printf(error modbus_read_registersb(%d)\n, rc);printf(address%d,nb%d\n, addr_float_supermax, spnb);nb_fail;}else{for (int lst 0; lst flnb; lst){ dspmsg TRUE;read_float_registers[lst] modbus_get_float_dcba(tab_float_registerslst*2);rfloat read_float_registers[lst];//Sleep(1);::PostMessage(thHwnd-GetSafeHwnd(), WM_SHOUWDATAFROMSIEMENS,WPARAM(dspmsg),LPARAM(lst));dspmsg FALSE;}rfloat read_float_registers[0];strfloat.Format(_T(%.4f), rfloat);modbustcp-SetDlgItemText(IDC_EDITREADFLOAT,strfloat);strfloat.Format(_T(%.4f), read_float_registers[1]);modbustcp-SetDlgItemText(IDC_EDITFREADLOAT4, strfloat);strfloat.Format(_T(%.4f), read_float_registers[2]);modbustcp-SetDlgItemText(IDC_EDITREADFLOAT8, strfloat);}n;modbustcp-SetDlgItemInt(IDC_EDITCACULATE, n);}}}}else{printf(Connection Failed: %s\n, modbus_strerror(errno));AfxMessageBox(_T(ModbusServer Connect Failed!), MB_ICONINFORMATION);}n 0;modbustcp-SetDlgItemInt(IDC_EDITCACULATE, n);modbustcp-ModbusTcpThread NULL;sendmsg FALSE;dspmsg FALSE;modbuslock.Unlock();return 0; } 9、增加线程启动按钮在按钮中启动通信线程完成通信。此例程为Libmodbus和S7-1200通信测试例程写的比较早没有严格封装。S7-200 PLC 的程序做了严格封装后面在做介绍。 void CMFCApplicationMultiLineTestDlg::OnBnClickedButtonstart() {if (ModbusTcpThread NULL){ModbusThreadKiller FALSE;ModbusLoop FALSE;UpdateData(TRUE);sel m_select;SetDlgItemInt(IDC_EDITDSP,sel);UpdateData(FALSE);Sleep(50);ModbusTcpThread AfxBeginThread((AFX_THREADPROC)ModBusCommunication, this);}else{AfxMessageBox(_T(ModbusTCP通讯线程已启动无需重启!), MB_ICONINFORMATION);} } 10、启动MFC程序进行仿真。如下图所示。 11、在博图变量监控表中监控变量如下图所示。对比发现数据准确无误。 12、合信M226ES与LibModbus之间的通信。合信M226ESModbusTCP协议客户端不需要编写程序设置好IP地址即可端口默认502。下面是M226ES Modbus地址映射默认隐射。 13、下面为测试的相关视频。 C和S7-1200 Libmodbus 通信 开启你的Libmodbus之旅吧
http://www.tj-hxxt.cn/news/136646.html

相关文章:

  • 镇江建设网站的公司织梦网站做站群
  • 环保局网站建设 自查报告wordpress导航改哪个php文件
  • 做网站的经历网站备案审核通过后
  • 两学一做 专题网站职业生涯规划书模板
  • 做网站的人跑了网站可以恢复吗滕州手机网站建设
  • 网站开发速成班html网页设计logo代码
  • 遵义公司建网站要多少费用百度免费广告发布平台
  • 直播网站排名全媒体运营师培训费用
  • 有没有做网站网络营销推广方法ppt
  • 网站建设的前期投入一些网站只能在微信打开怎么做的
  • 佛山制作做网站哪个旅游网站规划好
  • 马克 扎克伯格大学做的网站百度关键词搜索广告的优缺点
  • 如何进行网页设计和网站制作网站建设这个职业是什么意思
  • 做网站page厦门小微企业网站建设补贴
  • 如何加强精神文明网站建设内容湖南百度seo
  • 电商网站的好处wordpress登录插件
  • 微网站网站模板建站自己做qq头像网站
  • 为网站网站做代理怎么判wordpress免费主题 开源
  • 网站开发产品经理招聘网站建设学习学校
  • 网站建化国内知名网站建设
  • 湖南响应式网站建设跨境电商一般卖哪些产品
  • 小型视频网站建设淄博张店整合网络推广
  • 宁波制作网站企业网站制作需求文档
  • python做网站设计公司常用网站开发软件
  • 做标书的视频网站如何做网站流量分析
  • 专业做互联网招聘的网站有哪些内容网址被禁止访问怎么办
  • 珠海网站建设哪个好薇网站建设公司营业执照图片
  • 国外学校网站模板国家标准下载网免费
  • 网站建设专家评审意见手机网站相册代码
  • 呈贡网站建设环保公司网站建设内容