vs+Qt+modbus学习记录

前言

       QtserialBus下提供了访问工业串行总线和协议的类和函数,包括CAN和Modbus等。Modbus的一些类如下:

 Modbus协议物理层接口有RS232和RS485串行接口和以太网接口,使用网口通讯主要使用QModbusTcpClient(Modbus客户端设备的接口类)和QModbusTcpServer(TCP服务器与Modbus客户端进行通讯的Modbus服务器)。

上位机主站的实现

(1)创建modbusTCPclient对象指针QModbusTcpClient *  myClient;并将其创建在堆上,添加到QT的对象数中,这是一个用于发送各种请求的对象,比如读和写。以下将其统称为客户端。

(2)通过TCP/IP进行连接:客户端的连接状态有四个状态,分别为:UnconnectedState (0)、ConnectingState(1)、ConnectedState(2)、ClosingState(3).可以判断状态未连接时进行连接。设置其连接相关参数:

myClient->setConnectionParameter(QModbusDevice::NetworkAddressParameter, “127.0.0.0”);
myClient->setConnectionParameter(QModbusDevice::NetworkPortParameter, 502);

myClient->setTimeout(500);//超时时间内没有相应,则设置TimeoutError
myClient->setNumberOfRetries(3);//请求失败前客户端执行重试的次数
myClient->connectDevice()//连接设备

        连接这里需要注意的问题是connectDevice()执行时会在另外一个线程中进行连接,因此需要另外写一个槽函数用于判断设备的连接状态。官方提供了一个stateChanged的信号,状态改变后在槽函数中判断设备是否连接。

(3)写操作:对modbus设备进行写操作时,需要使用QModbusDataUnit类来存储一些信息,包括写入寄存器的类型,写入数据的起始地址,写入数据的个数。创建该容器的方式如下,其中注意参数所需要的类型。创建完容器对象后,使用函数setValue()来将信息写入到modbus设备中。

QModbusDataUnit writeUnit = QModbusDataUnit(QModbusDataUnit::Coils, starAddress, numberOfwrite);
writeUnit .setValue(index,value);

此时还需要给设备发送写入的请求,当请求成功时会返回一个有效的QModbusReply的对象指针,否则返回nullptr。

QModbusReply* reply = myClient->sendWriteRequest(writeUnit, server_Address)

可以判断reply的状态进行后续的操作。

(4)读操作:与写操作对应,首先使用QModbusDataUnit类来存储所读寄存器的类型,读取数据的起始地址,读取数据的个数等信息。然后发送读取数据的请求,根据请求的返回QModbusReply对象指针来进行后续操作。

QModbusDataUnit readUnit(QModbusDataUnit::Coils, startAddress, numberOfRead);
QModbusReply *reply = myClient->sendReadRequest(readUnit, server_Address)

与写操作不同的是,读取请求发送后,需要根据响应的状态然后进行读取数据的存储。官方提供了响应完成的信号QModbusReply::finished,此时自己再实现读取数据的槽函数。

connect(reply, &QModbusReply::finished, [=](){
    if (reply->error() == QModbusDevice::NoError)
	{
		//处理成功返回的数据
		const QModbusDataUnit unit = reply->result();
		quint16 res = unit.value(0);  //读取第一位的数据
		appendMsg("读取结果" + QString::number(res));
	}
	else
	{
	    QString error = QString::fromLocal8Bit("Read response error: %1 (code: 0x%2)").arg(reply->errorString()).arg(reply->error(), -1, 16);
	    appendMsg(error);
	}
	reply->deleteLater();
});

代码有自己实现的接口,具体内容自己调整。

(5)自己调试过程需要的问题总结

第一点,在连接PLC的时候不要自己另外开线程,会导致设置连接后自己线程没有退出,与连接自带的线程隔离,无法判断是否连接成功。

第二点,写入和读取寄存器对应地址的数据时,要判断该寄存器地址是否是可读可写的,我在调试过程中使用了一个只读的寄存器地址,让我以为写入数据的程序有问题,白调整了几个小时。。。另外,最近在做项目自学很多东西都会在此更新,有兴趣的欢迎关注,一同交流学习。

最后多使用QT帮助文档,太好的东西!

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值