#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QFileDialog>
#include <QMessageBox>
#include <QDateTime>
#include <QTimer>
#include <QTextStream>
#include <QApplication>
#include <QScreen>
#include <QInputDialog>
#include <QTextCodec>
#include <QProgressDialog>
#include <QToolBar>
#include <QThread>
#include <QDebug>
MainWindow::MainWindow(QWidget *parent)
: QMainWindow(parent) // 初始化父类QMainWindow
, ui(new Ui::MainWindow) // 初始化UI对象
, m_serial(new SerialCommunication(this)) // 创建串口通信实例
, m_serialDialog(new SerialSettingDialog(m_serial, this)) // 创建串口设置对话框
{
ui->setupUi(this);//初始化UI
// 启用双缓冲绘制,减少闪烁
setAttribute(Qt::WA_NoSystemBackground, true); // 禁用系统背景绘制
setAttribute(Qt::WA_OpaquePaintEvent, true); // 确保完全覆盖背景,避免透底
setAttribute(Qt::WA_PaintOnScreen, false); // 使用Qt的双缓冲机制
// 取消固定比例,设置合理最小尺寸
//setMinimumSize(1024, 768); // 基于内容需求的最小尺寸
setMinimumSize(1600, 900); // 基于内容需求的最小尺寸
initUI(); // 初始化界面布局
m_modbus = new ModBus(m_serial);
initMotorUnits(); // 初始化99个电机控制单元
updateStatusBar(); // 初始化状态栏
// 连接反馈信号
connect(m_modbus, &ModBus::motorFeedbackReceived, this, &MainWindow::onMotorFeedbackReceived);
// 定时刷新双缓冲(20Hz频率,减少闪烁)
QTimer *bufferTimer = new QTimer(this);
connect(bufferTimer, &QTimer::timeout, this, [this](){
updateBuffer(); // 自定义缓冲更新逻辑
update(); // 触发界面重绘
});
bufferTimer->start(50); // 50ms触发一次(20Hz)
// 连接串口数据接收信号(串口收到数据时,调用handleSerialData处理)
connect(m_serial, &SerialCommunication::dataReceived, this, &MainWindow::handleSerialData);
// 连接"关于"菜单动作(点击时显示关于对话框)
connect(ui->actionAbout, &QAction::triggered, this, &MainWindow::onAboutClicked);
// 定时更新状态栏(1秒一次)
QTimer *timeTimer = new QTimer(this);
connect(timeTimer, &QTimer::timeout, this, &MainWindow::updateStatusBar);
timeTimer->start(1000);
}
MainWindow::~MainWindow()
{
delete ui;
delete m_modbus;
delete m_serial;
}
void MainWindow::resizeEvent(QResizeEvent *event)
{
Q_UNUSED(event);
// 禁用所有子控件更新
setUpdatesEnabled(false);
// 调整分页布局,不限制比例
adjustTabLayout(qobject_cast<QGridLayout*>(ui->tab1_20->layout()));
adjustTabLayout(qobject_cast<QGridLayout*>(ui->tab21_40->layout()));
adjustTabLayout(qobject_cast<QGridLayout*>(ui->tab41_60->layout()));
adjustTabLayout(qobject_cast<QGridLayout*>(ui->tab61_80->layout()));
adjustTabLayout(qobject_cast<QGridLayout*>(ui->tab81_100->layout()));
// 启用更新并触发一次重绘
setUpdatesEnabled(true);
updateBuffer(); // 刷新缓冲
}
// 初始化界面(绑定分页控件、状态栏)
void MainWindow::initUI()
{
// 深色主题全局样式表(增强对比度与专业性)
setStyleSheet(R"(
QMainWindow {
background-color: #1A1A1A;
color: #E6E6E6;
font-family: "Segoe UI", "Microsoft YaHei", sans-serif;
font-size: 10pt;
/* 移除边框,避免拉伸时闪烁 */
}
QWidget {
background-color: #1A1A1A;
color: #E6E6E6;
font-family: "Segoe UI", "Microsoft YaHei", sans-serif;
font-size: 10pt;
border: 1px solid #333333;
border-radius: 6px;
}
/* 分页控件样式 */
QTabWidget::pane {
border: 1px solid #333333;
background-color: #222222;
border-radius: 6px;
margin: 5px;
}
QTabBar::tab {
background-color: #2A2A2A;
color: #CCCCCC;
padding: 8px 16px;
border: 1px solid #444444;
border-bottom-color: transparent;
border-radius: 4px 4px 0 0;
min-width: 90px;
}
QTabBar::tab:selected {
background-color: #222222;
color: #FFFFFF;
border-color: #555555;
border-bottom-color: #222222;
font-weight: bold;
}
QTabBar::tab:hover:!selected {
background-color: #333333;
}
/* 按钮样式(强化交互反馈) */
QPushButton {
background-color: #3D5A80;
color: #FFFFFF;
border: none;
border-radius: 3px;
padding: 6px 12px;
min-height: 28px;
}
QPushButton:hover {
background-color: #4A6FA5;
border: 1px solid #5C85B8;
}
QPushButton:pressed {
background-color: #2A4365;
}
QPushButton:disabled {
background-color: #333333;
color: #888888;
}
/* 状态栏样式 */
QStatusBar {
background-color: #1A1A1A;
color: #BBBBBB;
border-top: 1px solid #333333;
padding: 2px 8px;
}
/* 菜单与工具栏 */
QMenuBar {
background-color: #222222;
color: #CCCCCC;
border-bottom: 1px solid #333333;
}
QMenuBar::item:selected {
background-color: #333333;
color: #FFFFFF;
}
QToolBar {
background-color: #222222;
border-bottom: 1px solid #333333;
spacing: 4px;
}
)");
// 添加快速定位区域(放在工具栏)
QToolBar *navToolBar = new QToolBar("导航", this);
navToolBar->setStyleSheet("QToolBar { border-bottom: 1px solid #333333; }");
addToolBar(navToolBar);
QLabel *jumpLabel = new QLabel("跳转至电机: ");
QLineEdit *jumpInput = new QLineEdit();
jumpInput->setValidator(new QIntValidator(1, 100, this));
jumpInput->setMaximumWidth(60);
QPushButton *jumpBtn = new QPushButton("跳转");
navToolBar->addWidget(jumpLabel);
navToolBar->addWidget(jumpInput);
navToolBar->addWidget(jumpBtn);
// 绑定跳转逻辑
connect(jumpBtn, &QPushButton::clicked, this, [=]() {
int motorNum = jumpInput->text().toInt();
if (motorNum < 1 || motorNum > 100) return;
// 计算目标分页(1-20→0,21-40→1,以此类推)
int tabIndex = (motorNum - 1) / 20;
m_tabWidget->setCurrentIndex(tabIndex);
jumpInput->clear();
});
// 绑定UI中的分页控件
m_tabWidget = ui->tabWidget;
m_statusBar = ui->statusBar;
// 为每个分页签直接创建QGridLayout(避免多层嵌套)
// 为每个分页签创建QGridLayout
QLayout* layout = nullptr;
if((layout = ui->tab1_20->layout()) != nullptr) delete layout;
ui->tab1_20->setLayout(new QGridLayout());
if((layout = ui->tab21_40->layout()) != nullptr) delete layout;
ui->tab21_40->setLayout(new QGridLayout());
if((layout = ui->tab41_60->layout()) != nullptr) delete layout;
ui->tab41_60->setLayout(new QGridLayout());
if((layout = ui->tab61_80->layout()) != nullptr) delete layout;
ui->tab61_80->setLayout(new QGridLayout());
if((layout = ui->tab81_100->layout()) != nullptr) delete layout;
ui->tab81_100->setLayout(new QGridLayout());
// 5个标签页布局
QList<QGridLayout*> layouts = {
qobject_cast<QGridLayout*>(ui->tab1_20->layout()),
qobject_cast<QGridLayout*>(ui->tab21_40->layout()),
qobject_cast<QGridLayout*>(ui->tab41_60->layout()),
qobject_cast<QGridLayout*>(ui->tab61_80->layout()),
qobject_cast<QGridLayout*>(ui->tab81_100->layout())
};
// 统一配置分页布局
for (QGridLayout *layout : layouts) {
if (layout) {
layout->setSpacing(8);
layout->setContentsMargins(10, 10, 10, 10);
adjustTabLayout(layout); // 配置行列拉伸
}
}
}
// 辅助函数:配置分页布局的行列拉伸(5列5行,均匀分布25个电机)
//void MainWindow::adjustTabLayout(QGridLayout *layout)
//{
//// if (!layout) return;
//// // 5列布局,加大最小宽度阈值
//// const int MIN_COL_WIDTH = 150; // 从150调整为200,减少频繁重排
//// const int MIN_ROW_HEIGHT = 120; // 从120调整为150,减少频繁重排
// if (!layout) return;
// // 根据屏幕分辨率动态计算最小宽高(示例:屏幕宽度的1/8,高度的1/10)
// QScreen *screen = QApplication::primaryScreen();
// int screenWidth = screen->geometry().width();
// int screenHeight = screen->geometry().height();
// const int MIN_COL_WIDTH = qMax(150, screenWidth / 8); // 最小150px,适配小屏
// const int MIN_ROW_HEIGHT = qMax(120, screenHeight /10);
// // 5列:每列拉伸因子相同(均匀分配宽度)
// for (int col = 0; col < 5; col++) {
// layout->setColumnMinimumWidth(col, MIN_COL_WIDTH);
// layout->setColumnStretch(col, 1); // 保持均匀拉伸
// }
// // 4行:每行列拉伸因子相同(均匀分配高度)
// int rowCount = layout->rowCount();
// for (int row = 0; row < qMax(4, rowCount); row++) { // 至少5行(25个电机5x5)
// layout->setRowMinimumHeight(row, MIN_ROW_HEIGHT);
// layout->setRowStretch(row, 1);
// }
//}
//void MainWindow::adjustTabLayout(QGridLayout *layout) {
// if (!layout) return;
// // 基于当前窗口尺寸计算,而非屏幕尺寸
// int windowWidth = this->width();
// int windowHeight = this->height();
// // 5列布局,每列宽度随窗口自适应(保留边距)
// const int margin = 20; // 窗口边缘留白
// const int colCount = 5;
// int availableWidth = windowWidth - margin * 2;
// int colWidth = qMax(180, availableWidth / colCount); // 最小180px避免拥挤
// // 4行布局,每行高度基于内容自适应
// const int rowCount = 4;
// int availableHeight = windowHeight - 200; // 扣除标题栏、状态栏等高度
// int rowHeight = qMax(160, availableHeight / rowCount); // 最小160px保证控件完整
// // 设置列属性
// for (int col = 0; col < colCount; col++) {
// layout->setColumnMinimumWidth(col, colWidth);
// layout->setColumnStretch(col, 1); // 均等拉伸
// }
// // 设置行属性
// for (int row = 0; row < rowCount; row++) {
// layout->setRowMinimumHeight(row, rowHeight);
// layout->setRowStretch(row, 1); // 均等拉伸
// }
// // 统一网格布局边距
// layout->setContentsMargins(margin, margin, margin, margin);
//}
// 修改 mainwindow.cpp 中 adjustTabLayout() 函数
void MainWindow::adjustTabLayout(QGridLayout *layout) {
if (!layout) return;
// 基于当前分页控件尺寸计算(而非整个窗口)
QWidget *tabWidget = layout->parentWidget();
if (!tabWidget) return;
int tabWidth = tabWidget->width();
int tabHeight = tabWidget->height();
// 动态计算边距(随窗口大小变化)
const int margin = qMax(10, tabWidth / 50); // 最小10px,最大窗口1/50
const int colCount = 5;
const int rowCount = 4;
// 可用空间 = 总尺寸 - 边距*2(减去两侧边距)
int availableWidth = tabWidth - margin * 2;
int availableHeight = tabHeight - margin * 2;
// 列宽:确保最小宽度(180px),同时不超过可用空间的1/colCount
int colWidth = qMin(availableWidth / colCount, 250); // 最大250px避免过大
colWidth = qMax(colWidth, 180);
// 行高:类似列宽计算逻辑
int rowHeight = qMin(availableHeight / rowCount, 200); // 最大200px
rowHeight = qMax(rowHeight, 160);
// 设置行列属性
for (int col = 0; col < colCount; col++) {
layout->setColumnMinimumWidth(col, colWidth);
layout->setColumnStretch(col, 1);
}
for (int row = 0; row < rowCount; row++) {
layout->setRowMinimumHeight(row, rowHeight);
layout->setRowStretch(row, 1);
}
layout->setContentsMargins(margin, margin, margin, margin);
}
// 初始化99个电机控制单元(按5列5行分配到4个分页)
void MainWindow::initMotorUnits()
{
// 分页布局列表(对应5个分页标签页)
QList<QGridLayout*> layouts = {
qobject_cast<QGridLayout*>(ui->tab1_20->layout()), // 第1-20号电机
qobject_cast<QGridLayout*>(ui->tab21_40->layout()), // 第21-40号电机
qobject_cast<QGridLayout*>(ui->tab41_60->layout()), // 第41-60号电机
qobject_cast<QGridLayout*>(ui->tab61_80->layout()), // 第61-80号电机
qobject_cast<QGridLayout*>(ui->tab81_100->layout()) // 第81-100号电机
};
// 每个分页20个电机(5×4)
QList<int> motorCounts = {20, 20, 20, 20, 20};
int motorNum = 1; // 电机编号从1开始
// 遍历5个分页
for (int tabIdx = 0; tabIdx < 5; tabIdx++) {
QGridLayout *layout = layouts[tabIdx]; // 当前分页的布局
int count = motorCounts[tabIdx]; // 当前分页的电机数量
int row = 0, col = 0; // 网格布局的行列索引
// 为当前分页创建电机控制单元
for (int i = 0; i < count; i++) {
// 创建电机控制单元(编号motorNum,父窗口为当前主窗口)
MotorControlUnit *motorUnit = new MotorControlUnit(motorNum, this);
// 设置尺寸策略为自适应(随窗口拉伸)
motorUnit->setSizePolicy(QSizePolicy::Expanding, QSizePolicy::Expanding);
// 添加到电机单元列表(便于后续管理)
m_motorUnits.append(motorUnit);
// 将电机单元添加到当前分页的网格布局
layout->addWidget(motorUnit, row, col);
// 连接电机发送指令信号(电机点击"发送"时,转发到串口)
connect(motorUnit, &MotorControlUnit::sendCommand,
this, &MainWindow::forwardMotorCommand);
// 更新行列索引(4列满则换行)
col++;
if (col >= 5) {
col = 0;
row++;
}
motorNum++; // 电机编号递增
}
}
}
// 更新状态栏(显示串口状态和当前时间)
void MainWindow::updateStatusBar()
{
// 串口状态文本
QString serialStatus = m_serial->isSerialPortOpen()
? QString("串口:%1(%2)").arg(m_serialDialog->getCurrentPortName()).arg(m_serialDialog->getCurrentBaudRate())
: "串口:未打开";
// 当前时间(格式:yyyy-MM-dd HH:mm:ss)
QString currentTime = QDateTime::currentDateTime().toString("yyyy-MM-dd HH:mm:ss");
// 更新状态栏
m_statusBar->showMessage(QString("%1 | %2").arg(serialStatus).arg(currentTime));
}
// 串口设置按钮点击事件
void MainWindow::onSerialSettingClicked()
{
m_serialDialog->exec();
updateStatusBar(); // 关闭对话框后更新串口状态
}
// 加载CSV按钮点击事件(从CSV读取电机参数)
void MainWindow::onLoadCsvClicked()
{
// 打开文件选择对话框(选择CSV文件)
QString filePath = QFileDialog::getOpenFileName(this, "选择CSV文件", "", "CSV Files (*.csv)");
if (filePath.isEmpty()) return; // 未选择文件则返回
QFile file(filePath);
// 尝试打开文件(只读、文本模式)
if (!file.open(QIODevice::ReadOnly | QIODevice::Text)) {
QMessageBox::warning(this, "错误", "无法打开CSV文件!");
return;
}
// 读取CSV内容(格式:电机编号,力控制(N),位置(cm),控制模式,使能状态)
QTextStream in(&file);
in.readLine(); // 跳过表头行
while (!in.atEnd()) { // 逐行读取
QString line = in.readLine();
QStringList parts = line.split(","); // 按逗号分割
if (parts.size() != 5) continue; // 格式错误则跳过
// 解析各字段
int motorNum = parts[0].toInt();
double force = parts[1].toDouble();
double pos = parts[2].toDouble();
QString mode = parts[3];
QString enable = parts[4];
// 找到对应电机并设置参数
for (MotorControlUnit *unit : m_motorUnits) {
if (unit->getMotorNumber() == motorNum) {
unit->setTargetForce(force); // 设置目标力
unit->setTargetPosition(pos); // 设置目标位置
unit->setControlMode(mode); // 设置控制模式
unit->setEnableState(enable); // 设置使能状态
break;
}
}
}
file.close();
QMessageBox::information(this, "成功", "CSV文件加载完成!");
}
//保存CSV文件
void MainWindow::onSaveCsvClicked()
{
QString filePath = QFileDialog::getSaveFileName(this, "保存CSV文件", "", "CSV Files (*.csv)");
if (filePath.isEmpty()) return;// 未指定路径则返回
QFile file(filePath);
// 尝试打开文件(只写、文本模式)
if (!file.open(QIODevice::WriteOnly | QIODevice::Text)) {
QMessageBox::warning(this, "错误", "无法创建CSV文件!");
return;
}
// 写入CSV内容(表头+99个电机参数)
QTextStream out(&file);
// 精确设置编码和换行符
out.setCodec(QTextCodec::codecForName("UTF-8"));
out.setGenerateByteOrderMark(false); // 手动控制BOM
// 处理BOM标记(关键修正)
const unsigned char utf8Bom[3] = {0xEF, 0xBB, 0xBF};
file.write(reinterpret_cast<const char*>(utf8Bom), 3);
// 写入CSV表头 - 使用本地化字符串处理中文
QString header = QString::fromLocal8Bit("电机编号,力控制(N),位置(cm),控制模式,使能状态\n");
out << header;
// 写入每个电机的参数
for (MotorControlUnit *unit : m_motorUnits) {
out << QString("%1,%2,%3,%4,%5\n")
.arg(unit->getMotorNumber())
.arg(unit->getTargetForce(), 0, 'f', 3)
.arg(unit->getTargetPosition(), 0, 'f', 3)
.arg(unit->getControlMode())
.arg(unit->getEnableState());
}
// 刷新缓冲区(确保数据写入文件)
out.flush(); // 确保缓冲区刷新
file.close();
QMessageBox::information(this, "成功", "CSV文件保存完成!");
}
// 全部发送按钮点击事件(发送所有电机的指令)
void MainWindow::onSendAllClicked()
{
if (!m_serial->isSerialPortOpen()) {
QMessageBox::warning(this, "警告", "串口未打开,无法发送数据!");
return;
}
// 遍历所有电机,发送指令
for (MotorControlUnit *unit : m_motorUnits) {
forwardMotorCommand(
unit->getMotorNumber(),
unit->getTargetForce(),
unit->getTargetPosition(),
unit->getControlMode(),
unit->getEnableState()
);
}
QMessageBox::information(this, "成功", "所有电机指令已发送!");
}
// 恢复初始按钮点击事件(重置所有电机参数)
void MainWindow::onRestoreDefaultClicked()
{
for (MotorControlUnit *unit : m_motorUnits) {
unit->setTargetForce(0.000);
unit->setTargetPosition(0.000);
unit->setControlMode("闭环");
unit->setEnableState("失能");
// 重置反馈值
unit->setFeedbackForce(0.000);
unit->setFeedbackPosition(0.000);
unit->setFeedbackMode("闭环系统");
unit->setFeedbackEnable("电机失能");
}
QMessageBox::information(this, "成功", "所有参数已恢复默认值!");
}
// 转发电机指令到串口(指令格式:自定义协议,便于硬件解析)
void MainWindow::forwardMotorCommand(int motorNum, double force, double pos, const QString &mode, const QString &enable)
{
if (!m_serial->isSerialPortOpen()) {
QMessageBox::warning(this, "警告", "串口未打开,无法发送电机指令!");
return;
}
// 寄存器映射:0=电机序号,1-2=力,3-4=位置,5=模式,6=使能
uint16_t regs[7]; // 共7个寄存器
// 寄存器0:电机序号(16位整数)
if (motorNum < 1) {
QMessageBox::warning(this, "警告", "电机序号无效!");
return;
}
regs[0] = static_cast<uint16_t>(motorNum);
// 寄存器1-2:力控制值(32位浮点数)
float forceFloat = static_cast<float>(force);
floatToRegisters(forceFloat, ®s[1]);
// 寄存器3-4:位置控制值(32位浮点数)
float posFloat = static_cast<float>(pos);
floatToRegisters(posFloat, ®s[3]);
// 寄存器5:控制模式(0=开环,1=闭环)
regs[5] = (mode == "开环") ? 0 : 1;
// 寄存器6:使能状态(0=失能,1=使能)
regs[6] = (enable == "使能") ? 1 : 0;
// 2. 计算该电机的起始寄存器地址
uint16_t startReg = (motorNum - 1) * 7;
// 发送0x10指令(假设从站地址为1,可根据硬件调整)
m_modbus->MODH_Send10H(1, startReg, 7,regs); // 从站地址1,起始寄存器0,7个寄存器
}
// 处理串口接收的数据(解析硬件反馈,更新电机反馈值)
void MainWindow::handleSerialData(const QByteArray &data)
{
// 自定义反馈数据格式(示例:<电机号,实际力,实际位置,实际模式,实际使能>)
QString feedback = QString::fromUtf8(data);
if (feedback.startsWith("<") && feedback.endsWith(">\n")) {
feedback = feedback.mid(1, feedback.size() - 3); // 去除首尾标记
QStringList parts = feedback.split(",");
if (parts.size() != 5) return;
int motorNum = parts[0].toInt();
double realForce = parts[1].toDouble();
double realPos = parts[2].toDouble();
int realModeCode = parts[3].toInt();
int realEnableCode = parts[4].toInt();
// 解析反馈状态文本
QString realMode = (realModeCode == 0) ? "开环系统" : "闭环系统";
QString realEnable = (realEnableCode == 1) ? "电机使能" : "电机失能";
// 更新对应电机的反馈值
for (MotorControlUnit *unit : m_motorUnits) {
if (unit->getMotorNumber() == motorNum) {
unit->setFeedbackForce(realForce);
unit->setFeedbackPosition(realPos);
unit->setFeedbackMode(realMode);
unit->setFeedbackEnable(realEnable);
break;
}
}
}
}
void MainWindow::onMotorFeedbackReceived(int motorNumber, double force, double position, int mode, int enable)
{
// // 查找对应的电机控制单元
// foreach (MotorControlUnit *unit, m_motorUnits) {
// if (unit->getMotorNumber() == motorNumber) {
// // 更新力反馈
// unit->setFeedbackForce(force);
// // 更新位置反馈
// unit->setFeedbackPosition(position);
// // 更新模式反馈
// QString modeStr = (mode == 0) ? "开环系统" : "闭环系统";
// unit->setFeedbackMode(modeStr);
// // 更新使能反馈
// QString enableStr = (enable == 1) ? "电机使能" : "电机失能";
// unit->setFeedbackEnable(enableStr);
// break;
// }
// }
// 1. 校验电机编号范围(1~100)
if (motorNumber < 1 || motorNumber > m_motorUnits.size()) {
qDebug() << "未找到电机" << motorNumber << "的控制单元(编号超出范围)";
return;
}
// 2. 计算正确索引(编号-1)
int index = motorNumber - 1;
MotorControlUnit* unit = m_motorUnits[index];
// 3. 验证单元是否存在(防御性检查)
if (!unit) {
qDebug() << "未找到电机" << motorNumber << "的控制单元(索引无效)";
return;
}
// 获取对应电机控制单元并更新反馈
unit->setFeedbackForce(force);
unit->setFeedbackPosition(position);
unit->setFeedbackMode(mode == 0 ? "开环" : "闭环"); // 根据实际模式值映射
unit->setFeedbackEnable(enable == 1 ? "使能" : "失能"); // 根据实际使能值映射
qDebug() << "未找到电机" << motorNumber << "的控制单元";
}
// 实现onAboutClicked函数(已存在于代码中)
void MainWindow::onAboutClicked()
{
AboutDialog dialog(this);
dialog.exec();
}
发送10H指令:从站 1 起始寄存器 0 数量 7
10H写入确认:从站 1 电机编号 1 起始寄存器 0 写入数量 7
发送03H请求:从站 1 寄存器 0 数量 7
解析到电机编号: 1 (原始字节: "00 01" )
解析到力控制: 0 (原始字节: "00 00 00 00" )
解析到电机位置: 0 (原始字节: "00 00 00 00" )
未找到电机 1 的控制单元
发送10H指令:从站 1 起始寄存器 252 数量 7
10H写入确认:从站 1 电机编号 37 起始寄存器 252 写入数量 7
03H指令错误:寄存器地址超出范围(起始 252 ,数量 7 )