C++客户端Modbus通信(TCP主站)

本文介绍了在Qt中使用C++进行modbus通信的步骤,包括配置环境、建立TCP连接、设置slave、读写数据等关键操作。由于Qt自带的QModbus在创建线程时存在问题,作者选择了qtmodbus库来实现。文中详细阐述了modbus通信的每个阶段,并给出了具体的代码示例。
摘要由CSDN通过智能技术生成

本文简单介绍Qt使用外部modbus通信C++编程流程
modbus中文手册:https://blog.csdn.net/qq_23670601/article/details/82155378
Qtmodbus较为方便,建议无特殊情况可以使用qtmodbus,为何不使用Qt自带QModbus呢?原因是我在编写modbus主站的时候需要创建一个线程监听从站的数据,创建线程的时候出现为不同线程的父线程创建子线程的报错,个人解决不了。

modbus通信编程流程

1.搭建modbus环境
在pro工程项目中添加头文件所在路径,lib库

2.建立连接

//创建modbus对象
modbus_t  *modbus;
//建立tcp连接
modbus = modbus_new_tcp(ip地址,端口号);
//设置slave
int  ret  =  modbus_set_slave(modbus,slave号);//错误返回-1,正确返回0;
//进行连接
ret = modbus_connect(modbus);//错误返回-1,正确返回0;
//设置响应延迟,第三个参数是最迟的时间,1000为1ms不是1s;
ret = modbus_response_timeout(modbus,0,900000);

中文操作手册上并没有找到设置slave的,但是这个确实要设置,不然只能连接不可以通信只是我没有找到,可能不是很细心,slave一般设置为1,市面上的modbus调试工具上面可以查看

3.接收/发送数据

//读数据
ret  = modbus_read_registers(modbus,起始地址,数据个数,存储的容器);//读取的数据存储在容器中,错误返回-1
//写数据
ret = modbus_write_registers(modbus,起始地址,数据个数,存储的容器);//将容器的数据依次写入寄存器
可以通过封装modbus库的函数和数据结构来实现C++中的Modbus TCP客户端和服务端。以下是一个简单的示例代码,其中包含了客户端和服务端的封装实现: ```cpp #include <modbus/modbus.h> #include <stdexcept> class ModbusTcpClient { public: ModbusTcpClient(const std::string& ip, int port, int slave_id = 1) { ctx_ = modbus_new_tcp(ip.c_str(), port); if (!ctx_) { throw std::runtime_error("Failed to create Modbus context"); } modbus_set_slave(ctx_, slave_id); if (modbus_connect(ctx_) == -1) { throw std::runtime_error("Failed to connect to Modbus server"); } } ~ModbusTcpClient() { modbus_close(ctx_); modbus_free(ctx_); } void read_registers(int addr, int nb, uint16_t* dest) { if (modbus_read_registers(ctx_, addr, nb, dest) == -1) { throw std::runtime_error("Failed to read Modbus registers"); } } void write_registers(int addr, int nb, const uint16_t* src) { if (modbus_write_registers(ctx_, addr, nb, src) == -1) { throw std::runtime_error("Failed to write Modbus registers"); } } private: modbus_t* ctx_; }; class ModbusTcpServer { public: ModbusTcpServer(int port, int slave_id = 1) { ctx_ = modbus_new_tcp("0.0.0.0", port); if (!ctx_) { throw std::runtime_error("Failed to create Modbus context"); } modbus_set_slave(ctx_, slave_id); mapping_ = modbus_mapping_new(10, 10, 10, 10); if (!mapping_) { throw std::runtime_error("Failed to create Modbus mapping"); } if (modbus_tcp_listen(ctx_, 1) == -1) { throw std::runtime_error("Failed to listen for Modbus TCP connections"); } modbus_tcp_accept(ctx_, &client_); } ~ModbusTcpServer() { modbus_mapping_free(mapping_); modbus_close(client_); modbus_close(ctx_); modbus_free(client_); modbus_free(ctx_); } void run() { while (true) { uint8_t query[MODBUS_TCP_MAX_ADU_LENGTH]; int rc = modbus_receive(client_, query); if (rc > 0) { uint16_t addr, nb; modbus_get_header(client_, query, &addr, MODBUS_FC_READ_HOLDING_REGISTERS, &nb); if (nb > MODBUS_MAX_READ_REGISTERS) { nb = MODBUS_MAX_READ_REGISTERS; } modbus_reply(client_, query, rc, mapping_->tab_registers + addr, nb); } else if (rc == -1) { modbus_close(client_); modbus_tcp_accept(ctx_, &client_); } } } private: modbus_t* ctx_; modbus_t* client_; modbus_mapping_t* mapping_; }; int main() { // 启动服务端 ModbusTcpServer server(502); std::thread server_thread([&server](){ server.run(); }); server_thread.detach(); // 启动客户端 ModbusTcpClient client("127.0.0.1", 502); uint16_t read_data[10]; uint16_t write_data[10] = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10}; client.write_registers(0, 10, write_data); client.read_registers(0, 10, read_data); return 0; } ``` 通过封装后,使用起来更加方便,同时也更加安全和稳定。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值