1、演示效果

image-1658154119939

2、线程进行接口转接

后台线程进行接口读写操作,这样可以避免上层的应用层被调用导致阻塞,下面是关键类

(1)头文件

#pragma once
#include <QObject>
#include <QThread>

#include "BaseObject.h"
struct sModbusVal;
class cModbusObject : public cBaseObject
{
	Q_OBJECT

public:
	cModbusObject(QObject *parent = 0);
	~cModbusObject();

public:
	bool connect(sConnectData connectData) override;
	void quitRelease() override;
	bool isConnected() override;
	bool writeRegister(int nAddr, uint16_t nValue) override;
	int writeRegisters(int nAddr, int nCount, uint16_t *valueArray) override;
	bool readRegister(int nAddr, uint16_t &nValue) override;
	int readRegisters(int nAddr, int nCount, uint16_t *valueArray) override;
	int readCoilStatusBits(int nAddr, int nCount, uint8_t *valueArray) override;
	bool setBit(int nAddr, bool bState, eRegisterType nType, int nBit ) override;
	bool getBit(int nAddr, bool &bState, eRegisterType nType, int nBit) override;
	bool writeRegister32(int nAddr, uint32_t nValue)override;
	bool readRegister32(int nAddr, uint32_t &nValue)override;

private:
	sModbusVal *d_ptr;

};

(2)源文件

#include "ModbusObject.h"
#include "Include/modbus-version.h"
#include "Include/modbus.h"
#include "Include/config.h"
#include "Include/modbus-private.h"
#include "Include/modbus-rtu-private.h"
#include "Include/modbus-rtu.h"
#include "Include/modbus-tcp-private.h"
#include "Include/modbus-tcp.h"

#include <QDebug>
//#pragma comment(lib,"Libs/modbus.lib")
#pragma comment(lib,"modbus.lib")
#pragma execution_character_set("utf-8")
#define RETURN_ERROR   -1         // 返回错误值
#define MAX_RW_COUNT    1         // 读写的最大数量



struct sModbusVal
{
	modbus_t *ctx = nullptr; //	通讯指针
	bool bConnected = false;
};

cModbusObject::cModbusObject(QObject *parent)
	: cBaseObject(parent)
	, d_ptr(new sModbusVal)
{

}

cModbusObject::~cModbusObject()
{
	
}

// 连接
 bool cModbusObject::connect(sConnectData connectData)
 {
	 if (d_ptr->bConnected)
		 return true;

	 if (connectData.nType == CT_TYPE_TCP)
	 {
		 char *pChIp = nullptr;
		 QByteArray baIp = connectData.strTcpIp.toLatin1();
		 pChIp = baIp.data();
		 
		 d_ptr->ctx =  modbus_new_tcp((const char*)pChIp,connectData.nTcpPort);

		 // 设置Modbus超时时间
		 struct timeval tv;
		 tv.tv_sec = 0;
		 tv.tv_usec = 1000000;  //设置modbus超时时间为1000毫秒 
		 modbus_set_response_timeout(d_ptr->ctx, tv.tv_sec, tv.tv_usec);

		 //	设置站号
		 modbus_set_slave(d_ptr->ctx, connectData.nRtuSlave);

	 }
	 else if (connectData.nType == CT_TYPE_RTU)
	 {
		 QString strComNum = QString("COM%1").arg(connectData.nComNum);
		 char *pChCom = nullptr;
		 QByteArray baCom = strComNum.toLatin1();
		 pChCom = baCom.data();

		 char *pChParity = nullptr;
		 QByteArray baParity = connectData.strRtuParity.toLatin1();
		 pChParity = baParity.data();

		 //	创建通讯指针
		 d_ptr->ctx = modbus_new_rtu((const char*)pChCom, connectData.nRtuBaud, *pChParity, connectData.nRtuDataBit, connectData.nRtuStopBit);
		 
		 //	设置站号
		 modbus_set_slave(d_ptr->ctx, connectData.nRtuSlave);
	 }

	 //	建立连接
	 if (modbus_connect(d_ptr->ctx) == RETURN_ERROR)
	 {
		 modbus_free(d_ptr->ctx);
		 d_ptr->ctx = nullptr;
		 d_ptr->bConnected = false;

		 qDebug() << QObject::tr("Modbus 通讯连接失败!错误信息:%1").arg(modbus_strerror(errno)) << "\n";
	 }
	 else
	 {
		 //	连接成功
		 d_ptr->bConnected = true;
		 qDebug() << QObject::tr("Modbus 通讯连接成功!") << "\n";
	 }

	 return d_ptr->bConnected;
 }

// 是否连接
 bool cModbusObject::isConnected()
 {
	 return d_ptr->bConnected;
 }

// 资源释放,退出
 void cModbusObject::quitRelease()
 {
	 if (d_ptr->ctx != nullptr)
	 {
		 modbus_free(d_ptr->ctx);
		 d_ptr->ctx = nullptr;
	 }
 }

// 写寄存器值(单个)
 bool cModbusObject::writeRegister(int nAddr, uint16_t nValue)
 {
	 bool bRet = false;
	 if (!d_ptr->bConnected || nAddr < 0 )
		 return bRet;

	 if (modbus_write_registers(d_ptr->ctx, nAddr,(int)MAX_RW_COUNT,&nValue) != RETURN_ERROR)
		 bRet = true;
	 else
	 {
		 modbus_flush(d_ptr->ctx);
		qDebug() << QObject::tr("Modbus 寄存器写入错误:%1").arg(modbus_strerror(errno)) << "\n";
	 }
	 return bRet;
 }

// 写寄存器值(多个)
 int cModbusObject::writeRegisters(int nAddr, int nCount, uint16_t *valueArray)
 {
	 int nRet = 0;
	 if (!d_ptr->bConnected || nAddr < 0)
		 return nRet;

	 nRet = modbus_write_registers(d_ptr->ctx, nAddr, nCount, valueArray);

	 if (nRet == RETURN_ERROR)
	 {
		 modbus_flush(d_ptr->ctx);
		qDebug() << QObject::tr("Modbus 寄存器写入错误:%1").arg(modbus_strerror(errno)) << "\n";
	 }
	 return nRet;
 }

// 读寄存器值(单个)
 bool cModbusObject::readRegister(int nAddr, uint16_t &nValue)
 {
	 bool bRet = false;
	 if (!d_ptr->bConnected || nAddr < 0)
		 return bRet;

	 if (modbus_connect(d_ptr->ctx) == RETURN_ERROR)
	 {
		 qDebug() << QObject::tr("Modbus 通讯连接失败!错误信息:%1").arg(modbus_strerror(errno)) << "\n";
	 }

	 int nRCount = 0;
	 nRCount = modbus_read_registers(d_ptr->ctx, nAddr, (int)MAX_RW_COUNT, &nValue);
	 if (nRCount != RETURN_ERROR)
	 {
		 bRet = true;
	 }
	 else
	 {
		 qDebug() << QObject::tr("Modbus 寄存器:%1读取错误:%2").arg(nAddr).arg(modbus_strerror(errno)) << "\n";
		 //modbus_flush(d_ptr->ctx);
	 }

	 return bRet;
 }

// 读寄存器值(多个)
 int cModbusObject::readRegisters(int nAddr, int nCount, uint16_t *valueArray)
 {
	 if (modbus_connect(d_ptr->ctx) == RETURN_ERROR)
	 {
		 qDebug() << QObject::tr("Modbus 通讯连接失败!错误信息:%1").arg(modbus_strerror(errno)) << "\n";
	 }
	 int nRet = 0;
	  nRet = modbus_read_registers(d_ptr->ctx, (int)nAddr, (int)nCount, valueArray);
	 if (nRet < 0)
	 {
		 modbus_flush(d_ptr->ctx);
		qDebug() << QObject::tr("Modbus 寄存器:%1 数量:%2 读取错误:%3").arg(nAddr).arg(nCount).arg(modbus_strerror(errno)) << "\n";
	 }

	 return  nRet;
 }

// 读线圈值(多个)
 int cModbusObject::readCoilStatusBits(int nAddr, int nCount, uint8_t *valueArray)
 {
	 int nRet = 0;
	 nRet = modbus_read_bits(d_ptr->ctx, (int)nAddr, (int)nCount, valueArray);
	 if (nRet < 0)
	 {
		 modbus_flush(d_ptr->ctx);
	 }
	 return nRet;
 }

// 设置位状态
 bool cModbusObject::setBit(int nAddr, bool bState, eRegisterType nType, int nBit)
 {
	 bool bRet = false;
	 if (!d_ptr->bConnected ||nAddr < 0|| nBit < 0)
		 return bRet;

	 if (nType == RT_D_READ_HOLDING_REGISTERS)
	 {
		 uint16_t nValue = 0;
		 if (!readRegister(nAddr, nValue))
			 bRet = false;
		 else
		 {
			 if (bState)
				 nValue |= (1 << (nBit % 16));
			 else
				 nValue &= ~(1 << (nBit % 16));

			 bRet = writeRegister(nAddr, nValue);
		 }
	 }
	 else if (nType == RT_M_COIL_STATUS)
	 {
		 uint8_t nBitWrite = bState ? 1 : 0;
		 if (modbus_write_bits(d_ptr->ctx,nAddr, MAX_RW_COUNT,&nBitWrite) != RETURN_ERROR)
			 bRet = true;
		 else
		 {
			 modbus_flush(d_ptr->ctx);
			 qDebug() << QObject::tr("Modbus 寄存器位写入错误:%1").arg(modbus_strerror(errno)) << "\n";
		 }

	 }

	 return bRet;
 }

// 读取位状态
 bool cModbusObject::getBit(int nAddr, bool &bState, eRegisterType nType, int nBit)
 {
	 bool bRet = false;
	 if (!d_ptr->bConnected || nAddr < 0 || nBit < 0)
		 return bRet;

	 if (nType == RT_D_READ_HOLDING_REGISTERS)
	 {
		 uint16_t nValue = 0;
		 if (!readRegister(nAddr, nValue))
			 bRet = false;
		 else
		 {
			 bRet = true;
			 bState = (nValue & (1 << (nBit % 16))) > 0?true:false;
		 }
	 }
	 else if (nType == RT_M_COIL_STATUS)
	 {
		 uint8_t nBitRead = 0;
		 if (modbus_read_bits(d_ptr->ctx, nAddr, MAX_RW_COUNT, &nBitRead) != RETURN_ERROR)
			 bRet = true;
		 else
		 {
			 modbus_flush(d_ptr->ctx);
			 qDebug() << QObject::tr("Modbus 寄存器位读取错误:%1").arg(modbus_strerror(errno)) << "\n";
		 }
		 bState = (nBitRead == 1 ? true : false);
	 }

	 return bRet;
 }

 bool cModbusObject::writeRegister32(int nAddr, uint32_t nValue)
 {
	 bool bRet = false;
	 if (!d_ptr->bConnected || nAddr < 0)
		 return bRet;

	 uint16_t u16Data[2];
	 u16Data[0] = nValue & 0Xffff;
	 u16Data[1] = (nValue >> 16) & 0Xffff;

	 int nR = modbus_write_registers(d_ptr->ctx, nAddr, 2, u16Data);
	 if (nR < 0)
	 {
		 qDebug() << QObject::tr("writeRegister32 寄存器写入错误:%1").arg(modbus_strerror(errno)) << "\n";
		 modbus_flush(d_ptr->ctx);
	 }
	 else
		 bRet = true;

	
	 return bRet;
 }

 bool cModbusObject::readRegister32(int nAddr, uint32_t &nValue)
 {
	 bool bRet = false;
	 if (!d_ptr->bConnected || nAddr < 0)
		 return bRet;

	 uint16_t u16Data[2];
	 memset(u16Data, 0, sizeof(u16Data));
	 int nR = readRegisters(nAddr, 2, u16Data);
	 nValue = u16Data[0] | (u16Data[1] << 16);
	 if (nR < 0)
	 {
		 //QThread::msleep(30);
		 qDebug() << QObject::tr("readRegister32 寄存器读取错误:%1").arg(modbus_strerror(errno)) << "\n";
		 //modbus_flush(d_ptr->ctx);
	 }
	 else
		 bRet = true;

	 return bRet;
 }

3、程序下载
https://download.csdn.net/download/u013083044/85402497

打赏
支付宝 微信
上一篇 下一篇