1.Qt中几个常用的串口modbus类
QModbusRtuSerialSlave //modbus串口通信方式下的服务器类
QModbusRtuSerialMaster //串口通信方式下的客户端类
QModbusServer // QModbusServer类接收和处理modbus的请求。
QModbusDataUnit //存储接收和发送数据的类,数据类型为1bit和16bit
QModbusReply //客户端访问服务器后得到的回复(如客户端读服务器数据时包含数据信息)
2.modbusMaster发送数据代码流程
3.部分代码及注释
void modbusMaster::on_connectButton_clicked()//连接按钮点击槽方法
{
if (!modbusDevice)
return;
statusBar()->clearMessage();
QString comPortName = ui->lineEdit->text();
if (modbusDevice->state() != QModbusDevice::ConnectedState) {//如果处在非连接状态,进行连接
//进行串口连接
modbusDevice->setConnectionParameter(QModbusDevice::SerialPortNameParameter,
comPortName);//获取串口端口,下面设置各种参数
modbusDevice->setConnectionParameter(QModbusDevice::SerialParityParameter,
QSerialPort::EvenParity);//偶较验
modbusDevice->setConnectionParameter(QModbusDevice::SerialBaudRateParameter,
QSerialPort::Baud19200);//波特率为19200
modbusDevice->setConnectionParameter(QModbusDevice::SerialDataBitsParameter,
QSerialPort::Data8);//数据位为8位
modbusDevice->setConnectionParameter(QModbusDevice::SerialStopBitsParameter,
QSerialPort::OneStop);//停止位为1位
modbusDevice->setTimeout(1000);//连接超时1S
modbusDevice->setNumberOfRetries(3);//连接失败重试三次连接
if (!modbusDevice->connectDevice()) {
statusBar()->showMessage(tr("Connect failed: ") + modbusDevice->errorString(), 5000);
}
}else{//处在连接状态进行断开连接的操作
modbusDevice->disconnectDevice();
}
}
void modbusMaster::on_sendButton_clicked()
{
if (!modbusDevice)//如果设备没有被创建就返回
return;
QString strDis;
QString str1 = ui->textEdit->toPlainText();
qDebug()<
//qDebug()<
statusBar()->clearMessage();//清除状态栏显示的信息
QModbusDataUnit writeUnit(QModbusDataUnit::HoldingRegisters,0,10);//发送的数据信息(数据类型 ,起始地址,个数)
// QModbusDataUnit::RegisterType table = writeUnit.registerType();//得到寄存器类型传给table
for (uint i = 0; i < writeUnit.valueCount(); i++) {
int j = 2*i;
QString st = str3.mid (j,2);
bool ok;
int hex =st.toInt(&ok,16);//将textedit中读取到的数据转换为16进制发送
qDebug()<
}
if (auto *reply = modbusDevice->sendWriteRequest(writeUnit, 1)) {// 1是server address sendWriteRequest是向服务器写数据
if (!reply->isFinished()) { //reply Returns true when the reply has finished or was aborted.
connect(reply, &QModbusReply::finished, this, [this, reply]() {
if (reply->error() == QModbusDevice::ProtocolError) {
statusBar()->showMessage(tr("Write response error: %1 (Mobus exception: 0x%2)")
.arg(reply->errorString()).arg(reply->rawResult().exceptionCode(), -1, 16),
5000);
} else if (reply->error() != QModbusDevice::NoError) {
statusBar()->showMessage(tr("Write response error: %1 (code: 0x%2)").
arg(reply->errorString()).arg(reply->error(), -1, 16), 5000);
}
reply->deleteLater();
});
} else {
// broadcast replies return immediately
reply->deleteLater();
}
} else {
statusBar()->showMessage(tr("Write error: ") + modbusDevice->errorString(), 5000);
}
}
void modbusMaster::on_readButton_clicked()//从服务器读数据的读按钮槽方法
{
if (!modbusDevice)
return;
statusBar()->clearMessage();
QModbusDataUnit readUnit(QModbusDataUnit::HoldingRegisters,0,10);
if (auto *reply = modbusDevice->sendReadRequest(readUnit, 1)) {
if (!reply->isFinished())
connect(reply, &QModbusReply::finished, this, &modbusMaster::readReady);
else
delete reply; // broadcast replies return immediately
} else {
statusBar()->showMessage(tr("Read error: ") + modbusDevice->errorString(), 5000);
}
}
void modbusMaster::readReady()//在这里读的数据
{
auto reply = qobject_cast
if (!reply)
return;
//数据从QModbusReply这个类的resuil方法中获取,也就是本程序中的reply->result()
if (reply->error() == QModbusDevice::NoError) {
const QModbusDataUnit unit = reply->result();
for (uint i = 0; i < unit.valueCount(); i++) {
const QString entry = tr("Address: %1, Value: %2").arg(unit.startAddress())
.arg(QString::number(unit.value(i),
unit.registerType() <= QModbusDataUnit::Coils ? 10 : 16));
ui->textEdit_2->append(entry);
}
} else if (reply->error() == QModbusDevice::ProtocolError) {
statusBar()->showMessage(tr("Read response error: %1 (Mobus exception: 0x%2)").
arg(reply->errorString()).
arg(reply->rawResult().exceptionCode(), -1, 16), 5000);
} else {
statusBar()->showMessage(tr("Read response error: %1 (code: 0x%2)").
arg(reply->errorString()).
arg(reply->error(), -1, 16), 5000);
}
reply->deleteLater();
}
程序效果如图所示
4.modbusSlave接收数据代码流程
5.slave数据部分代码及注释
modbusSlave::modbusSlave(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::modbusSlave)
{
ui->setupUi(this);
modbusDevice = new QModbusRtuSerialSlave(this);
QModbusDataUnitMap reg;//设置可接收的寄存器数据类型
reg.insert(QModbusDataUnit::Coils, { QModbusDataUnit::Coils, 0, 10 });//
reg.insert(QModbusDataUnit::DiscreteInputs, { QModbusDataUnit::DiscreteInputs, 0, 10 });
reg.insert(QModbusDataUnit::InputRegisters, { QModbusDataUnit::InputRegisters, 0, 10 });
reg.insert(QModbusDataUnit::HoldingRegisters, { QModbusDataUnit::HoldingRegisters, 0, 10 });
modbusDevice->setMap(reg);//
connect(modbusDevice, &QModbusServer::stateChanged,
this, &modbusSlave::onStateChanged);//连接状态发生改变时改变connect按钮上的显示文字(connect or discennect)
connect(modbusDevice, &QModbusServer::dataWritten,
this, &modbusSlave::updateWidgets);//modbus客户端向服务器写入数据时dataWritten信号被触发
connect(modbusDevice, &QModbusServer::errorOccurred,
this, &modbusSlave::handleDeviceError);
}
void modbusSlave::updateWidgets(QModbusDataUnit::RegisterType table, int address, int size)//dataWriten信号被处发后,得到数据做出显示
{
for (int i = 0; i < size; ++i) {
quint16 value;
switch (table) {
case QModbusDataUnit::Coils:
modbusDevice->data(QModbusDataUnit::Coils, address + i, &value);
qDebug()<
case QModbusDataUnit::HoldingRegisters:
modbusDevice->data(QModbusDataUnit::HoldingRegisters, address + i, &value);//得到数据后做出显示
qDebug()<
default:
break;
}
QString s = QString::number(value, 16);
qDebug("%d",value);
ui->textEdit->append(s);
}
}
程序运行效果
总体效果图
完整程序地址:http://download.csdn.net/detail/maowendi/9598219