1、演示效果
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
打赏