modbus学习第5天
今天用Qt实现一个可以通过modbus对线圈寄存器--读写单个寄存器和多个寄存器,离散寄存器--读单个和多个寄存器,保持寄存器--读写单个寄存器和多个寄存器,输入寄存器--读单个和多个寄存器的功能,大概是这么个效果,ui设计好了

用单例模式设计了一个ModbusMaster的类用于连接从站设备以及对从站设备的读写,防止ui更新和读取数据冲突造成卡顿,用了多线程,今天完成了主站设备和从站设备的连接,明天再完成主站设备对从站设备的读写,整个小程序功能比较单一就不用git管理了
点击查看代码
点击查看代码
#include "ModbusMaster.h"
Q_GLOBAL_STATIC(ModbusMaster, theInstance);
ModbusMaster::ModbusMaster(QObject *parent)
: QObject(parent), m_isConnect(false), m_modbusCtx(nullptr)
{
}
ModbusMaster::~ModbusMaster()
{
this->disconnectSlave();
if (m_modbusCtx != nullptr)
{
modbus_free(m_modbusCtx);
m_modbusCtx = nullptr;
}
}
//获取单例对象
ModbusMaster * ModbusMaster::getInstance()
{
return theInstance;
}
//初始化RTU
bool ModbusMaster::initRtu(const QString & portName, int baudRate, char parity, int dataBits, int stopBits)
{
QMutexLocker locker(&this->m_mutex);
if (this->m_modbusCtx != nullptr)
{
modbus_free(this->m_modbusCtx);
this->m_modbusCtx = nullptr;
}
//创建modbus的RTU
this->m_modbusCtx = modbus_new_rtu(portName.toLocal8Bit().data(), baudRate, parity, dataBits, stopBits);
if (this->m_modbusCtx == nullptr)
{
QMessageBox::information(nullptr, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("初始化RTU失败"));
return false;
}
modbus_set_response_timeout(this->m_modbusCtx, 3, 0);//设置超时3s
QMessageBox::information(nullptr, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("初始化RTU成功"));
return true;
}
//连接串口
bool ModbusMaster::connectSlave()
{
QMutexLocker locker(&this->m_mutex);
if (this->m_modbusCtx == nullptr)
{
QMessageBox::information(nullptr, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("未初始化RTU"));
return false;
}
if (this->m_isConnect)
{
qDebug() << "已连接从站,不需要再次连接";
return true;
}
int ret = modbus_connect(this->m_modbusCtx);//串口打开了,没有被占用
if (ret == -1)
{
QMessageBox::information(nullptr, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("串口打开失败"));
return false;
}
this->m_isConnect = true;
return true;
}
//设置从站地址
void ModbusMaster::setSlaveId(int slaveId)
{
QMutexLocker locker(&this->m_mutex);
if (this->m_modbusCtx != nullptr)
{
modbus_set_slave(this->m_modbusCtx, slaveId);
qDebug() << "从站地址为" << slaveId;
uint16_t testData[1] = { 0 };
// 读地址0的保持寄存器(功能码03),需和从站模拟器配置的地址匹配
int readRet = modbus_read_registers(m_modbusCtx, 0, 1, testData);
if (readRet == -1)
{
QString errMsg = QString::fromLocal8Bit("串口已打开,但从站(ID=%1)无响应:%2")
.arg(slaveId).arg(modbus_strerror(errno));
QMessageBox::warning(nullptr, QString::fromLocal8Bit("提示"), errMsg);
// 串口已打开,需关闭
modbus_close(this->m_modbusCtx);
this->m_isConnect = false;
return;
}
}
else
{
QMessageBox::information(nullptr, QString::fromLocal8Bit("提示"), QString::fromLocal8Bit("未初始化RTU"));
}
}
//断开连接
void ModbusMaster::disconnectSlave()
{
QMutexLocker locker(&this->m_mutex);
if ((this->m_modbusCtx == nullptr) && this->m_isConnect)
{
QMessageBox::information(nullptr, QString::fromLocal8Bit("提示"),
QString::fromLocal8Bit("初始化失败,无法断开连接"));
return;
}
modbus_close(this->m_modbusCtx);
this->m_isConnect = false;
QMessageBox::information(nullptr, QString::fromLocal8Bit("提示"),
QString::fromLocal8Bit("已断开"));
}
浙公网安备 33010602011771号