191 lines
5.7 KiB
C++
191 lines
5.7 KiB
C++
#include "modbuscontroller.h"
|
||
|
||
#define _DEBUG_VSPD_
|
||
|
||
ModbusController::ModbusController():m_pModbusMaster(nullptr), m_pSettings(nullptr)
|
||
{
|
||
m_version= "1.0.0";
|
||
m_modbus_type = 1;
|
||
m_modbus_ip = "127.0.0.1";
|
||
m_modbus_port = 502;
|
||
m_modbus_com = "COM1";
|
||
m_modbus_baund = 9600;
|
||
m_modbus_data = 1;
|
||
m_modbus_parity = 0;
|
||
m_modbus_stop = 1;
|
||
}
|
||
|
||
ModbusController::~ModbusController()
|
||
{
|
||
if (m_pSettings!=nullptr)
|
||
{
|
||
delete m_pSettings;
|
||
m_pSettings = nullptr;
|
||
}
|
||
|
||
for (SlaveData* ptr : m_slaves)
|
||
{
|
||
delete ptr;
|
||
ptr = nullptr;
|
||
}
|
||
|
||
m_slaves.clear();
|
||
m_slaves.squeeze();
|
||
|
||
if (m_pModbusMaster != nullptr)
|
||
{
|
||
m_pModbusMaster->disconnectDevice();
|
||
delete m_pModbusMaster;
|
||
m_pModbusMaster = nullptr;
|
||
}
|
||
}
|
||
|
||
void ModbusController::getConfiguration(QString iniFilePath)
|
||
{
|
||
m_pSettings = new QSettings(iniFilePath, QSettings::IniFormat);
|
||
|
||
m_version = m_pSettings->value("general/ver").toString();
|
||
m_modbus_type = m_pSettings->value("modbus/type").toInt();
|
||
|
||
m_modbus_ip = m_pSettings->value("modbus/ip").toString();
|
||
m_modbus_port = m_pSettings->value("modbus/port").toInt();
|
||
|
||
m_modbus_com = m_pSettings->value("modbus/com").toString();
|
||
m_modbus_baund = m_pSettings->value("modbus/baund").toInt();
|
||
m_modbus_data = m_pSettings->value("modbus/data").toInt();
|
||
m_modbus_parity = m_pSettings->value("modbus/parity").toInt();
|
||
m_modbus_stop = m_pSettings->value("modbus/stop").toInt();
|
||
|
||
QStringList slaves_list = m_pSettings->value("slaves/slave_id").toString().split(":", Qt::SkipEmptyParts);
|
||
|
||
int slave_id = 0;
|
||
foreach (const QString &str, slaves_list)
|
||
{
|
||
QString app = QString("slave_%1/function_code_counts").arg(slave_id);
|
||
|
||
int functions_count = m_pSettings->value(app).toInt();
|
||
for(int i=0; i<functions_count; i++)
|
||
{
|
||
QString app2 = QString("slave_%1_function_%2").arg(slave_id).arg(i);
|
||
|
||
#ifndef _DEBUG_VSPD_
|
||
unsigned short equipmentCode = m_pSettings->value(app2 + "/equipment_code").toInt();
|
||
equipmentCode = equipmentCode << 9;
|
||
equipmentCode &= 0xFE00; // 二进制掩码: 1111 1110 0000 0000(保留高7位)
|
||
|
||
QStringList sn_list = m_pSettings->value(app2 + "/serial_number").toString().split(":", Qt::SkipEmptyParts);
|
||
QStringList quantity_list = m_pSettings->value(app2 + "/read_quantity").toString().split(":", Qt::SkipEmptyParts);
|
||
|
||
assert(sn_list.size() == quantity_list.size());
|
||
|
||
int j = 0;
|
||
foreach(const QString sn, sn_list)
|
||
{
|
||
SlaveData* pSlaveData = new SlaveData();
|
||
pSlaveData->id = str.toInt();
|
||
pSlaveData->function_code = m_pSettings->value(app2 + "/function_code").toInt();
|
||
pSlaveData->interval = m_pSettings->value(app2 + "/interval").toInt();
|
||
|
||
|
||
unsigned short serialNumber = sn.toInt();
|
||
|
||
serialNumber &= 0x01FF; // 二进制掩码: 0000 0001 1111 1111(保留低9位)
|
||
|
||
// 组合操作:高7位左移9位,低9位直接填充
|
||
unsigned short address = pSlaveData->start_address = (equipmentCode ) | serialNumber; // 关键位操作
|
||
|
||
pSlaveData->start_address = address;
|
||
pSlaveData->quantity = quantity_list.at(j).toInt();
|
||
m_slaves.push_back(pSlaveData);
|
||
j++;
|
||
}
|
||
#else
|
||
SlaveData* pSlaveData = new SlaveData();
|
||
pSlaveData->id = str.toInt();
|
||
pSlaveData->function_code = m_pSettings->value(app2 + "/function_code").toInt();
|
||
pSlaveData->interval = m_pSettings->value(app2 + "/interval").toInt();
|
||
pSlaveData->quantity = m_pSettings->value(app2 + "/quantity").toInt();
|
||
pSlaveData->start_address = m_pSettings->value(app2 + "/start_addr").toInt();
|
||
m_slaves.push_back(pSlaveData);
|
||
#endif
|
||
}
|
||
|
||
slave_id++;
|
||
}
|
||
}
|
||
|
||
bool ModbusController::Open()
|
||
{
|
||
if (m_modbus_type == 1)
|
||
{
|
||
return modbus_rtu();
|
||
}
|
||
else
|
||
{
|
||
return modbus_tcp();
|
||
}
|
||
}
|
||
|
||
bool ModbusController::modbus_rtu()
|
||
{
|
||
m_pModbusMaster = new QModbusRtuSerialClient();
|
||
m_pModbusMaster->setConnectionParameter(QModbusDevice::SerialPortNameParameter, m_modbus_com); //串口号
|
||
m_pModbusMaster->setConnectionParameter(QModbusDevice::SerialBaudRateParameter, m_modbus_baund); //波特率
|
||
m_pModbusMaster->setConnectionParameter(QModbusDevice::SerialParityParameter, m_modbus_parity); //无校验
|
||
m_pModbusMaster->setConnectionParameter(QModbusDevice::SerialDataBitsParameter, m_modbus_data); //数据位
|
||
m_pModbusMaster->setConnectionParameter(QModbusDevice::SerialStopBitsParameter, m_modbus_stop); //停止位
|
||
m_pModbusMaster->setTimeout(1000); // 设置超时2秒
|
||
|
||
return m_pModbusMaster->connectDevice();
|
||
}
|
||
|
||
bool ModbusController::modbus_tcp()
|
||
{
|
||
return false;
|
||
}
|
||
|
||
bool ModbusController::Read()
|
||
{
|
||
//对每一个从机进行操作
|
||
for( SlaveData* sd : m_slaves)
|
||
{
|
||
//定义读写单元
|
||
QModbusDataUnit readUnit(QModbusDataUnit::HoldingRegisters, sd->start_address, sd->quantity);
|
||
//发送请求
|
||
auto* reply = m_pModbusMaster->sendReadRequest(readUnit, sd->id);
|
||
if (reply)
|
||
{
|
||
connect(reply, &QModbusReply::finished, this, &ModbusController::readRegisters);
|
||
}
|
||
}
|
||
|
||
return true;
|
||
}
|
||
|
||
void ModbusController::readRegisters()
|
||
{
|
||
//接收信号
|
||
auto reply = qobject_cast<QModbusReply*>(sender());
|
||
if (!reply)
|
||
{
|
||
qDebug() << "无效回复";
|
||
return;
|
||
}
|
||
//处理响应
|
||
const QModbusDataUnit unit = reply->result();
|
||
// 将数据值转换为字符串
|
||
QString dataStr;
|
||
for (int i = 0; i < unit.valueCount(); ++i)
|
||
{
|
||
dataStr += QString::number(unit.value(i)) + " ";
|
||
}
|
||
if (dataStr.size() != 0)
|
||
{
|
||
qDebug() << "读取成功";
|
||
qDebug() << dataStr;
|
||
}
|
||
else
|
||
{
|
||
qDebug() << "无数据";
|
||
}
|
||
} |