diff --git a/crc.cpp b/crc.cpp index 155bbe1..00f9a72 100644 --- a/crc.cpp +++ b/crc.cpp @@ -1,6 +1,6 @@ #include "crc.h" -quint16 calculateCrc(const QByteArray &data) +quint16 CalculateCrc(const QByteArray &data) { quint16 crc = 0xFFFF; // MODBUS初始值 const quint16 polynomial = 0xA001; // MODBUS多项式(0x8005的反转) @@ -22,3 +22,33 @@ quint16 calculateCrc(const QByteArray &data) } return crc; } + +bool CrcCheck(const QByteArray &data) +{ + //首先对接收报文的长度进行检验 + if (data.size() < 3) + { + return false; + } + //对接收的报文进行CRC校验 + QByteArray payload = data.left(data.length() - 2); + + //分离接收值的crc校验位 + quint8 receivedCrcLow = static_cast(data.at(data.length() - 2)); + quint8 receivedCrcHigh = static_cast(data.at(data.length() - 1)); + + //计算返回的报文的crc + quint16 crc = CalculateCrc(payload); + quint8 calcCrcLow = crc & 0xFF; + quint8 calcCrcHigh = (crc >> 8) & 0xFF; + + //比较计算的crc值和接收到的crc值是否一致 + if(calcCrcLow == receivedCrcLow && calcCrcHigh == receivedCrcHigh) + { + return true; + } + else + { + return false; + } +} diff --git a/crc.h b/crc.h index 621871e..2cf4052 100644 --- a/crc.h +++ b/crc.h @@ -5,4 +5,5 @@ #include #include -quint16 calculateCrc(const QByteArray &data); +quint16 CalculateCrc(const QByteArray &data); +bool CrcCheck(const QByteArray &data); diff --git a/modbus.pro b/modbus.pro index c6e6268..1425b43 100644 --- a/modbus.pro +++ b/modbus.pro @@ -15,9 +15,11 @@ TEMPLATE = app SOURCES += main.cpp\ widget.cpp \ - crc.cpp + crc.cpp \ + mymodbus.cpp HEADERS += widget.h \ - crc.h + crc.h \ + mymodbus.h FORMS += widget.ui diff --git a/modbus.pro.user b/modbus.pro.user index 7a92d7f..008fb78 100644 --- a/modbus.pro.user +++ b/modbus.pro.user @@ -1,6 +1,6 @@ - + EnvironmentId diff --git a/mymodbus.cpp b/mymodbus.cpp new file mode 100644 index 0000000..dc0b593 --- /dev/null +++ b/mymodbus.cpp @@ -0,0 +1,200 @@ +#include "mymodbus.h" + + +MyModbus::MyModbus() +{ +} + +void MyModbus::Set(quint16 stationAddress, quint16 functionCode, quint16 startAdress, quint16 length) +{ + this->stationAddress = stationAddress; + this->functionCode = functionCode; + this->startAdress = startAdress; + this->length = length; + +} + +void MyModbus::ReadColiAndReg() +{ + sendCommand.clear(); + sendCommand.append(stationAddress%256); + sendCommand.append(functionCode%256); + sendCommand.append(startAdress/256); + sendCommand.append(startAdress%256); + sendCommand.append(length/256); + sendCommand.append(length%256); + quint16 temp = CalculateCrc(sendCommand); + sendCommand.append(temp%256); + sendCommand.append(temp/256); +} + +void MyModbus::WriteCoil(QVector &coils) +{ + quint16 coilCount = coils.size(); + int byteCount = (coilCount + 7) / 8; + + sendCommand.clear(); + sendCommand.append(stationAddress%256); + sendCommand.append(0x0f); + sendCommand.append(startAdress/256); + sendCommand.append(startAdress%256); + sendCommand.append(length/256); + sendCommand.append(length%256); + sendCommand.append(byteCount); + for (int i = 0; i < byteCount; ++i) + { + quint8 byte = 0; + for (int j = 0; j < 8; ++j) + { + int bitIndex = i * 8 + j; + if (bitIndex < coils.size() && coils[bitIndex]) + byte |= (1 << j); + } + sendCommand.append(static_cast(byte)); + } + + quint16 temp = CalculateCrc(sendCommand); //计算crc + sendCommand.append(temp%256); //加入计算的crc值 + sendCommand.append(temp/256); +} + +void MyModbus::WriteRegister(QVector &values) +{ + sendCommand.clear(); + sendCommand.append(stationAddress%256); + sendCommand.append(0x10); + sendCommand.append(startAdress/256); + sendCommand.append(startAdress%256); + sendCommand.append(length/256); + sendCommand.append(length%256); + sendCommand.append(static_cast(values.size() * 2)); + for (quint16 v : values) + { + sendCommand.append(static_cast((v >> 8) & 0xFF)); + sendCommand.append(static_cast(v & 0xFF)); + } + quint16 temp = CalculateCrc(sendCommand); //计算crc + sendCommand.append(temp%256); //加入计算的crc值 + sendCommand.append(temp/256); +} + +QByteArray MyModbus::SendCommand() +{ + return sendCommand; +} + +QByteArray MyModbus::Receive(const QByteArray &revMessage) +{ + receive.clear(); + if (CrcCheck(revMessage)) + { + this->receive = revMessage; + } + return receive; +} + +int MyModbus::ErrorCheck() +{ + if ((receive.at(1) & 0x80) == 0x80) + { + // MODBUS异常响应结构:地址 | 功能码+0x80 | 异常码 | CRC + quint8 exCode = receive.at(2); + return exCode; + } + else + { + return 0; + } +} + +int MyModbus::ErrorCheck(QByteArray rev) +{ + if ((rev.at(1) & 0x80) == 0x80) + { + // MODBUS异常响应结构:地址 | 功能码+0x80 | 异常码 | CRC + quint8 exCode = rev.at(2); + return exCode; + } + else + { + return 0; + } +} + +QVector MyModbus::AnalReadCoil() +{ + quint8 byteCount = static_cast(receive[2]); + QVector coil; + + for (int byteIndex = 0; byteIndex < byteCount; byteIndex++) + { + quint8 byteValue = static_cast(receive[3 + byteIndex]); + + // 解析每个字节的8个位 + for (int bitIndex = 0; bitIndex < 8; bitIndex++) + { + int coilIndex = byteIndex * 8 + bitIndex; + if (coilIndex < length) + { + bool state = byteValue & (1 << bitIndex); + coil.append(state); + } + } + } + return coil; +} + +QVector MyModbus::AnalReadReg() +{ + int byteCount = receive.at(2); + QByteArray data = receive.mid(3, byteCount); + + QVector registers; + for (int i = 0; i < data.size(); i += 2) + { + quint16 value = (static_cast(data[i]) << 8) | static_cast(data[i+1]); + registers.append(value); + } + + return registers; +} + +QVector MyModbus::AnalReadCoil(QByteArray rev) +{ + quint8 byteCount = static_cast(rev[2]); + QVector coil; + + for (int byteIndex = 0; byteIndex < byteCount; byteIndex++) + { + quint8 byteValue = static_cast(rev[3 + byteIndex]); + + // 解析每个字节的8个位 + for (int bitIndex = 0; bitIndex < 8; bitIndex++) + { + int coilIndex = byteIndex * 8 + bitIndex; + if (coilIndex < length) + { + bool state = byteValue & (1 << bitIndex); + coil.append(state); + } + } + } + return coil; +} + +QVector MyModbus::AnalReadReg(QByteArray rev) +{ + int byteCount = rev.at(2); + QByteArray data = rev.mid(3, byteCount); + + QVector registers; + for (int i = 0; i < data.size(); i += 2) + { + quint16 value = (static_cast(data[i]) << 8) | static_cast(data[i+1]); + registers.append(value); + } + + return registers; +} + + diff --git a/mymodbus.h b/mymodbus.h new file mode 100644 index 0000000..cb7aeef --- /dev/null +++ b/mymodbus.h @@ -0,0 +1,35 @@ +#ifndef MYMODBUS_H +#define MYMODBUS_H + +#include +#include +#include +#include "crc.h" + +class MyModbus +{ +private: + quint16 stationAddress; + quint16 functionCode; + quint16 startAdress; + quint16 length; + QByteArray sendCommand; + QByteArray receive; + +public: + MyModbus(); + void Set(quint16 stationAddress,quint16 functionCode,quint16 startAdress,quint16 length); + void ReadColiAndReg(); + void WriteCoil(QVector &coils); + void WriteRegister(QVector &values); + QByteArray SendCommand(); + QByteArray Receive(const QByteArray &revMessage); + int ErrorCheck(); + int ErrorCheck(QByteArray rev); + QVector AnalReadCoil(); + QVector AnalReadReg(); + QVector AnalReadCoil(QByteArray rev); + QVector AnalReadReg(QByteArray rev); +}; + +#endif // MYMODBUS_H diff --git a/widget.cpp b/widget.cpp index 6cd13fb..44a824d 100644 --- a/widget.cpp +++ b/widget.cpp @@ -8,7 +8,10 @@ #include #include #include +#include +#include #include "crc.h" +#include "mymodbus.h" Widget::Widget(QWidget *parent) : QWidget(parent), @@ -16,11 +19,28 @@ Widget::Widget(QWidget *parent) : { ui->setupUi(this); serialPort = new QSerialPort(this); + modbus = new MyModbus(); connect(serialPort,&QSerialPort::readyRead,this,&Widget::on_SerialData_ReadyToRead); QObject::connect(&timer, &QTimer::timeout, [&]{ + if (comCount < 3) + { + ui->textEdit_2->append("通信超时,重新发送中"); + + serialPort->write(modbus->SendCommand()); + Sleep(1000); + timer.isActive(); + timer.start(1000); + + comCount ++; + } + else + { QMessageBox::warning(this, "提示", "等待响应超时,请检查设备状态。"); + ui->btn_read->setEnabled(1); + ui->pushWrite->setEnabled(1); timer.stop(); + } }); ui->comboBox_baudRate->setCurrentIndex(3); @@ -71,6 +91,7 @@ void Widget::on_btnConnect_clicked() if (serialPort->open(QIODevice::ReadWrite)) { qDebug() << "Serial open success"; + ui->textEdit_2->append("串口连接成功"); ui->btnConnect->setText("断开"); ui->btn_read->setEnabled(1); ui->pushWrite->setEnabled(1); @@ -78,15 +99,18 @@ void Widget::on_btnConnect_clicked() else { qDebug() << "error"; + QMessageBox::warning(this, "提示", "串口连接失败,请检查串口参数配置"); } } else { + delete modbus; serialPort->close(); ui->btn_read->setEnabled(0); ui->pushWrite->setEnabled(0); qDebug() << "Serial close"; ui->btnConnect->setText("连接"); + ui->textEdit_2->append("串口断开"); } } @@ -117,43 +141,23 @@ void Widget::on_pushWrite_clicked() coils.append(ch == '1'); } - quint16 coilCount = coils.size(); - - QByteArray SendCommand; //要发送的报文 - SendCommand.append(ui->comboBox_stationAddress->currentText().toInt()%256); //加入站地址 - SendCommand.append(0x0f); - SendCommand.append(ui->lineEdit_stratAddress->text().toInt()/256); //加入起始地址 - SendCommand.append(ui->lineEdit_stratAddress->text().toInt()%256); - SendCommand.append(ui->lineEdit_length->text().toInt()/256); //加入长度 - SendCommand.append(ui->lineEdit_length->text().toInt()%256); - - int byteCount = (coilCount + 7) / 8; - - SendCommand.append(byteCount); //字节数 - for (int i = 0; i < byteCount; ++i) - { - quint8 byte = 0; - for (int j = 0; j < 8; ++j) - { - int bitIndex = i * 8 + j; - if (bitIndex < coils.size() && coils[bitIndex]) - byte |= (1 << j); - } - SendCommand.append(static_cast(byte)); - } - + quint16 stationAddress = ui->comboBox_stationAddress->currentText().toInt(); + quint16 functionCode = 0x0f; + quint16 stratAddress = ui->lineEdit_stratAddress->text().toInt(); + quint16 length = ui->lineEdit_length->text().toInt(); - quint16 temp = calculateCrc(SendCommand); //计算crc + modbus->Set(stationAddress,functionCode,stratAddress,length); + modbus->WriteCoil(coils); - SendCommand.append(temp%256); //加入计算的crc值 - SendCommand.append(temp/256); - - ui->textEdit_2->append("发送报文"+SendCommand.toHex().toUpper()); - serialPort->write(SendCommand); + ui->textEdit_2->append("发送报文"+modbus->SendCommand().toHex().toUpper()); + serialPort->write(modbus->SendCommand()); + ui->btn_read->setEnabled(0); + ui->pushWrite->setEnabled(0); - Sleep(100); + comCount = 0; + Sleep(200); timer.isActive(); - timer.start(2000); // 2 s 后触发超时 + timer.start(1000); // 1 s 后触发超时 qDebug() << "SenOk" <comboBox_stationAddress->currentText().toInt()%256); //加入站地址 - SendCommand.append(0x10); - SendCommand.append(ui->lineEdit_stratAddress->text().toInt()/256); //加入起始地址 - SendCommand.append(ui->lineEdit_stratAddress->text().toInt()%256); - SendCommand.append(ui->lineEdit_length->text().toInt()/256); //加入长度 - SendCommand.append(ui->lineEdit_length->text().toInt()%256); - SendCommand.append(static_cast(values.size() * 2)); - for (quint16 v : values) - { - SendCommand.append(static_cast((v >> 8) & 0xFF)); - SendCommand.append(static_cast(v & 0xFF)); - } - - quint16 temp = calculateCrc(SendCommand); //计算crc + quint16 stationAddress = ui->comboBox_stationAddress->currentText().toInt(); + quint16 functionCode = 0x0f; + quint16 stratAddress = ui->lineEdit_stratAddress->text().toInt(); + quint16 length = ui->lineEdit_length->text().toInt(); - SendCommand.append(temp%256); //加入计算的crc值 - SendCommand.append(temp/256); + modbus->Set(stationAddress,functionCode,stratAddress,length); + modbus->WriteRegister(values); //要发送的报文 - ui->textEdit_2->append("发送报文"+SendCommand.toHex().toUpper()); - serialPort->write(SendCommand); + ui->textEdit_2->append("发送报文"+modbus->SendCommand().toHex().toUpper()); + serialPort->write(modbus->SendCommand()); + ui->btn_read->setEnabled(0); + ui->pushWrite->setEnabled(0); - Sleep(100); + comCount = 0; + Sleep(200); timer.isActive(); - timer.start(2000); // 2 s 后触发超时 + timer.start(1000); // 1 s 后触发超时 qDebug() << "SenOk" <readAll(); + QByteArray revMessage = modbus->Receive(serialPort->readAll()); + if (!revMessage.isEmpty()) + { + ui->btn_read->setEnabled(1); + ui->pushWrite->setEnabled(1); + timer.stop(); + } + else + { + return; + } QString hexData = revMessage.toHex().toUpper(); qDebug() << hexData; ui->textEdit_2->append("接收报文"+hexData); - //首先对接收报文的长度进行检验 - if (revMessage.size() < 3) { - QMessageBox::warning(this, "警告", "无效的响应格式"); - qDebug() << "响应报文过短,长度 =" << revMessage.size(); - return; - } - - //对接收的报文进行CRC校验 - QByteArray payload = revMessage.left(revMessage.length() - 2); + qDebug() << "接收成功"; + int exCode = modbus->ErrorCheck(revMessage); + if (exCode) + { + QString errorMsg; + switch (exCode) + { + case 0x01: errorMsg = "非法功能码"; break; + case 0x02: errorMsg = "非法数据地址"; break; + case 0x03: errorMsg = "非法数据值"; break; + case 0x04: errorMsg = "从站设备故障"; break; + default: errorMsg = "未知异常"; break; + } - //分离接收值的crc校验位 - quint8 receivedCrcLow = static_cast(revMessage.at(revMessage.length() - 2)); - quint8 receivedCrcHigh = static_cast(revMessage.at(revMessage.length() - 1)); + QMessageBox::warning(this, "异常响应", + QString("异常\n错误码: 0x%1 (%2)") + .arg(QString::number(exCode, 16).toUpper().rightJustified(2, '0')) + .arg(errorMsg)); - //计算返回的报文的crc - quint16 crc = calculateCrc(payload); - quint8 calcCrcLow = crc & 0xFF; - quint8 calcCrcHigh = (crc >> 8) & 0xFF; + return; + } - //比较计算的crc值和接收到的crc值是否一致 - if(calcCrcLow == receivedCrcLow && calcCrcHigh == receivedCrcHigh) + switch (ui->comboBox_gongnengma->currentIndex()) { - qDebug() << "接收成功"; - if ((revMessage.at(1) & 0x80) == 0x80) { - // MODBUS异常响应结构:地址 | 功能码+0x80 | 异常码 | CRC - quint8 originalFunctionCode = revMessage.at(1) & 0x7F; // 去掉最高位 - quint8 exCode = revMessage.at(2); - - QString errorMsg; - switch (exCode) { - case 0x01: errorMsg = "非法功能码"; break; - case 0x02: errorMsg = "非法数据地址"; break; - case 0x03: errorMsg = "非法数据值"; break; - case 0x04: errorMsg = "从站设备故障"; break; - case 0x05: errorMsg = "确认"; break; - case 0x06: errorMsg = "从站设备忙"; break; - case 0x07: errorMsg = "负确认"; break; - case 0x08: errorMsg = "存储奇偶错误"; break; - default: errorMsg = "未知异常"; break; - } - - QMessageBox::warning(this, "异常响应", - QString("功能码 0x%1 异常\n错误码: 0x%2 (%3)") - .arg(QString::number(originalFunctionCode, 16).toUpper()) - .arg(QString::number(exCode, 16).toUpper().rightJustified(2, '0')) - .arg(errorMsg)); - - return; - } + //解析读线圈的返回报文 + case 0: + { + QVector coil = modbus->AnalReadCoil(revMessage); - switch (ui->comboBox_gongnengma->currentIndex()) + ui->textEdit->append("线圈状态:"); + for (int i = 0; i < coil.size(); i++) { - //解析读线圈的返回报文 - case 0: - { - quint8 byteCount = static_cast(revMessage[2]); - - for (int byteIndex = 0; byteIndex < byteCount; byteIndex++) - { - quint8 byteValue = static_cast(revMessage[3 + byteIndex]); - - // 解析每个字节的8个位 - for (int bitIndex = 0; bitIndex < 8; bitIndex++) - { - int coilIndex = byteIndex * 8 + bitIndex; - if (coilIndex < ui->lineEdit_length->text().toInt()) - { - bool state = byteValue & (1 << bitIndex); - qDebug() << coilIndex <<" " << state; - ui->textEdit->append("线圈"+QString::number(coilIndex+1)+":"+QString::number(state)); - } - } - } - break; + bool state = coil.at(i); + ui->textEdit->append("线圈"+QString::number(i+1)+":"+QString::number(state)); } + + break; + } //解析读寄存器的返回报文 - case 1: - { - if (revMessage.size() >= 5 && revMessage.at(1) == 0x03) + case 1: + { + QVector registers = modbus->AnalReadReg(revMessage); + + ui->textEdit->append("寄存器的值:"); + for (int i = 0; i < registers.size(); i++) { - int byteCount = revMessage.at(2); - QByteArray data = revMessage.mid(3, byteCount); - - QVector registers; - for (int i = 0; i < data.size(); i += 2) - { - quint16 value = (static_cast(data[i]) << 8) | static_cast(data[i+1]); - registers.append(value); - } - - for (int i = 0; i < registers.size(); i++) - { - qDebug() << "Register value:" << registers.at(i); - ui->textEdit->append("寄存器"+QString::number(i)+":"+QString::number(registers.at(i))); - } + ui->textEdit->append("寄存器"+QString::number(i+1)+":"+QString::number(registers.at(i))); } - break; - } + break; - } } - else - { - qDebug() << "接收失败"; + } } @@ -346,32 +298,88 @@ void Widget::on_btn_read_clicked() QMessageBox::warning(this, "提示", "请将“操作”切换为读线圈或读寄存器"); return; } - QByteArray SendCommand; //要发送的报文 - SendCommand.append(ui->comboBox_stationAddress->currentText().toInt()%256); //加入站地址 + quint16 stationAddress = ui->comboBox_stationAddress->currentText().toInt(); + quint16 functionCode; + quint16 stratAddress = ui->lineEdit_stratAddress->text().toInt(); + quint16 length = ui->lineEdit_length->text().toInt(); + QByteArray SendCommand; + if (ui->comboBox_gongnengma->currentIndex() == 0) //读线圈 { - SendCommand.append(0x01); + functionCode = 0x01; } else if(ui->comboBox_gongnengma->currentIndex() == 1) //读寄存器 { - SendCommand.append(0x03); + functionCode = 0x03; } - SendCommand.append(ui->lineEdit_stratAddress->text().toInt()/256); //加入起始地址 - SendCommand.append(ui->lineEdit_stratAddress->text().toInt()%256); - SendCommand.append(ui->lineEdit_length->text().toInt()/256); //加入长度 - SendCommand.append(ui->lineEdit_length->text().toInt()%256); + modbus->Set(stationAddress,functionCode,stratAddress,length); + modbus->ReadColiAndReg(); + + serialPort->write(modbus->SendCommand()); //发送报文 + ui->textEdit_2->append("发送报文"+modbus->SendCommand().toHex().toUpper()); + ui->btn_read->setEnabled(0); + ui->pushWrite->setEnabled(0); + + comCount = 0; + Sleep(200); + timer.isActive(); + timer.start(1000); // 1 s 后触发超时 +} + +void Widget::on_pushButton_clicked() +{ + QString fileName = QFileDialog::getSaveFileName( + this, + "保存文本", + QDir::homePath() + "/note.txt", + "文本文件 (*.txt);;所有文件 (*.*)"); + + if (fileName.isEmpty()) + return; - quint16 temp = calculateCrc(SendCommand); //计算crc + QFile file(fileName); + if (!file.open(QIODevice::Append | QIODevice::Text)) // + { + QMessageBox::warning(this, "错误", "无法打开文件"); + return; + } - SendCommand.append(temp%256); //加入计算的crc值 - SendCommand.append(temp/256); + // 每次追加前换行 + if (file.size() > 0) // 文件非空 + file.write("\n"); // 先换行,再写内容 - qDebug() << SendCommand.toHex(); - ui->textEdit_2->append("发送报文"+SendCommand.toHex().toUpper()); - serialPort->write(SendCommand); //发送报文 + QTextStream out(&file); + out.setCodec("UTF-8"); + out << ui->textEdit_2->toPlainText(); // 追加写入 + file.close(); +} - Sleep(100); - timer.isActive(); - timer.start(2000); // 2 s 后触发超时 +void Widget::on_pushButton_2_clicked() +{ + QString fileName = QFileDialog::getOpenFileName( + this, + "打开文本", + QDir::homePath(), + "文本文件 (*.txt);;所有文件 (*.*)"); + + if (fileName.isEmpty()) + return; + + QFile file(fileName); + if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) + { + QMessageBox::warning(this, "错误", "无法读取文件"); + return; + } + + QTextStream in(&file); + in.setCodec("UTF-8"); + ui->textEdit_2->setPlainText(in.readAll()); + file.close(); +} + +void Widget::on_pushButton_3_clicked() +{ + ui->textEdit_2->clear(); } diff --git a/widget.h b/widget.h index 8464491..a8ffe3f 100644 --- a/widget.h +++ b/widget.h @@ -4,6 +4,7 @@ #include #include #include +#include "mymodbus.h" namespace Ui { class Widget; @@ -26,10 +27,18 @@ private slots: void on_btn_read_clicked(); + void on_pushButton_clicked(); + + void on_pushButton_2_clicked(); + + void on_pushButton_3_clicked(); + private: Ui::Widget *ui; QSerialPort *serialPort; + MyModbus *modbus; QTimer timer; + int comCount; }; #endif // WIDGET_H diff --git a/widget.ui b/widget.ui index 65ee4c6..1c5cd1a 100644 --- a/widget.ui +++ b/widget.ui @@ -13,219 +13,11 @@ Widget - - - - 31 - 31 - 30 - 16 - - - - 串口 - - - - - - 68 - 31 - 87 - 21 - - - - - - - 162 - 31 - 45 - 16 - - - - 波特率 - - - - - - 308 - 31 - 45 - 16 - - - - 数据位 - - - - - - 214 - 31 - 87 - 21 - - - - - 1200 - - - - - 2400 - - - - - 4800 - - - - - 9600 - - - - - 19200 - - - - - 38400 - - - - - - - 360 - 31 - 61 - 21 - - - - - 5 - - - - - 6 - - - - - 7 - - - - - 8 - - - - - NONE - - - - - - - 340 - 60 - 93 - 28 - - - - 连接 - - - - - - 80 - 70 - 91 - 21 - - - - - 无校验(N) - - - - - 奇校验(O) - - - - - 偶校验(E) - - - - - - - 30 - 70 - 51 - 21 - - - - 校验位 - - - - - - 198 - 70 - 45 - 16 - - - - 停止位 - - - - - - 250 - 70 - 61 - 21 - - - - - 1 - - - - - 2 - - - - 330 - 410 + 340 + 430 301 31 @@ -234,8 +26,8 @@ - 330 - 460 + 350 + 470 93 28 @@ -248,7 +40,7 @@ 40 - 230 + 250 251 211 @@ -257,8 +49,8 @@ - 90 - 460 + 110 + 470 93 28 @@ -374,7 +166,7 @@ - 00 + 256 @@ -388,7 +180,7 @@ - 00 + 1 @@ -397,8 +189,8 @@ - 330 - 300 + 340 + 330 311 101 @@ -410,15 +202,206 @@ 相邻寄存器的值之间用英文","分离。 - + + + + 40 + 30 + 378 + 62 + + + + + + + + + 串口 + + + + + + + + + + 波特率 + + + + + + + + 1200 + + + + + 2400 + + + + + 4800 + + + + + 9600 + + + + + 19200 + + + + + 38400 + + + + + + + + 数据位 + + + + + + + + 5 + + + + + 6 + + + + + 7 + + + + + 8 + + + + + NONE + + + + + + + + + + + + 校验位 + + + + + + + + 无校验(N) + + + + + 奇校验(O) + + + + + 偶校验(E) + + + + + + + + 停止位 + + + + + + + + 1 + + + + + 2 + + + + + + + + 连接 + + + + + + + + 40 150 671 - 61 + 91 + + + + + + + + + + 清空收发信息 + + + + + + + 保存收发信息 + + + + + + + 读取历史收发信息 + + + + + +