已经和cursor集成,可以在cursor编程了。
authorSnickerSun <snickersun@163.com>
Thu, 27 Nov 2025 05:57:51 +0000 (13:57 +0800)
committerSnickerSun <snickersun@163.com>
Thu, 27 Nov 2025 05:57:51 +0000 (13:57 +0800)
15 files changed:
.vscode/launch.json
.vscode/settings.json
.vscode/tasks.json
AT指令执行路径分析.md [new file with mode: 0644]
README_CURSOR.md [new file with mode: 0644]
Setting.ini
fix_link_order.ps1 [new file with mode: 0644]
mac_address.db [new file with mode: 0644]
mainwindow.cpp
mainwindow.h
mainwindow.ui
rebuild_fixed.ps1 [new file with mode: 0644]
serial_port_context.h [new file with mode: 0644]
实现总结.md [new file with mode: 0644]
统一配置实现方案.md [new file with mode: 0644]

index 8b331a9..9caf0a4 100644 (file)
@@ -5,14 +5,14 @@
             "name": "Debug (GDB)",\r
             "type": "cppdbg",\r
             "request": "launch",\r
-            "program": "${workspaceFolder}/debug/HiBTMacWriteTool.exe",\r
+            "program": "${workspaceFolder}/../build-HiBTMacWriteTool-Desktop_Qt_5_14_2_MinGW_32_bit-Debug/debug/HiBTMacWriteTool.exe",\r
             "args": [],\r
             "stopAtEntry": false,\r
             "cwd": "${workspaceFolder}",\r
             "environment": [\r
                 {\r
                     "name": "PATH",\r
-                    "value": "${env:PATH};d:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin"\r
+                    "value": "D:\\Qt\\Qt5.14.2\\Tools\\mingw730_32\\bin;D:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin;${env:PATH}"\r
                 }\r
             ],\r
             "externalConsole": false,\r
             "name": "Release (GDB)",\r
             "type": "cppdbg",\r
             "request": "launch",\r
-            "program": "${workspaceFolder}/release/HiBTMacWriteTool.exe",\r
+            "program": "${workspaceFolder}/../build-HiBTMacWriteTool-Desktop_Qt_5_14_2_MinGW_32_bit-Debug/release/HiBTMacWriteTool.exe",\r
             "args": [],\r
             "stopAtEntry": false,\r
             "cwd": "${workspaceFolder}",\r
             "environment": [\r
                 {\r
                     "name": "PATH",\r
-                    "value": "${env:PATH};d:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin"\r
+                    "value": "D:\\Qt\\Qt5.14.2\\Tools\\mingw730_32\\bin;D:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin;${env:PATH}"\r
                 }\r
             ],\r
             "externalConsole": false,\r
             "name": "Debug (No Build)",\r
             "type": "cppdbg",\r
             "request": "launch",\r
-            "program": "${workspaceFolder}/debug/HiBTMacWriteTool.exe",\r
+            "program": "${workspaceFolder}/../build-HiBTMacWriteTool-Desktop_Qt_5_14_2_MinGW_32_bit-Debug/debug/HiBTMacWriteTool.exe",\r
             "args": [],\r
             "stopAtEntry": false,\r
             "cwd": "${workspaceFolder}",\r
             "environment": [\r
                 {\r
                     "name": "PATH",\r
-                    "value": "${env:PATH};d:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin"\r
+                    "value": "D:\\Qt\\Qt5.14.2\\Tools\\mingw730_32\\bin;D:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin;${env:PATH}"\r
                 }\r
             ],\r
             "externalConsole": false,\r
index 67b3e2f..b3bc38d 100644 (file)
@@ -26,7 +26,7 @@
     "C_Cpp.default.compilerPath": "d:/Qt/Qt5.14.2/Tools/mingw730_32/bin/g++.exe",\r
     "C_Cpp.default.cStandard": "c11",\r
     "C_Cpp.default.cppStandard": "c++11",\r
-    "C_Cpp.default.intelliSenseMode": "gcc-x64",\r
+    "C_Cpp.default.intelliSenseMode": "gcc-x86",\r
     "files.exclude": {\r
         "**/.git": true,\r
         "**/.svn": true,\r
index f01276a..1888183 100644 (file)
@@ -4,15 +4,19 @@
         {
             "label": "qmake: Configure Project",
             "type": "shell",
-            "command": "qmake",
+            "command": "D:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin\\qmake.exe",
             "args": [
-                "HiBTMacWriteTool.pro"
+                "HiBTMacWriteTool.pro",
+                "-spec",
+                "win32-g++",
+                "CONFIG+=debug",
+                "CONFIG+=qml_debug"
             ],
             "options": {
-                "cwd": "${workspaceFolder}",
+                "cwd": "${workspaceFolder}/../build-HiBTMacWriteTool-Desktop_Qt_5_14_2_MinGW_32_bit-Debug",
                 "env": {
                     "QTDIR": "d:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32",
-                    "PATH": "${env:PATH};d:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin"
+                    "PATH": "D:\\Qt\\Qt5.14.2\\Tools\\mingw730_32\\bin;D:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin;${env:PATH}"
                 }
             },
             "group": {
         {
             "label": "build: Debug",
             "dependsOn": [
-                "fix: Link Order",
                 "clean: Build Files"
             ],
             "type": "shell",
-            "command": "mingw32-make",
+            "command": "D:\\Qt\\Qt5.14.2\\Tools\\mingw730_32\\bin\\mingw32-make.exe",
             "args": [],
             "options": {
                 "cwd": "${workspaceFolder}/../build-HiBTMacWriteTool-Desktop_Qt_5_14_2_MinGW_32_bit-Debug",
                 "env": {
                     "QTDIR": "d:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32",
-                    "PATH": "${env:PATH};d:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin"
+                    "PATH": "D:\\Qt\\Qt5.14.2\\Tools\\mingw730_32\\bin;D:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin;${env:PATH}"
                 }
             },
             "group": {
@@ -93,7 +96,7 @@
                 "fix: Link Order"
             ],
             "type": "shell",
-            "command": "mingw32-make",
+            "command": "D:\\Qt\\Qt5.14.2\\Tools\\mingw730_32\\bin\\mingw32-make.exe",
             "args": [
                 "release"
             ],
                 "cwd": "${workspaceFolder}/../build-HiBTMacWriteTool-Desktop_Qt_5_14_2_MinGW_32_bit-Debug",
                 "env": {
                     "QTDIR": "d:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32",
-                    "PATH": "${env:PATH};d:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin"
+                    "PATH": "D:\\Qt\\Qt5.14.2\\Tools\\mingw730_32\\bin;D:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin;${env:PATH}"
                 }
             },
             "group": "build",
         {
             "label": "clean: Build Files",
             "type": "shell",
-            "command": "mingw32-make",
+            "command": "D:\\Qt\\Qt5.14.2\\Tools\\mingw730_32\\bin\\mingw32-make.exe",
             "args": [
                 "clean"
             ],
                 "cwd": "${workspaceFolder}/../build-HiBTMacWriteTool-Desktop_Qt_5_14_2_MinGW_32_bit-Debug",
                 "env": {
                     "QTDIR": "d:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32",
-                    "PATH": "${env:PATH};d:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin"
+                    "PATH": "D:\\Qt\\Qt5.14.2\\Tools\\mingw730_32\\bin;D:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin;${env:PATH}"
                 }
             },
             "group": "build",
             "problemMatcher": []
         },
+        {
+            "label": "run: Debug",
+            "type": "shell",
+            "command": "${workspaceFolder}/../build-HiBTMacWriteTool-Desktop_Qt_5_14_2_MinGW_32_bit-Debug/debug/HiBTMacWriteTool.exe",
+            "args": [],
+            "options": {
+                "cwd": "${workspaceFolder}",
+                "env": {
+                    "PATH": "D:\\Qt\\Qt5.14.2\\Tools\\mingw730_32\\bin;D:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin;${env:PATH}"
+                }
+            },
+            "group": "test",
+            "dependsOn": "build: Debug",
+            "presentation": {
+                "reveal": "always",
+                "panel": "dedicated",
+                "focus": false
+            },
+            "problemMatcher": []
+        },
+        {
+            "label": "run: Release",
+            "type": "shell",
+            "command": "${workspaceFolder}/../build-HiBTMacWriteTool-Desktop_Qt_5_14_2_MinGW_32_bit-Debug/release/HiBTMacWriteTool.exe",
+            "args": [],
+            "options": {
+                "cwd": "${workspaceFolder}",
+                "env": {
+                    "PATH": "D:\\Qt\\Qt5.14.2\\Tools\\mingw730_32\\bin;D:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin;${env:PATH}"
+                }
+            },
+            "group": "test",
+            "dependsOn": "build: Release",
+            "presentation": {
+                "reveal": "always",
+                "panel": "dedicated",
+                "focus": false
+            },
+            "problemMatcher": []
+        },
         {
             "label": "qmake: Reconfigure",
             "type": "shell",
-            "command": "qmake",
+            "command": "D:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin\\qmake.exe",
             "args": [
-                "HiBTMacWriteTool.pro"
+                "${workspaceFolder}/HiBTMacWriteTool.pro",
+                "-spec",
+                "win32-g++",
+                "CONFIG+=debug",
+                "CONFIG+=qml_debug"
             ],
             "options": {
-                "cwd": "${workspaceFolder}",
+                "cwd": "${workspaceFolder}/../build-HiBTMacWriteTool-Desktop_Qt_5_14_2_MinGW_32_bit-Debug",
                 "env": {
                     "QTDIR": "d:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32",
-                    "PATH": "${env:PATH};d:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin"
+                    "PATH": "D:\\Qt\\Qt5.14.2\\Tools\\mingw730_32\\bin;D:\\Qt\\Qt5.14.2\\5.14.2\\mingw73_32\\bin;${env:PATH}"
                 }
             },
             "group": "build",
diff --git a/AT指令执行路径分析.md b/AT指令执行路径分析.md
new file mode 100644 (file)
index 0000000..aeec766
--- /dev/null
@@ -0,0 +1,105 @@
+# AT指令执行路径分析\r
+\r
+## 执行流程图\r
+\r
+```\r
+spp_connect_1() \r
+  ↓\r
+打开串口,设置working_state_1=true\r
+  ↓\r
+readData1() 持续监听\r
+  ↓\r
+检测到 BOOT_UP_MSG ("yaffs filesystem init start")\r
+  ↓\r
+waiting_cmd1=true, cmd_index_1=0, 获取可用MAC地址\r
+  ↓\r
+检测到 TIME_FOR_CMD ("bt enable_bt_stack ret")\r
+  ↓\r
+uart_send_data1(ATCMD_ADD_VOTE) [cmd_index=0]\r
+  ↓\r
+等待响应结束标志 (OK~)\r
+  ↓\r
+uart_process1() case 0: 处理投票指令\r
+  ↓\r
+cmd_index_1++ → 1\r
+  ↓\r
+uart_send_data1(ATCMD_GET_MAC) [cmd_index=1]\r
+  ↓\r
+等待响应结束标志\r
+  ↓\r
+uart_process1() case 1: 解析MAC地址,检查是否已占用\r
+  ↓\r
+cmd_index_1++ → 2\r
+  ↓\r
+uart_send_data1(ATCMD_SET_MAC) [cmd_index=2]\r
+  ↓\r
+等待响应结束标志\r
+  ↓\r
+uart_process1() case 2: 设置MAC完成\r
+  ↓\r
+cmd_index_1++ → 3\r
+  ↓\r
+uart_send_data1(ATCMD_GET_MAC) [cmd_index=3]\r
+  ↓\r
+等待响应结束标志\r
+  ↓\r
+uart_process1() case 3: 验证MAC地址设置\r
+  ↓\r
+cmd_index_1++ → 4\r
+  ↓\r
+等待 STARTUP_POST_INIT 和 STARTUP_POST_INIT_TASK\r
+  ↓\r
+uart_send_data1(ATCMD_GET_CPUID) [cmd_index=4]\r
+  ↓\r
+等待响应结束标志\r
+  ↓\r
+uart_process1() case 4: 解析CPU ID,保存到数据库\r
+  ↓\r
+cmd_index_1++ → 5\r
+  ↓\r
+uart_send_data1(ATCMD_POWEROFF) [cmd_index=5]\r
+  ↓\r
+等待响应结束标志\r
+  ↓\r
+uart_process1() case 5: 关机完成,显示成功\r
+  ↓\r
+cmd_index_1=-1, 工作完成\r
+```\r
+\r
+## AT指令列表\r
+\r
+| 指令 | 定义 | 用途 | 超时时间 |\r
+|------|------|------|----------|\r
+| ATCMD_ADD_VOTE | `AT^PMADDVOTE\r\n` | 阻止设备休眠 | 1.5秒 |\r
+| ATCMD_GET_MAC | `AT^GETBTMAC\r\n` | 查询MAC地址 | 3秒 |\r
+| ATCMD_SET_MAC | `AT^BTADDR=%1 6\r\n` | 设置MAC地址 | 1.5秒 |\r
+| ATCMD_GET_CPUID | `AT^GETIDS\r\n` | 获取CPU ID | 5秒 |\r
+| ATCMD_POWEROFF | `AT^POWEROFF\r\n` | 关机 | 1.5秒 |\r
+\r
+## 检测信号\r
+\r
+| 信号 | 定义 | 用途 |\r
+|------|------|------|\r
+| BOOT_UP_MSG | `"yaffs filesystem init start"` | 检测设备开机 |\r
+| TIME_FOR_CMD | `"bt enable_bt_stack ret"` | 检测可以发送AT指令的时机 |\r
+| STARTUP_POST_INIT | `"APP\|startup_post_init !"` | 系统启动完成信号1 |\r
+| STARTUP_POST_INIT_TASK | `"APP\|startup_post_init_task !"` | 系统启动完成信号2 |\r
+\r
+## 当前问题\r
+\r
+1. **代码重复**: 只有串口1有完整实现,串口2/3/4只有空函数\r
+2. **变量分散**: 每个串口的状态变量都是独立的(cmd_index_1, uart_rx_flag1等)\r
+3. **难以扩展**: 添加新功能需要修改4个地方\r
+4. **配置不统一**: 每个串口使用相同的配置但代码重复\r
+\r
+## 改进方案\r
+\r
+### 1. 统一配置结构\r
+创建 `SerialPortContext` 结构体,封装每个串口的所有状态\r
+\r
+### 2. 统一处理函数\r
+将 readData1/uart_process1/uart_send_data1 等函数改为模板函数,接受端口索引\r
+\r
+### 3. 4线程独立工作\r
+每个串口使用独立的上下文,互不干扰\r
+\r
diff --git a/README_CURSOR.md b/README_CURSOR.md
new file mode 100644 (file)
index 0000000..6ac746e
--- /dev/null
@@ -0,0 +1,74 @@
+# Cursor/VSCode 编译和运行配置说明\r
+\r
+## 已配置的功能\r
+\r
+### 1. 编译任务 (Tasks)\r
+\r
+在 Cursor/VSCode 中按 `Ctrl+Shift+P`,输入 "Tasks: Run Task",可以选择以下任务:\r
+\r
+- **build: Debug** (默认构建任务)\r
+  - 使用32位MinGW编译Debug版本\r
+  - 路径:`D:\Qt\Qt5.14.2\Tools\mingw730_32\bin\mingw32-make.exe`\r
+  - 构建目录:`../build-HiBTMacWriteTool-Desktop_Qt_5_14_2_MinGW_32_bit-Debug`\r
+\r
+- **build: Release**\r
+  - 使用32位MinGW编译Release版本\r
+\r
+- **clean: Build Files**\r
+  - 清理构建文件\r
+\r
+- **qmake: Configure Project**\r
+  - 重新配置Qt项目\r
+\r
+- **qmake: Reconfigure**\r
+  - 重新生成Makefile\r
+\r
+- **run: Debug**\r
+  - 编译并运行Debug版本(不调试)\r
+\r
+- **run: Release**\r
+  - 编译并运行Release版本(不调试)\r
+\r
+### 2. 调试配置 (Launch)\r
+\r
+按 `F5` 或使用调试面板,可以选择以下配置:\r
+\r
+- **Debug (GDB)**\r
+  - 使用GDB调试器\r
+  - 自动编译后启动调试\r
+  - 可执行文件:`../build-HiBTMacWriteTool-Desktop_Qt_5_14_2_MinGW_32_bit-Debug/debug/HiBTMacWriteTool.exe`\r
+\r
+- **Release (GDB)**\r
+  - 调试Release版本\r
+\r
+- **Debug (No Build)**\r
+  - 直接运行已编译的程序,不重新编译\r
+\r
+### 3. 路径配置\r
+\r
+所有配置都使用32位MinGW工具链:\r
+\r
+- **MinGW工具链**:`D:\Qt\Qt5.14.2\Tools\mingw730_32\bin`\r
+- **Qt库路径**:`D:\Qt\Qt5.14.2\5.14.2\mingw73_32`\r
+- **构建目录**:`D:\workspace\fd230_source_win\build-HiBTMacWriteTool-Desktop_Qt_5_14_2_MinGW_32_bit-Debug`\r
+\r
+### 4. 快速使用\r
+\r
+1. **编译项目**:\r
+   - 按 `Ctrl+Shift+B` (默认构建任务)\r
+   - 或 `Ctrl+Shift+P` → "Tasks: Run Task" → "build: Debug"\r
+\r
+2. **运行项目(不调试)**:\r
+   - `Ctrl+Shift+P` → "Tasks: Run Task" → "run: Debug"\r
+\r
+3. **调试项目**:\r
+   - 按 `F5` 启动调试\r
+   - 或使用调试面板选择配置\r
+\r
+### 5. 注意事项\r
+\r
+- 确保构建目录存在,如果不存在,先运行 "qmake: Configure Project"\r
+- 首次使用前,建议先运行 "qmake: Reconfigure" 生成Makefile\r
+- 所有路径都使用绝对路径,确保在不同环境下都能正常工作\r
+- 使用32位MinGW工具链,与QtCreator保持一致\r
+\r
index e3f6e21..02406f5 100644 (file)
@@ -1,5 +1,5 @@
 [Uart_setting]\r
-uart_com=COM41\r
+uart_com=COM8\r
 uart_baud=18\r
 spp_addr=\r
 \r
diff --git a/fix_link_order.ps1 b/fix_link_order.ps1
new file mode 100644 (file)
index 0000000..f796176
--- /dev/null
@@ -0,0 +1,36 @@
+# 修复 Makefile 中的链接顺序,确保 advapi32 在最后\r
+# 这个脚本会在编译前自动修复链接顺序\r
+\r
+$makefilePath = "D:\workspace\fd230_source_win\build-HiBTMacWriteTool-Desktop_Qt_5_14_2_MinGW_32_bit-Debug\Makefile.Debug"\r
+\r
+if (Test-Path $makefilePath) {\r
+    $content = Get-Content $makefilePath -Raw -Encoding UTF8\r
+    \r
+    # 检查是否已经有 advapi32\r
+    if ($content -match "LIBS\s*=\s*(.*)") {\r
+        $libsLine = $matches[1]\r
+        \r
+        # 如果 advapi32 不在最后,移除它并添加到末尾\r
+        if ($libsLine -match "-ladvapi32" -and $libsLine -notmatch "-ladvapi32\s*$") {\r
+            Write-Host "Fixing link order..." -ForegroundColor Yellow\r
+            $libsLine = $libsLine -replace "\s+-ladvapi32", ""\r
+            $libsLine = $libsLine.TrimEnd() + " -ladvapi32"\r
+            $content = $content -replace "LIBS\s*=\s*.*", "LIBS        =        $libsLine"\r
+            Set-Content $makefilePath $content -NoNewline -Encoding UTF8\r
+            Write-Host "Link order fixed!" -ForegroundColor Green\r
+        } elseif ($libsLine -notmatch "-ladvapi32") {\r
+            # 如果没有 advapi32,添加到末尾\r
+            Write-Host "Adding advapi32 to link command..." -ForegroundColor Yellow\r
+            $libsLine = $libsLine.TrimEnd() + " -ladvapi32"\r
+            $content = $content -replace "LIBS\s*=\s*.*", "LIBS        =        $libsLine"\r
+            Set-Content $makefilePath $content -NoNewline -Encoding UTF8\r
+            Write-Host "advapi32 added!" -ForegroundColor Green\r
+        } else {\r
+            Write-Host "Link order is correct!" -ForegroundColor Green\r
+        }\r
+    }\r
+} else {\r
+    Write-Host "Makefile.Debug not found, skipping link order fix" -ForegroundColor Yellow\r
+    exit 0\r
+}\r
+\r
diff --git a/mac_address.db b/mac_address.db
new file mode 100644 (file)
index 0000000..e69de29
index 0a47afd..89dd459 100644 (file)
@@ -7,57 +7,72 @@
 MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
 {
     ui->setupUi(this);
+    
+    // 初始化串口对象
     serialport1 = new QSerialPort(this);
     serialport2 = new QSerialPort(this);
     serialport3 = new QSerialPort(this);
     serialport4 = new QSerialPort(this);
-
-    spp_timer_handle1 = new QTimer(this);
-    connect(spp_timer_handle1, SIGNAL(timeout()), this, SLOT(spp_timer_callback1()));
-
-    result_thread1 = new Result_Thread(this,1);
-    result_thread2 = new Result_Thread(this,2);
-    result_thread3 = new Result_Thread(this,3);
-    result_thread4 = new Result_Thread(this,4);
-    result_thread1->start();
-    result_thread1->pause();
-    result_thread2->start();
-    result_thread2->pause();
-    result_thread3->start();
-    result_thread3->pause();
-    result_thread4->start();
-    result_thread4->pause();
+    
+    QSerialPort *ports[MAX_SERIAL_PORTS] = {serialport1, serialport2, serialport3, serialport4};
+    
+    // 初始化统一配置结构
+    for (int i = 0; i < MAX_SERIAL_PORTS; i++) {
+        // 创建串口上下文
+        port_contexts[i] = new SerialPortContext(i + 1);
+        
+        // 创建定时器
+        spp_timer_handles[i] = new QTimer(this);
+        
+        // 连接定时器信号(使用lambda捕获端口索引)
+        connect(spp_timer_handles[i], &QTimer::timeout, [this, i]() {
+            this->spp_timer_callback(i);
+        });
+        
+        // 初始化上下文
+        port_contexts[i]->init(ports[i], spp_timer_handles[i]);
+        
+        // 创建结果线程
+        result_threads[i] = new Result_Thread(this, i + 1);
+        result_threads[i]->start();
+        result_threads[i]->pause();
+    }
+    
+    // 向后兼容:映射到数组
+    result_thread1 = result_threads[0];
+    result_thread2 = result_threads[1];
+    result_thread3 = result_threads[2];
+    result_thread4 = result_threads[3];
+    
+    // 向后兼容:保留原有的定时器引用(映射到数组)
+    // 注意:spp_timer_handle1 将在后续代码中通过 port_contexts[0]->spp_timer_handle 访问
+    
     ui_setting_read();
-
 }
 
-void MainWindow::ui_show_result1(QString msg,bool success)
-{
-    ui->label_runtime_status1->setText(msg);
-    if (success)
-    {
-        this->write_success_count1++;
-        ui->label_result_success1->setText(tr("成功%1").arg(write_success_count1));
-    }else{
-        this->write_fail_count1++;
-        ui->label_result_fail1->setText(tr("失败%1").arg(write_fail_count1));
-        poweroff_watch1();
-    }
-    if (spp_timer_handle1->isActive())
-        spp_timer_handle1->stop();
-
-}
+// ui_show_result1已在后面实现为向后兼容函数
 
-void MainWindow::readData1()
+// 统一的readData函数
+void MainWindow::readData(int port_index)
 {
-    const QByteArray data = serialport1->readAll();
-//    qDebug()<<uart_rx_flag1;
-    if(uart_rx_flag1)
-        qDebug()<<data;
+    if (port_index < 0 || port_index >= MAX_SERIAL_PORTS) {
+        qDebug() << tr("无效的端口索引:") << port_index;
+        return;
+    }
+    
+    SerialPortContext *ctx = port_contexts[port_index];
+    if (ctx == nullptr || ctx->serialport == nullptr) {
+        qDebug() << tr("串口上下文未初始化,端口索引:") << port_index;
+        return;
+    }
+    
+    const QByteArray data = ctx->serialport->readAll();
+    // 调试输出
+    if(ctx->uart_rx_flag)
+        qDebug() << tr("端口%1接收数据:").arg(port_index) << data;
 
-if (working_state_1 == false)
-{
-        qDebug() << tr("写号结束,跳过读取串口");
+    if (ctx->working_state == false) {
+        qDebug() << tr("端口%1写号结束,跳过读取串口").arg(port_index);
         return;
     }
     
@@ -67,370 +82,435 @@ if (working_state_1 == false)
     }
     
     // 将新数据添加到开机检测缓存中
-    boot_detect_buffer.append(data);
+    ctx->boot_detect_buffer.append(data);
     
     // 保持缓存大小合理,避免内存过度使用(保留最近8192字节)
-    if (boot_detect_buffer.length() > 8192) {
-        boot_detect_buffer = boot_detect_buffer.right(8192);
+    if (ctx->boot_detect_buffer.length() > 8192) {
+        ctx->boot_detect_buffer = ctx->boot_detect_buffer.right(8192);
         // 只在第一次超过限制时打印,避免重复打印
-        static bool buffer_limit_warned = false;
-        if (!buffer_limit_warned) {
-            qDebug() << tr("开机检测缓存过大,保留最近8192字节");
-            buffer_limit_warned = true;
+        static bool buffer_limit_warned[MAX_SERIAL_PORTS] = {false, false, false, false};
+        if (!buffer_limit_warned[port_index]) {
+            qDebug() << tr("端口%1开机检测缓存过大,保留最近8192字节").arg(port_index);
+            buffer_limit_warned[port_index] = true;
         }
     }
+    
     // 在缓存区中检测开机信号,处理分包情况
-    if (boot_detect_buffer.indexOf(BOOT_UP_MSG)>=0)
-    {
-        this->ui->label_runtime_status1->setText(tr("发现新设备"));
-        waiting_cmd1 = true;
-        cmd_index_1 = 0;
+    if (ctx->boot_detect_buffer.indexOf(BOOT_UP_MSG) >= 0) {
+        UIPortWidgets widgets = getUIPortWidgets(port_index);
+        widgets.label_runtime_status->setText(tr("发现新设备"));
+        ctx->waiting_cmd = true;
+        ctx->cmd_index = 0;
         QString avalible_mac = settings::getInstance().getAvalibleMac();
-        ui->ledit_spp_addr_1->setText(avalible_mac);
-        ui->txtb_dispaly->clear();
+        widgets.ledit_spp_addr->setText(avalible_mac);
+        widgets.txtb_dispaly->clear();
         // 检测到开机信号后清理缓存,避免无限增长
-        boot_detect_buffer.clear();
-        qDebug() << tr("检测到开机信号(yaffs filesystem init start),清理缓存");
-        
+        ctx->boot_detect_buffer.clear();
+        qDebug() << tr("端口%1检测到开机信号(yaffs filesystem init start),清理缓存").arg(port_index);
     }
     
     // 在缓存区中检测MAC地址信息,处理分包情况
-    if (working_state_1 && !waiting_cmd1) {
+    if (ctx->working_state && !ctx->waiting_cmd) {
         // 使用正则表达式在缓存区中查找完整的MAC地址
         QRegExp macRegex("BTMAC=([0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2})");
-        int macPos = macRegex.indexIn(boot_detect_buffer);
+        int macPos = macRegex.indexIn(ctx->boot_detect_buffer);
         if (macPos >= 0) {
             QString foundMac = macRegex.cap(1); // 提取MAC地址部分 (28:11:06:XX:XX:XX)
-            qDebug() << tr("🔍 在开机缓冲区中发现完整MAC地址:") << foundMac;
+            qDebug() << tr("端口%1在开机缓冲区中发现完整MAC地址:").arg(port_index) << foundMac;
             
             // 转换为无冒号格式
             QString macWithoutColon = foundMac.replace(":", "").toUpper();
-            qDebug() << tr("转换后的MAC地址:") << macWithoutColon;
+            qDebug() << tr("端口%1转换后的MAC地址:").arg(port_index) << macWithoutColon;
             
             // 检查MAC地址是否已被使用
             bool mac_used = settings::getInstance().getMacUsed(macWithoutColon);
-            qDebug() << tr("MAC地址是否已被使用:") << mac_used;
+            qDebug() << tr("端口%1 MAC地址是否已被使用:").arg(port_index) << mac_used;
             
             if (mac_used) {
-                ui_display1(tr("手表地址") + macWithoutColon + tr("已占用\r\n"), LOG_DIRECT_OUT);
-                ui_show_result1(tr("Mac地址已占用"), false);
+                ui_display(port_index, tr("手表地址") + macWithoutColon + tr("已占用\r\n"), LOG_DIRECT_OUT);
+                ui_show_result(port_index, tr("Mac地址已占用"), false);
             } else {
-                ui_display1(tr("手表当前地址") + macWithoutColon + tr(" 可用!\r\n"), LOG_DIRECT_IN);
-                qDebug() << tr("✅ 手表当前MAC地址可用:") << macWithoutColon;
+                ui_display(port_index, tr("手表当前地址") + macWithoutColon + tr(" 可用!\r\n"), LOG_DIRECT_IN);
+                qDebug() << tr("端口%1手表当前MAC地址可用:").arg(port_index) << macWithoutColon;
             }
         }
     }
+    
     // 在缓存区中检测命令时机信号,处理分包情况
-    if (waiting_cmd1 && boot_detect_buffer.indexOf(TIME_FOR_CMD)>=0)
-    {
-        uart_send_data1(ATCMD_ADD_VOTE);
+    if (ctx->waiting_cmd && ctx->boot_detect_buffer.indexOf(TIME_FOR_CMD) >= 0) {
+        uart_send_data(port_index, ATCMD_ADD_VOTE);
         // 检测到命令时机后也清理缓存
-        boot_detect_buffer.clear();
-        qDebug() << tr("检测到命令时机信号,清理缓存");
+        ctx->boot_detect_buffer.clear();
+        qDebug() << tr("端口%1检测到命令时机信号,清理缓存").arg(port_index);
     }
     
     // 检测启动完成信号,需要同时检测到两个信号
-    if (waiting_cmd1 && !startup_complete_detected &&
-        boot_detect_buffer.indexOf(STARTUP_POST_INIT) >= 0 && 
-        boot_detect_buffer.indexOf(STARTUP_POST_INIT_TASK) >= 0)
-    {
-        startup_complete_detected = true; // 设置标志,防止重复触发
-        qDebug() << tr("✅ 检测到启动完成信号,系统已完全启动");
-        ui_display1(tr("系统启动完成,可以执行GETIDS\r\n"), LOG_DIRECT_IN);
+    if (ctx->waiting_cmd && !ctx->startup_complete_detected &&
+        ctx->boot_detect_buffer.indexOf(STARTUP_POST_INIT) >= 0 && 
+        ctx->boot_detect_buffer.indexOf(STARTUP_POST_INIT_TASK) >= 0) {
+        ctx->startup_complete_detected = true; // 设置标志,防止重复触发
+        qDebug() << tr("端口%1检测到启动完成信号,系统已完全启动").arg(port_index);
+        ui_display(port_index, tr("系统启动完成,可以执行GETIDS\r\n"), LOG_DIRECT_IN);
         
         // 清理缓存
-        boot_detect_buffer.clear();
-        qDebug() << tr("检测到启动完成信号,清理缓存");
+        ctx->boot_detect_buffer.clear();
+        qDebug() << tr("端口%1检测到启动完成信号,清理缓存").arg(port_index);
         
         // 如果当前正在等待GETIDS执行,且没有AT命令在执行,则触发GETIDS
-        if ((cmd_index_1 == 3 || cmd_index_1 == 4) && !uart_rx_flag1) {
-            qDebug() << tr("🚀 启动完成且正在等待GETIDS,立即触发GETIDS执行");
-            qDebug() << tr("当前cmd_index_1:") << cmd_index_1;
+        if ((ctx->cmd_index == 3 || ctx->cmd_index == 4) && !ctx->uart_rx_flag) {
+            qDebug() << tr("端口%1启动完成且正在等待GETIDS,立即触发GETIDS执行").arg(port_index);
+            qDebug() << tr("端口%1当前cmd_index:").arg(port_index) << ctx->cmd_index;
             
-            if (cmd_index_1 == 3) {
-                cmd_index_1++; // 从3递增到4
-                qDebug() << tr("cmd_index_1从3递增到4");
+            if (ctx->cmd_index == 3) {
+                ctx->cmd_index++; // 从3递增到4
+                qDebug() << tr("端口%1 cmd_index从3递增到4").arg(port_index);
             }
-            // 如果cmd_index_1已经是4,保持不变,重新执行case 4
+            // 如果cmd_index已经是4,保持不变,重新执行case 4
             
             // 清空之前的响应缓冲区,准备接收GETIDS响应
-            uart_rx_buff_array1.clear();
-            qDebug() << tr("清空响应缓冲区,准备执行GETIDS");
+            ctx->uart_rx_buff_array.clear();
+            qDebug() << tr("端口%1清空响应缓冲区,准备执行GETIDS").arg(port_index);
             
             // 重新执行switch逻辑,现在startup_complete_detected = true
-            switch(cmd_index_1) {
+            switch(ctx->cmd_index) {
             case 4:
-                qDebug() << tr("✅ 系统已完全启动,发送GETIDS指令");
-                this->uart_send_data1(ATCMD_GET_CPUID);
+                qDebug() << tr("端口%1系统已完全启动,发送GETIDS指令").arg(port_index);
+                uart_send_data(port_index, ATCMD_GET_CPUID);
                 break;
             default:
-                qDebug() << tr("启动完成回调中的cmd_index_1异常:") << cmd_index_1;
+                qDebug() << tr("端口%1启动完成回调中的cmd_index异常:").arg(port_index) << ctx->cmd_index;
                 break;
             }
         }
     }
 
-    if (uart_rx_flag1)
-    {//指令下达完毕,开始接收数据
-        uart_rx_buff_array1.append(data);
-        qDebug() << tr("📥 AT命令响应数据累积中,当前长度:") << uart_rx_buff_array1.length();
-        qDebug() << tr("📥 当前累积内容:") << uart_rx_buff_array1;
+    if (ctx->uart_rx_flag) {
+        // 指令下达完毕,开始接收数据
+        ctx->uart_rx_buff_array.append(data);
+        qDebug() << tr("端口%1 AT命令响应数据累积中,当前长度:").arg(port_index) << ctx->uart_rx_buff_array.length();
+        qDebug() << tr("端口%1当前累积内容:").arg(port_index) << ctx->uart_rx_buff_array;
         
         // 检查各种可能的结束标志
-        bool hasOK = uart_rx_buff_array1.indexOf("OK~") >= 0;
-        bool hasPowerOff = uart_rx_buff_array1.indexOf("power off device!") >= 0;
-        bool hasDSPPowerDown = uart_rx_buff_array1.indexOf("DSP0 power down") >= 0;
+        bool hasOK = ctx->uart_rx_buff_array.indexOf("OK~") >= 0;
+        bool hasPowerOff = ctx->uart_rx_buff_array.indexOf("power off device!") >= 0;
+        bool hasDSPPowerDown = ctx->uart_rx_buff_array.indexOf("DSP0 power down") >= 0;
         
         // 特殊处理:对于GETBTMAC命令,如果检测到完整的MAC地址响应,认为命令完成
         bool isGetMacComplete = false;
-        qDebug() << tr("🔧 当前命令G_cmd:") << G_cmd;
-        qDebug() << tr("🔧 是否包含GETBTMAC:") << G_cmd.contains("GETBTMAC");
+        qDebug() << tr("端口%1当前命令G_cmd:").arg(port_index) << ctx->G_cmd;
+        qDebug() << tr("端口%1是否包含GETBTMAC:").arg(port_index) << ctx->G_cmd.contains("GETBTMAC");
         
-        if (G_cmd.contains("GETBTMAC")) {
-            qDebug() << tr("🔧 开始GETBTMAC特殊检测");
+        if (ctx->G_cmd.contains("GETBTMAC")) {
+            qDebug() << tr("端口%1开始GETBTMAC特殊检测").arg(port_index);
             // 检查是否包含完整的MAC地址格式和CyweeChipInfo
-            bool hasLocalAddr = uart_rx_buff_array1.indexOf("get nv local_addr") >= 0;
-            bool hasBTMAC = uart_rx_buff_array1.indexOf("BTMAC=") >= 0;
-            bool hasCyweeChipInfo = uart_rx_buff_array1.indexOf("CyweeChipInfo=") >= 0;
+            bool hasLocalAddr = ctx->uart_rx_buff_array.indexOf("get nv local_addr") >= 0;
+            bool hasBTMAC = ctx->uart_rx_buff_array.indexOf("BTMAC=") >= 0;
+            bool hasCyweeChipInfo = ctx->uart_rx_buff_array.indexOf("CyweeChipInfo=") >= 0;
             
-            qDebug() << tr("🔧 检测结果 - hasLocalAddr:") << hasLocalAddr << tr("hasBTMAC:") << hasBTMAC << tr("hasCyweeChipInfo:") << hasCyweeChipInfo;
+            qDebug() << tr("端口%1检测结果 - hasLocalAddr:").arg(port_index) << hasLocalAddr 
+                     << tr("hasBTMAC:") << hasBTMAC << tr("hasCyweeChipInfo:") << hasCyweeChipInfo;
             
             if (hasLocalAddr && hasBTMAC && hasCyweeChipInfo) {
-                qDebug() << tr("🔧 基本条件满足,检查MAC地址格式");
+                qDebug() << tr("端口%1基本条件满足,检查MAC地址格式").arg(port_index);
                 // 进一步检查是否包含完整的MAC地址格式
                 QRegExp completeMacRegex("BTMAC=([0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2})");
-                int macPos = completeMacRegex.indexIn(uart_rx_buff_array1);
-                qDebug() << tr("🔧 MAC地址正则匹配结果:") << macPos;
+                int macPos = completeMacRegex.indexIn(ctx->uart_rx_buff_array);
+                qDebug() << tr("端口%1 MAC地址正则匹配结果:").arg(port_index) << macPos;
                 
                 if (macPos >= 0) {
                     QString foundMac = completeMacRegex.cap(1);
-                    qDebug() << tr("🔧 找到完整MAC地址:") << foundMac;
+                    qDebug() << tr("端口%1找到完整MAC地址:").arg(port_index) << foundMac;
                     isGetMacComplete = true;
-                    qDebug() << tr("✅ GETBTMAC命令响应完整,包含完整MAC地址和CyweeChipInfo");
+                    qDebug() << tr("端口%1 GETBTMAC命令响应完整,包含完整MAC地址和CyweeChipInfo").arg(port_index);
                 }
             }
         } else {
-            qDebug() << tr("🔧 当前命令不是GETBTMAC,跳过GETBTMAC特殊检测");
+            qDebug() << tr("端口%1当前命令不是GETBTMAC,跳过GETBTMAC特殊检测").arg(port_index);
         }
         
+        qDebug() << tr("端口%1结束标志检查 - OK~:").arg(port_index) << hasOK 
+                 << tr("power off:") << hasPowerOff << tr("DSP0 power down:") << hasDSPPowerDown 
+                 << tr("GETMAC完整:") << isGetMacComplete;
         
-        qDebug() << tr("🔍 结束标志检查 - OK~:") << hasOK << tr("power off:") << hasPowerOff << tr("DSP0 power down:") << hasDSPPowerDown << tr("GETMAC完整:") << isGetMacComplete;
-        
-        if (hasOK || hasPowerOff || hasDSPPowerDown || isGetMacComplete)
-        {
-            qDebug() << tr("✅ 检测到结束标志,开始处理AT命令结果");
+        if (hasOK || hasPowerOff || hasDSPPowerDown || isGetMacComplete) {
+            qDebug() << tr("端口%1检测到结束标志,开始处理AT命令结果").arg(port_index);
             
             // 停止超时定时器
-            if (spp_timer_handle1->isActive()) {
-                spp_timer_handle1->stop();
-                qDebug() << tr("🛑 停止AT命令超时定时器");
+            if (ctx->spp_timer_handle && ctx->spp_timer_handle->isActive()) {
+                ctx->spp_timer_handle->stop();
+                qDebug() << tr("端口%1停止AT命令超时定时器").arg(port_index);
             }
             
-            uart_rx_flag1 = false;
-            uart_process1();//开始处理当前指令结果
-if (cmd_index_1 <0)
-            {
-                if (spp_timer_handle1->isActive())
-                    spp_timer_handle1->stop();
-
-                if (uart_rx_buff_array1.indexOf("power off device") >= 0 )
-                {
-                    ui_display1(tr("关机成功\r\n"),LOG_DIRECT_IN);
-}
+            ctx->uart_rx_flag = false;
+            uart_process(port_index); // 开始处理当前指令结果
+            
+            if (ctx->cmd_index < 0) {
+                if (ctx->spp_timer_handle && ctx->spp_timer_handle->isActive()) {
+                    ctx->spp_timer_handle->stop();
+                }
+                
+                if (ctx->uart_rx_buff_array.indexOf("power off device") >= 0) {
+                    ui_display(port_index, tr("关机成功\r\n"), LOG_DIRECT_IN);
+                }
                 return;
             }
-            cmd_index_1 ++; //开始执行下一指令
-            qDebug()<<"next cmdindex "<<cmd_index_1;
-switch(cmd_index_1){
+            
+            ctx->cmd_index++; // 开始执行下一指令
+            qDebug() << tr("端口%1 next cmdindex").arg(port_index) << ctx->cmd_index;
+            
+            UIPortWidgets widgets = getUIPortWidgets(port_index);
+            switch(ctx->cmd_index) {
             case 0:
             {
-
+                // 空操作
             }
+                break;
             case 1:
             {
-                qDebug() << tr("=== 执行case 1: 查询手表MAC地址 ===");
-                this->uart_send_data1(ATCMD_GET_MAC);
+                qDebug() << tr("端口%1执行case 1: 查询手表MAC地址").arg(port_index);
+                uart_send_data(port_index, ATCMD_GET_MAC);
             }
                 break;
             case 2:
             {
-                QString set_mac_cmd=QString(ATCMD_SET_MAC).arg(ui->ledit_spp_addr_1->text());
-                this->uart_send_data1(set_mac_cmd);
+                QString set_mac_cmd = QString(ATCMD_SET_MAC).arg(widgets.ledit_spp_addr->text());
+                uart_send_data(port_index, set_mac_cmd);
             }
                 break;
             case 3:
             {
-                this->uart_send_data1(ATCMD_GET_MAC);
+                uart_send_data(port_index, ATCMD_GET_MAC);
             }
                 break;
             case 4:
             {
                 // 只有在检测到启动完成信号后才发送GETIDS
-                if (startup_complete_detected) {
-                    qDebug() << tr("✅ 系统已完全启动,发送GETIDS指令");
-                    this->uart_send_data1(ATCMD_GET_CPUID);
+                if (ctx->startup_complete_detected) {
+                    qDebug() << tr("端口%1系统已完全启动,发送GETIDS指令").arg(port_index);
+                    uart_send_data(port_index, ATCMD_GET_CPUID);
                 } else {
-                    qDebug() << tr("⏳ 等待系统完全启动信号,暂不发送GETIDS");
-                    ui_display1(tr("等待系统完全启动信号...\r\n"), LOG_DIRECT_OUT);
+                    qDebug() << tr("端口%1等待系统完全启动信号,暂不发送GETIDS").arg(port_index);
+                    ui_display(port_index, tr("等待系统完全启动信号...\r\n"), LOG_DIRECT_OUT);
                     // 保持在case 4,等待启动完成信号
-                    cmd_index_1 = 4;
+                    ctx->cmd_index = 4;
                     return;
                 }
             }
                 break;
             case 5:
             {
-                this->uart_send_data1(ATCMD_POWEROFF);
+                uart_send_data(port_index, ATCMD_POWEROFF);
             }
                 break;
             default:
             {
-                cmd_index_1=-1;
-                if (spp_timer_handle1->isActive())
-                    spp_timer_handle1->stop();
+                ctx->cmd_index = -1;
+                if (ctx->spp_timer_handle && ctx->spp_timer_handle->isActive()) {
+                    ctx->spp_timer_handle->stop();
+                }
             }
                 break;
             }
         }
-        else{
-
-        }
     }
+}
 
-
-
-//        m_timer->stop();
-
-
-
-//    {
-//        ui_display1(data,false);
-//    }
-//    m_console->putData(data);
+// 向后兼容:readData1
+void MainWindow::readData1()
+{
+    readData(0);
 }
+
+// 向后兼容:readData2/3/4
 void MainWindow::readData2()
 {
-    const QByteArray data = serialport2->readAll();
-    qDebug()<<data;
-//    m_console->putData(data);
+    readData(1);
 }
 void MainWindow::readData3()
 {
-    const QByteArray data = serialport3->readAll();
-    qDebug()<<data;
-//    m_console->putData(data);
+    readData(2);
 }
 void MainWindow::readData4()
 {
-    const QByteArray data = serialport4->readAll();
-    qDebug()<<data;
-//    m_console->putData(data);
+    readData(3);
 }
 //  结束线程
 MainWindow::~MainWindow()
 {
-    if (spp_timer_handle1 != nullptr) {
-        spp_timer_handle1->stop();
-        spp_timer_handle1 = nullptr;
-    }
-//    if (spp_connected_handle != nullptr) {
-//        spp_connected_handle->stop();
-//        spp_connected_handle = nullptr;
-//    }
     ui_setting_save();
-    result_thread1->stop();
-    result_thread1->wait();
-    result_thread2->stop();
-    result_thread2->wait();
-    result_thread3->stop();
-    result_thread3->wait();
-    result_thread4->stop();
-    result_thread4->wait();
-
-
-    delete result_thread1;
-    delete result_thread2;
-    delete result_thread3;
-    delete result_thread4;
+    
+    // 停止所有线程和定时器
+    for (int i = 0; i < MAX_SERIAL_PORTS; i++) {
+        if (spp_timer_handles[i] != nullptr) {
+            spp_timer_handles[i]->stop();
+        }
+        if (result_threads[i] != nullptr) {
+            result_threads[i]->stop();
+            result_threads[i]->wait();
+            delete result_threads[i];
+        }
+        if (port_contexts[i] != nullptr) {
+            delete port_contexts[i];
+        }
+    }
+    
     delete ui;
 }
-void MainWindow::poweroff_watch1()
+// 统一的poweroff_watch函数
+void MainWindow::poweroff_watch(int port_index)
 {
-//    cmd_index_1 = 4; //直接执行关机
-    this->uart_send_data1(ATCMD_POWEROFF);
+    if (port_index < 0 || port_index >= MAX_SERIAL_PORTS) {
+        qDebug() << tr("无效的端口索引:") << port_index;
+        return;
+    }
+    
+    uart_send_data(port_index, ATCMD_POWEROFF);
 }
 
-void MainWindow::ui_display1(QString str,bool inOrOut)
+// 向后兼容:poweroff_watch1
+void MainWindow::poweroff_watch1()
 {
+    poweroff_watch(0);
+}
 
-    ui->txtb_dispaly->moveCursor(QTextCursor::End);
-    if(inOrOut){
-        ui->txtb_dispaly->setTextColor(QColor(127, 255, 0));
-    }else{
-        ui->txtb_dispaly->setTextColor(Qt::red);
-    }    
-    ui->txtb_dispaly->insertPlainText(str);
-    ui->txtb_dispaly->moveCursor(QTextCursor::End);
+// 旧的ui_display1/2/3实现已删除,使用统一的ui_display函数
+void MainWindow::ui_display4(QString str,bool inOrOut)
+{
+    ui_display(3, str, inOrOut);
 }
-void MainWindow::ui_display2(QString str,bool inOrOut)
+
+// ==================== 统一处理函数实现 ====================
+
+// 获取指定端口的UI控件
+MainWindow::UIPortWidgets MainWindow::getUIPortWidgets(int port_index)
 {
-//    QTime Time= QTime::currentTime();//获取系统当前的时间
-//    QString str_time = Time.toString("[hh:mm:ss ");//格式化时间
-    ui->txtb_dispaly_2->moveCursor(QTextCursor::End);
-    if(inOrOut){
-        ui->txtb_dispaly_2->setTextColor(QColor(127, 255, 0));
-    }else{
-        ui->txtb_dispaly_2->setTextColor(Qt::red);
+    UIPortWidgets widgets;
+    switch(port_index) {
+    case 0:
+        widgets.txtb_dispaly = ui->txtb_dispaly;
+        widgets.label_runtime_status = ui->label_runtime_status1;
+        widgets.ledit_spp_addr = ui->ledit_spp_addr_1;
+        widgets.label_result_success = ui->label_result_success1;
+        widgets.label_result_fail = ui->label_result_fail1;
+        widgets.cbox_uart_com_select = ui->cbox_uart_com_select_1;
+        widgets.pbtn_spp_reconnect = ui->pbtn_spp_reconnect_1;
+        break;
+    case 1:
+        widgets.txtb_dispaly = ui->txtb_dispaly_2;
+        widgets.label_runtime_status = ui->label_runtime_status2;
+        widgets.ledit_spp_addr = ui->ledit_spp_addr_2;
+        widgets.label_result_success = ui->label_result_success2;
+        widgets.label_result_fail = ui->label_result_fail2;
+        widgets.cbox_uart_com_select = ui->cbox_uart_com_select_2;
+        widgets.pbtn_spp_reconnect = ui->pbtn_spp_reconnect_2;
+        break;
+    case 2:
+        widgets.txtb_dispaly = ui->txtb_dispaly_3;
+        widgets.label_runtime_status = ui->label_runtime_status3;
+        widgets.ledit_spp_addr = ui->ledit_spp_addr_3;
+        widgets.label_result_success = ui->label_result_success3;
+        widgets.label_result_fail = ui->label_result_fail3;
+        widgets.cbox_uart_com_select = ui->cbox_uart_com_select_3;
+        widgets.pbtn_spp_reconnect = ui->pbtn_spp_reconnect_3;
+        break;
+    case 3:
+        widgets.txtb_dispaly = ui->txtb_dispaly_4;
+        widgets.label_runtime_status = ui->label_runtime_status4;
+        widgets.ledit_spp_addr = ui->ledit_spp_addr_4;
+        widgets.label_result_success = ui->label_result_success4;
+        widgets.label_result_fail = ui->label_result_fail4;
+        widgets.cbox_uart_com_select = ui->cbox_uart_com_select_4;
+        widgets.pbtn_spp_reconnect = ui->pbtn_spp_reconnect_4;
+        break;
+    default:
+        widgets.txtb_dispaly = ui->txtb_dispaly;
+        widgets.label_runtime_status = ui->label_runtime_status1;
+        widgets.ledit_spp_addr = ui->ledit_spp_addr_1;
+        widgets.label_result_success = ui->label_result_success1;
+        widgets.label_result_fail = ui->label_result_fail1;
+        widgets.cbox_uart_com_select = ui->cbox_uart_com_select_1;
+        widgets.pbtn_spp_reconnect = ui->pbtn_spp_reconnect_1;
+        break;
     }
-//    if(inOrOut){
-//        str_time.append("IN] : ");
-//    }else{
-//        str_time.append("OUT] : ");
-//    }
-//    str.prepend(str_time);
-//    str+="\r\n";
-    ui->txtb_dispaly_2->insertPlainText(str);
-    ui->txtb_dispaly_2->moveCursor(QTextCursor::End);
+    return widgets;
 }
-void MainWindow::ui_display3(QString str,bool inOrOut)
+
+// 统一的UI显示函数
+void MainWindow::ui_display(int port_index, QString str, bool inOrOut)
 {
-//    QTime Time= QTime::currentTime();//获取系统当前的时间
-//    QString str_time = Time.toString("[hh:mm:ss ");//格式化时间
-    ui->txtb_dispaly_3->moveCursor(QTextCursor::End);
+    if (port_index < 0 || port_index >= MAX_SERIAL_PORTS) {
+        qDebug() << tr("无效的端口索引:") << port_index;
+        return;
+    }
+    
+    UIPortWidgets widgets = getUIPortWidgets(port_index);
+    if (widgets.txtb_dispaly == nullptr) {
+        qDebug() << tr("UI控件未找到,端口索引:") << port_index;
+        return;
+    }
+    
+    widgets.txtb_dispaly->moveCursor(QTextCursor::End);
     if(inOrOut){
-        ui->txtb_dispaly_3->setTextColor(QColor(127, 255, 0));
+        widgets.txtb_dispaly->setTextColor(QColor(127, 255, 0));
     }else{
-        ui->txtb_dispaly_3->setTextColor(Qt::red);
+        widgets.txtb_dispaly->setTextColor(Qt::red);
     }
-//    if(inOrOut){
-//        str_time.append("IN] : ");
-//    }else{
-//        str_time.append("OUT] : ");
-//    }
-//    str.prepend(str_time);
-//    str+="\r\n";
-    ui->txtb_dispaly_3->insertPlainText(str);
-    ui->txtb_dispaly_3->moveCursor(QTextCursor::End);
+    widgets.txtb_dispaly->insertPlainText(str);
+    widgets.txtb_dispaly->moveCursor(QTextCursor::End);
 }
-void MainWindow::ui_display4(QString str,bool inOrOut)
+
+// 统一的结果显示函数
+void MainWindow::ui_show_result(int port_index, QString msg, bool success)
 {
-//    QTime Time= QTime::currentTime();//获取系统当前的时间
-//    QString str_time = Time.toString("[hh:mm:ss ");//格式化时间
-    ui->txtb_dispaly_4->moveCursor(QTextCursor::End);
-    if(inOrOut){
-        ui->txtb_dispaly_4->setTextColor(QColor(127, 255, 0));
-    }else{
-        ui->txtb_dispaly_4->setTextColor(Qt::red);
+    if (port_index < 0 || port_index >= MAX_SERIAL_PORTS) {
+        qDebug() << tr("无效的端口索引:") << port_index;
+        return;
     }
-//    if(inOrOut){
-//        str_time.append("IN] : ");
-//    }else{
-//        str_time.append("OUT] : ");
-//    }
-//    str.prepend(str_time);
-//    str+="\r\n";
-    ui->txtb_dispaly_4->insertPlainText(str);
-    ui->txtb_dispaly_4->moveCursor(QTextCursor::End);
+    
+    SerialPortContext *ctx = port_contexts[port_index];
+    UIPortWidgets widgets = getUIPortWidgets(port_index);
+    
+    if (widgets.label_runtime_status == nullptr) {
+        qDebug() << tr("UI控件未找到,端口索引:") << port_index;
+        return;
+    }
+    
+    widgets.label_runtime_status->setText(msg);
+    if (success) {
+        ctx->write_success_count++;
+        widgets.label_result_success->setText(tr("成功%1").arg(ctx->write_success_count));
+    } else {
+        ctx->write_fail_count++;
+        widgets.label_result_fail->setText(tr("失败%1").arg(ctx->write_fail_count));
+        poweroff_watch(port_index);
+    }
+    if (ctx->spp_timer_handle && ctx->spp_timer_handle->isActive()) {
+        ctx->spp_timer_handle->stop();
+    }
+}
+
+// 向后兼容:ui_display1
+void MainWindow::ui_display1(QString str,bool inOrOut)
+{
+    ui_display(0, str, inOrOut);
+}
+
+// 向后兼容:ui_show_result1
+void MainWindow::ui_show_result1(QString msg,bool success)
+{
+    ui_show_result(0, msg, success);
+}
+
+// 向后兼容:ui_display2
+void MainWindow::ui_display2(QString str,bool inOrOut)
+{
+    ui_display(1, str, inOrOut);
+}
+
+// 向后兼容:ui_display3
+void MainWindow::ui_display3(QString str,bool inOrOut)
+{
+    ui_display(2, str, inOrOut);
 }
 
 void MainWindow::ui_save_windows()
@@ -476,197 +556,188 @@ void MainWindow::ui_setting_read()
 
 
 /* --------------------------------uart操作--------------------------- */
-void MainWindow::uart_process1()
+// 统一的uart_process函数
+void MainWindow::uart_process(int port_index)
 {
-    qDebug()<<"uart_process1 "<< cmd_index_1;
-    //处理指令结果
-    switch(cmd_index_1){
+    if (port_index < 0 || port_index >= MAX_SERIAL_PORTS) {
+        qDebug() << tr("无效的端口索引:") << port_index;
+        return;
+    }
+    
+    SerialPortContext *ctx = port_contexts[port_index];
+    if (ctx == nullptr) {
+        qDebug() << tr("串口上下文未初始化,端口索引:") << port_index;
+        return;
+    }
+    
+    UIPortWidgets widgets = getUIPortWidgets(port_index);
+    
+    qDebug() << tr("端口%1 uart_process").arg(port_index) << ctx->cmd_index;
+    // 处理指令结果
+    switch(ctx->cmd_index) {
     case 0:
-        ui_display1(tr("阻止休眠\r\n"),LOG_DIRECT_IN);
-        qDebug()<<tr("阻止休眠");
-        
-        // 投票指令完成后,如果还没有发送SETUART指令,则立即发送
-        // 已注释:去掉发送AT_SETUART=1
-        /*
-        if (!setuart_sent) {
-            qDebug() << tr("投票指令完成,立即发送SETUART指令");
-            ui_display1(tr("发送SETUART指令\r\n"), LOG_DIRECT_OUT);
-            setuart_sent = true; // 设置标志,防止重复发送
-            this->uart_send_data1(ATCMD_SETUART);
-            return; // 等待SETUART指令完成,不继续执行下一个指令
-        }
-        */
+        ui_display(port_index, tr("阻止休眠\r\n"), LOG_DIRECT_IN);
+        qDebug() << tr("端口%1阻止休眠").arg(port_index);
         break;
     case 1:
     {
-        //检查当前的号是否已经是写过的号,放置重复写号造成的浪费。
-        qDebug() << tr("=== 执行case 1: 查询手表MAC地址 ===");
-        qDebug() << tr("uart_rx_buff_array1长度:") << uart_rx_buff_array1.length();
-        qDebug() << tr("uart_rx_buff_array1内容:") << uart_rx_buff_array1;
-        
+        // 检查当前的号是否已经是写过的号,防止重复写号造成的浪费
+        qDebug() << tr("端口%1执行case 1: 查询手表MAC地址").arg(port_index);
+        qDebug() << tr("端口%1 uart_rx_buff_array长度:").arg(port_index) << ctx->uart_rx_buff_array.length();
+        qDebug() << tr("端口%1 uart_rx_buff_array内容:").arg(port_index) << ctx->uart_rx_buff_array;
         
         // 使用正则表达式查找MAC地址格式: BTMAC=28:11:06:XX:XX:XX,支持多包检测
-        qDebug() << tr("🔍 开始在AT响应中查找MAC地址");
-        qDebug() << tr("当前缓存内容:") << uart_rx_buff_array1;
-        qDebug() << tr("ç¼\93å­\98é\95¿åº¦:") << uart_rx_buff_array1.length();
+        qDebug() << tr("端口%1开始在AT响应中查找MAC地址").arg(port_index);
+        qDebug() << tr("端口%1当前缓存内容:").arg(port_index) << ctx->uart_rx_buff_array;
+        qDebug() << tr("端å\8f£%1ç¼\93å­\98é\95¿åº¦:").arg(port_index) << ctx->uart_rx_buff_array.length();
         
         QRegExp macRegex("BTMAC=([0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2})");
-        int ret = macRegex.indexIn(uart_rx_buff_array1);
-        qDebug() << tr("正则表达式查找结果:") << ret;
+        int ret = macRegex.indexIn(ctx->uart_rx_buff_array);
+        qDebug() << tr("端口%1正则表达式查找结果:").arg(port_index) << ret;
         
         // 如果正则表达式没找到,尝试简单的BTMAC=查找来调试
-        int simple_ret = uart_rx_buff_array1.indexOf("BTMAC=");
-        qDebug() << tr("ç®\80å\8d\95BTMAC=æ\9f¥æ\89¾ç»\93æ\9e\9c:") << simple_ret;
+        int simple_ret = ctx->uart_rx_buff_array.indexOf("BTMAC=");
+        qDebug() << tr("端å\8f£%1ç®\80å\8d\95BTMAC=æ\9f¥æ\89¾ç»\93æ\9e\9c:").arg(port_index) << simple_ret;
         
         if (simple_ret >= 0) {
             // 显示BTMAC=后面的内容,看看是否完整
-            QString after_btmac = uart_rx_buff_array1.mid(simple_ret);
-            qDebug() << tr("BTMAC=后面的内容:") << after_btmac;
+            QString after_btmac = ctx->uart_rx_buff_array.mid(simple_ret);
+            qDebug() << tr("端口%1 BTMAC=后面的内容:").arg(port_index) << after_btmac;
             
             // 备用方法:如果正则表达式失败,尝试手动提取MAC地址
             if (ret < 0) {
-                qDebug() << tr("🔧 正则表达式失败,尝试备用提取方法");
+                qDebug() << tr("端口%1正则表达式失败,尝试备用提取方法").arg(port_index);
                 
                 // 查找BTMAC=后面是否有足够的字符来组成MAC地址
-                QString remaining = uart_rx_buff_array1.mid(simple_ret + 6); // 跳过"BTMAC="
-                qDebug() << tr("BTMAC=后的剩余内容:") << remaining;
+                QString remaining = ctx->uart_rx_buff_array.mid(simple_ret + 6); // 跳过"BTMAC="
+                qDebug() << tr("端口%1 BTMAC=后的剩余内容:").arg(port_index) << remaining;
                 
                 // 尝试提取MAC地址,即使不完整也显示当前状态
                 QRegExp partialMacRegex("([0-9A-Fa-f:]+)");
                 if (partialMacRegex.indexIn(remaining) >= 0) {
                     QString partialMac = partialMacRegex.cap(1);
-                    qDebug() << tr("部分MAC地址:") << partialMac;
+                    qDebug() << tr("端口%1部分MAC地址:").arg(port_index) << partialMac;
                     
                     // 检查是否是完整的MAC地址(应该有5个冒号)
                     int colonCount = partialMac.count(':');
-                    qDebug() << tr("冒号数量:") << colonCount << tr("(完整MAC地址应该有5个冒号)");
+                    qDebug() << tr("端口%1冒号数量:").arg(port_index) << colonCount << tr("(完整MAC地址应该有5个冒号)");
                     
                     if (colonCount == 5) {
-                        qDebug() << tr("✅ 检测到完整MAC地址,使用备用方法处理");
+                        qDebug() << tr("端口%1检测到完整MAC地址,使用备用方法处理").arg(port_index);
                         QString unit = partialMac.replace(":", "").toUpper();
-                        qDebug() << tr("备用方法提取的MAC地址:") << unit;
+                        qDebug() << tr("端口%1备用方法提取的MAC地址:").arg(port_index) << unit;
                         
                         bool mac_used = settings::getInstance().getMacUsed(unit.toUpper());
-                        qDebug() << tr("MAC地址是否已被使用:") << mac_used;
+                        qDebug() << tr("端口%1 MAC地址是否已被使用:").arg(port_index) << mac_used;
                         
                         if (mac_used) {
-                            ui_display1(tr("手表地址")+unit+tr("已占用\r\n"),LOG_DIRECT_OUT);
-                            ui_show_result1(tr("Mac地址已占用"),false);
-                            cmd_index_1 = -1;
+                            ui_display(port_index, tr("手表地址") + unit + tr("已占用\r\n"), LOG_DIRECT_OUT);
+                            ui_show_result(port_index, tr("Mac地址已占用"), false);
+                            ctx->cmd_index = -1;
                         } else {
-                            ui_display1(tr("手表当前地址")+unit+tr(" 可用!\r\n"),LOG_DIRECT_IN);
+                            ui_display(port_index, tr("手表当前地址") + unit + tr(" 可用!\r\n"), LOG_DIRECT_IN);
                         }
                         
                         // 跳过后面的正常处理
                         break;
                     } else {
-                        qDebug() << tr("⚠️ MAC地址不完整,等待更多数据");
+                        qDebug() << tr("端口%1 MAC地址不完整,等待更多数据").arg(port_index);
                     }
                 }
             }
         }
         
-        if (ret >= 0)
-        {
+        if (ret >= 0) {
             QString mac_with_colon = macRegex.cap(1); // 提取MAC地址部分 (28:11:06:4D:29:EF)
-            qDebug() << tr("找到BTMAC=,位置:") << ret;
-            qDebug() << tr("提取的MAC地址(带冒号):") << mac_with_colon;
+            qDebug() << tr("端口%1找到BTMAC=,位置:").arg(port_index) << ret;
+            qDebug() << tr("端口%1提取的MAC地址(带冒号):").arg(port_index) << mac_with_colon;
             
-             QString unit = mac_with_colon.replace(":", "").toUpper(); // "28110604D29EF"
-            qDebug() << tr("处理后的MAC地址(无冒号):") << unit;
+            QString unit = mac_with_colon.replace(":", "").toUpper(); // "28110604D29EF"
+            qDebug() << tr("端口%1处理后的MAC地址(无冒号):").arg(port_index) << unit;
             
             bool mac_used = settings::getInstance().getMacUsed(unit.toUpper());
-            qDebug() << tr("MAC地址是否已被使用:") << mac_used;
+            qDebug() << tr("端口%1 MAC地址是否已被使用:").arg(port_index) << mac_used;
             
-             if (mac_used)
-             {
-                ui_display1(tr("手表地址")+unit+tr("已占用\r\n"),LOG_DIRECT_OUT);
-                ui_show_result1(tr("Mac地址已占用"),false);
-                cmd_index_1 = -1;
-             }else{
-                ui_display1(tr("手表当前地址")+unit+tr(" 可用!\r\n"),LOG_DIRECT_IN);
-             }
-
-        }else{
-             qDebug() << tr("在uart_rx_buff_array1中未找到BTMAC=");
-             qDebug() << tr("完整缓存内容(十六进制):") << uart_rx_buff_array1.toHex();
-             ui_display1(tr("查询手表Mac失败!\r\n"),LOG_DIRECT_OUT);
-             cmd_index_1 = -1;
-             ui_show_result1(tr("查询手表Mac失败"),false);
+            if (mac_used) {
+                ui_display(port_index, tr("手表地址") + unit + tr("已占用\r\n"), LOG_DIRECT_OUT);
+                ui_show_result(port_index, tr("Mac地址已占用"), false);
+                ctx->cmd_index = -1;
+            } else {
+                ui_display(port_index, tr("手表当前地址") + unit + tr(" 可用!\r\n"), LOG_DIRECT_IN);
+            }
+        } else {
+            qDebug() << tr("端口%1在uart_rx_buff_array中未找到BTMAC=").arg(port_index);
+            qDebug() << tr("端口%1完整缓存内容(十六进制):").arg(port_index) << ctx->uart_rx_buff_array.toHex();
+            ui_display(port_index, tr("查询手表Mac失败!\r\n"), LOG_DIRECT_OUT);
+            ctx->cmd_index = -1;
+            ui_show_result(port_index, tr("查询手表Mac失败"), false);
         }
-
     }
         break;
     case 2:
     {
-        QString new_mac = ui->ledit_spp_addr_1->text();
-        ui_display1(tr("执行设置地址\r\n"),LOG_DIRECT_OUT);
-        qDebug() << tr("=== 执行case 2: 设置MAC地址完成 ===");
-        qDebug() << tr("设置的MAC地址:") << new_mac;
-        ui_display1(tr("MAC地址设置完成,等待设备处理...\r\n"), LOG_DIRECT_IN);
+        QString new_mac = widgets.ledit_spp_addr->text();
+        ui_display(port_index, tr("执行设置地址\r\n"), LOG_DIRECT_OUT);
+        qDebug() << tr("端口%1执行case 2: 设置MAC地址完成").arg(port_index);
+        qDebug() << tr("端口%1设置的MAC地址:").arg(port_index) << new_mac;
+        ui_display(port_index, tr("MAC地址设置完成,等待设备处理...\r\n"), LOG_DIRECT_IN);
     }
         break;
     case 3:
     {
         // 验证设置的MAC地址是否成功
-        QString unit = ui->ledit_spp_addr_1->text();
-        qDebug() << tr("=== 执行case 3: 验证设置的MAC地址 ===");
-        qDebug() << tr("期望的MAC地址:") << unit;
-        qDebug() << tr("响应数据长度:") << uart_rx_buff_array1.length();
+        QString unit = widgets.ledit_spp_addr->text();
+        qDebug() << tr("端口%1执行case 3: 验证设置的MAC地址").arg(port_index);
+        qDebug() << tr("端口%1期望的MAC地址:").arg(port_index) << unit;
+        qDebug() << tr("端口%1响应数据长度:").arg(port_index) << ctx->uart_rx_buff_array.length();
         
-        if (uart_rx_buff_array1.length() < 50) {
-            qDebug() << tr("⚠️ 响应数据较短,可能是超时或设备重启中");
+        if (ctx->uart_rx_buff_array.length() < 50) {
+            qDebug() << tr("端口%1响应数据较短,可能是超时或设备重启中").arg(port_index);
         }
         
-        
         // 使用正则表达式查找MAC地址格式: BTMAC=28:11:06:XX:XX:XX,支持多包检测
         QRegExp macRegex("BTMAC=([0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2}:[0-9A-Fa-f]{2})");
-        int ret = macRegex.indexIn(uart_rx_buff_array1);
-        if (ret >= 0)
-        {
+        int ret = macRegex.indexIn(ctx->uart_rx_buff_array);
+        if (ret >= 0) {
             // 提取MAC地址部分
             QString mac_with_colon = macRegex.cap(1); // "28:11:06:4D:29:EF"
-             QString unit_watch = mac_with_colon.replace(":", "").toUpper(); // "28110604D29EF"
+            QString unit_watch = mac_with_colon.replace(":", "").toUpper(); // "28110604D29EF"
             
-            qDebug() << tr("手表返回的MAC地址:") << unit_watch;
-            qDebug() << tr("期望的MAC地址:") << unit;
+            qDebug() << tr("端口%1手表返回的MAC地址:").arg(port_index) << unit_watch;
+            qDebug() << tr("端口%1期望的MAC地址:").arg(port_index) << unit;
             
-            if(unit_watch.toUpper() == unit.toUpper())
-            {
-                ui_display1(tr("设置Mac")+unit_watch+tr("成功\r\n"),LOG_DIRECT_IN);
-             }else{
-                ui_display1(tr("设置Mac")+unit_watch+tr("失败\r\n"),LOG_DIRECT_OUT);
-                cmd_index_1 = -2;
-                ui_show_result1(tr("Mac地址设置失败"),false);
-             }
-
-        }else{
-             ui_display1(tr("设置Mac")+unit+tr("失败\r\n"),LOG_DIRECT_OUT);
-             cmd_index_1 = -3;
-             ui_show_result1(tr("查询手表Mac失败"),false);
+            if (unit_watch.toUpper() == unit.toUpper()) {
+                ui_display(port_index, tr("设置Mac") + unit_watch + tr("成功\r\n"), LOG_DIRECT_IN);
+            } else {
+                ui_display(port_index, tr("设置Mac") + unit_watch + tr("失败\r\n"), LOG_DIRECT_OUT);
+                ctx->cmd_index = -2;
+                ui_show_result(port_index, tr("Mac地址设置失败"), false);
+            }
+        } else {
+            ui_display(port_index, tr("设置Mac") + unit + tr("失败\r\n"), LOG_DIRECT_OUT);
+            ctx->cmd_index = -3;
+            ui_show_result(port_index, tr("查询手表Mac失败"), false);
         }
-
     }
         break;
     case 4:
     {
-        qDebug() << tr("=== 执行case 4: 获取CPU ID ===");
-        qDebug() << tr("响应内容:") << uart_rx_buff_array1;
-        qDebug() << tr("响应长度:") << uart_rx_buff_array1.length();
+        qDebug() << tr("端口%1执行case 4: 获取CPU ID").arg(port_index);
+        qDebug() << tr("端口%1响应内容:").arg(port_index) << ctx->uart_rx_buff_array;
+        qDebug() << tr("端口%1响应长度:").arg(port_index) << ctx->uart_rx_buff_array.length();
         
         // 使用分包检测方式查找CPU ID信息
-        int ret = uart_rx_buff_array1.indexOf("[soc id:]");
-        qDebug() << tr("[soc id:]查找结果:") << ret;
+        int ret = ctx->uart_rx_buff_array.indexOf("[soc id:]");
+        qDebug() << tr("端口%1 [soc id:]查找结果:").arg(port_index) << ret;
         
-        if (ret >= 0)
-        {
+        if (ret >= 0) {
             // 查找[soc id:]后面的内容,直到遇到OK~或其他结束标志
-            QString soc_section = uart_rx_buff_array1.mid(ret);
-            qDebug() << tr("SOC部分内容:") << soc_section;
+            QString soc_section = ctx->uart_rx_buff_array.mid(ret);
+            qDebug() << tr("端口%1 SOC部分内容:").arg(port_index) << soc_section;
             
             // 检查是否包含完整的数据结束标志
             bool hasCompleteData = soc_section.contains("OK~") || soc_section.contains("\r\n\r\n");
-            qDebug() << tr("是否包含完整数据标志:") << hasCompleteData;
+            qDebug() << tr("端口%1是否包含完整数据标志:").arg(port_index) << hasCompleteData;
             
             // 提取所有的十六进制数据(0x开头的),支持分包和多行格式
             QRegExp hexRegex("0x[0-9A-Fa-f]{4}");
@@ -676,11 +747,11 @@ void MainWindow::uart_process1()
             while ((pos = hexRegex.indexIn(soc_section, pos)) != -1) {
                 hexValues << hexRegex.cap(0);
                 pos += hexRegex.matchedLength();
-                qDebug() << tr("找到十六进制值:") << hexRegex.cap(0) << tr("位置:") << pos;
+                qDebug() << tr("端口%1找到十六进制值:").arg(port_index) << hexRegex.cap(0) << tr("位置:") << pos;
             }
             
-            qDebug() << tr("提取的十六进制值:") << hexValues;
-            qDebug() << tr("十六进制值数量:") << hexValues.size();
+            qDebug() << tr("端口%1提取的十六进制值:").arg(port_index) << hexValues;
+            qDebug() << tr("端口%1十六进制值数量:").arg(port_index) << hexValues.size();
             
             // 检查数据完整性:需要至少10个十六进制值且有结束标志
             if (hexValues.size() >= 10 && hasCompleteData) {
@@ -690,92 +761,78 @@ void MainWindow::uart_process1()
                     cpu_id += hex.mid(2); // 去掉"0x"前缀
                 }
                 
-                qDebug() << tr("ç»\84å\90\88ç\9a\84CPU ID:") << cpu_id;
-                ui_display1("cpuid: " + cpu_id + "\r\n", LOG_DIRECT_IN);
+                qDebug() << tr("端å\8f£%1ç»\84å\90\88ç\9a\84CPU ID:").arg(port_index) << cpu_id;
+                ui_display(port_index, "cpuid: " + cpu_id + "\r\n", LOG_DIRECT_IN);
                 
-                int db_ret = settings::getInstance().set_mac_used(ui->ledit_spp_addr_1->text(), cpu_id, true);
-                qDebug() << "set mac used " << ui->ledit_spp_addr_1->text() << " " << cpu_id << " ret " << db_ret;
+                int db_ret = settings::getInstance().set_mac_used(widgets.ledit_spp_addr->text(), cpu_id, true);
+                qDebug() << tr("端口%1 set mac used").arg(port_index) << widgets.ledit_spp_addr->text() << cpu_id << tr("ret") << db_ret;
                 
-                if (db_ret == 1)
-                  {
-                      ui->textBrowser_result->setText(settings::getInstance().getmacStatusFull());
-                    ui_display1(tr("设置mac成功\r\n"), LOG_DIRECT_IN);
+                if (db_ret == 1) {
+                    ui->textBrowser_result->setText(settings::getInstance().getmacStatusFull());
+                    ui_display(port_index, tr("设置mac成功\r\n"), LOG_DIRECT_IN);
                 } else {
-                    ui_show_result1(tr("获取cpuid失败\r\n"), false);
+                    ui_show_result(port_index, tr("获取cpuid失败\r\n"), false);
                 }
             } else {
-                qDebug() << tr("CPU ID数据不完整 - 十六进制值:") << hexValues.size() << tr("完整标志:") << hasCompleteData;
+                qDebug() << tr("端口%1 CPU ID数据不完整 - 十六进制值:").arg(port_index) << hexValues.size() << tr("完整标志:") << hasCompleteData;
                 
                 if (!hasCompleteData) {
-                    qDebug() << tr("ç­\89å¾\85å®\8cæ\95´ç\9a\84AT^GETIDSå\93\8dåº\94æ\95°æ\8d®");
-                    ui_display1(tr("等待CPU ID完整数据...\r\n"), LOG_DIRECT_OUT);
+                    qDebug() << tr("端å\8f£%1ç­\89å¾\85å®\8cæ\95´ç\9a\84AT^GETIDSå\93\8dåº\94æ\95°æ\8d®").arg(port_index);
+                    ui_display(port_index, tr("等待CPU ID完整数据...\r\n"), LOG_DIRECT_OUT);
                     return; // 等待更多数据
                 } else if (hexValues.size() < 10) {
-                    qDebug() << tr("十六进制值数量不足,期望>=10,实际:") << hexValues.size();
-                    ui_display1(tr("CPU ID格式不正确\r\n"), LOG_DIRECT_OUT);
-                 cmd_index_1 = -4;
-                    ui_show_result1(tr("获取CPU ID失败"), false);
+                    qDebug() << tr("端口%1十六进制值数量不足,期望>=10,实际:").arg(port_index) << hexValues.size();
+                    ui_display(port_index, tr("CPU ID格式不正确\r\n"), LOG_DIRECT_OUT);
+                    ctx->cmd_index = -4;
+                    ui_show_result(port_index, tr("获取CPU ID失败"), false);
                 }
             }
         } else {
-            qDebug() << tr("未找到[soc id:]标志,可能数据分包传输中");
-            ui_display1(tr("等待CPU ID数据...\r\n"), LOG_DIRECT_OUT);
+            qDebug() << tr("端口%1未找到[soc id:]标志,可能数据分包传输中").arg(port_index);
+            ui_display(port_index, tr("等待CPU ID数据...\r\n"), LOG_DIRECT_OUT);
             
             // 不使用备用CPU ID,直接失败
-            cmd_index_1 = -4;
-            ui_show_result1(tr("获取CPU ID失败"), false);
+            ctx->cmd_index = -4;
+            ui_show_result(port_index, tr("获取CPU ID失败"), false);
         }
     }
         break;
     case 5:
     {
-        int ret =  uart_rx_buff_array1.indexOf("power off device");
-        if (ret >= 0 )
-        {
-            ui_display1(tr("关机成功\r\n"),LOG_DIRECT_IN);
-        }else{
-            ui_display1(tr("关机失败\r\n"),LOG_DIRECT_OUT);
+        int ret = ctx->uart_rx_buff_array.indexOf("power off device");
+        if (ret >= 0) {
+            ui_display(port_index, tr("关机成功\r\n"), LOG_DIRECT_IN);
+        } else {
+            ui_display(port_index, tr("关机失败\r\n"), LOG_DIRECT_OUT);
         }
-        ui_show_result1(tr("设置mac成功\r\n"),true);
-
+        ui_show_result(port_index, tr("设置mac成功\r\n"), true);
     }
         break;
     default:
     {
-        cmd_index_1=-1;
+        ctx->cmd_index = -1;
     }
         break;
     }
 }
+
+// 向后兼容:uart_process1
+void MainWindow::uart_process1()
+{
+    uart_process(0);
+}
+// 向后兼容:uart_process2/3/4
 void MainWindow::uart_process2()
 {
-//    if (ui->pbtn_open_uart->isChecked()) {
-        QString str_com = ui->cbox_uart_com_select_1->currentText();
-        QString str_uart_baud = ui->cbox_uart_baud_select->currentText();
-//        uart_open(str_com,str_uart_baud);
-//    } else {
-//        uart_close();
-//    }
+    uart_process(1);
 }
 void MainWindow::uart_process3()
 {
-//    if (ui->pbtn_open_uart->isChecked()) {
-        QString str_com = ui->cbox_uart_com_select_1->currentText();
-        QString str_uart_baud = ui->cbox_uart_baud_select->currentText();
-//        uart_open(str_com,str_uart_baud);
-//    } else {
-//        uart_close();
-//    }
+    uart_process(2);
 }
 void MainWindow::uart_process4()
 {
-//    if (ui->pbtn_open_uart->isChecked()) {
-        QString str_com = ui->cbox_uart_com_select_1->currentText();
-        QString str_uart_baud = ui->cbox_uart_baud_select->currentText();
-//        uart_open(str_com,str_uart_baud);
-//    } else {
-//        uart_close();
-//    }
+    uart_process(3);
 }
 //void MainWindow::uart_open(QString com,QString com_baud)
 //{
@@ -785,59 +842,123 @@ void MainWindow::uart_process4()
 //{
 
 //}
-void MainWindow::uart_send_data1(QString cmd)
+// 统一的uart_send_data函数
+void MainWindow::uart_send_data(int port_index, QString cmd)
 {
-    qint64 ret =0;
+    if (port_index < 0 || port_index >= MAX_SERIAL_PORTS) {
+        qDebug() << tr("无效的端口索引:") << port_index;
+        return;
+    }
+    
+    SerialPortContext *ctx = port_contexts[port_index];
+    if (ctx == nullptr || ctx->serialport == nullptr) {
+        qDebug() << tr("串口上下文未初始化,端口索引:") << port_index;
+        return;
+    }
+    
+    qint64 ret = 0;
     
     // 发送AT指令之前清空缓存区,确保响应数据的准确性
-    uart_rx_buff_array1.clear();
-    qDebug() << tr("🧹 发送AT指令前清空缓存区");
+    ctx->uart_rx_buff_array.clear();
+    qDebug() << tr("端口%1发送AT指令前清空缓存区").arg(port_index);
     
-    qDebug()<<"uart_send_data1 "<<cmd;
-    ret=serialport1->write(cmd.toUtf8());
-    m_bytesToWrite1 = ret;
-    qDebug()<<"uart_send_data1 "<<cmd << " ret "<<m_bytesToWrite1;
+    qDebug() << tr("端口%1 uart_send_data").arg(port_index) << cmd;
+    ret = ctx->serialport->write(cmd.toUtf8());
+    ctx->m_bytesToWrite = ret;
+    qDebug() << tr("端口%1 uart_send_data").arg(port_index) << cmd << tr(" ret") << ctx->m_bytesToWrite;
     
-    G_cmd=cmd;
-    if (spp_timer_handle1->isActive())
-        spp_timer_handle1->stop();
+    ctx->G_cmd = cmd;
+    if (ctx->spp_timer_handle && ctx->spp_timer_handle->isActive()) {
+        ctx->spp_timer_handle->stop();
+    }
     
     // 对于特定命令使用更长的超时时间
     if (cmd.contains("GETIDS")) {
-        spp_timer_handle1->start(5000); // 5秒超时
-        qDebug() << tr("GETIDS命令使用5秒超时");
+        ctx->spp_timer_handle->start(5000); // 5秒超时
+        qDebug() << tr("端口%1 GETIDS命令使用5秒超时").arg(port_index);
     } else if (cmd.contains("GETBTMAC")) {
-        spp_timer_handle1->start(3000); // GETBTMAC命令3秒超时
-        qDebug() << tr("GETBTMAC命令使用3秒超时");
+        ctx->spp_timer_handle->start(3000); // GETBTMAC命令3秒超时
+        qDebug() << tr("端口%1 GETBTMAC命令使用3秒超时").arg(port_index);
     } else {
-        spp_timer_handle1->start(1500); // 其他命令1.5秒超时
+        ctx->spp_timer_handle->start(1500); // 其他命令1.5秒超时
     }
-//    ui_display1(cmd,true);
-//    发送指令,在发送结束的handleBytesWritten1中,设置接收状态,
-//    接收函数 readData1 中确认指令是否执行完毕,然后执行下一个指令。
+    // 发送指令,在发送结束的handleBytesWritten中,设置接收状态,
+    // 接收函数 readData 中确认指令是否执行完毕,然后执行下一个指令。
+}
+
+// 向后兼容:uart_send_data1
+void MainWindow::uart_send_data1(QString cmd)
+{
+    uart_send_data(0, cmd);
 }
+// 向后兼容:uart_send_data2/3/4
 void MainWindow::uart_send_data2(QString cmd)
 {
-
+    uart_send_data(1, cmd);
 }
 void MainWindow::uart_send_data3(QString cmd)
 {
-
+    uart_send_data(2, cmd);
 }
 void MainWindow::uart_send_data4(QString cmd)
 {
+    uart_send_data(3, cmd);
+}
+
+// 统一的spp_timer_callback函数
+void MainWindow::spp_timer_callback(int port_index)
+{
+    if (port_index < 0 || port_index >= MAX_SERIAL_PORTS) {
+        qDebug() << tr("无效的端口索引:") << port_index;
+        return;
+    }
+    
+    SerialPortContext *ctx = port_contexts[port_index];
+    if (ctx == nullptr) {
+        qDebug() << tr("串口上下文未初始化,端口索引:") << port_index;
+        return;
+    }
+    
+    ctx->uart_rx_flag = false;
+    qDebug() << tr("端口%1 AT命令超时:").arg(port_index) << ctx->G_cmd;
+    
+    if (ctx->G_cmd == ATCMD_ADD_VOTE) {
+        uart_send_data(port_index, ATCMD_ADD_VOTE);
+    } else if (ctx->G_cmd.contains("GETIDS")) {
+        // GETIDS命令超时,跳过CPU ID获取,继续执行关机
+        ui_display(port_index, tr("获取CPU ID超时,跳过此步骤\r\n"), LOG_DIRECT_OUT);
+        
+        // 直接跳到关机步骤
+        ctx->cmd_index = 4; // 设置为4,这样下次会执行case 5(关机)
+        ctx->uart_rx_flag = false;
+        uart_process(port_index); // 直接处理,跳过CPU ID
+    } else {
+        ui_display(port_index, tr("AT命令超时: %1\r\n").arg(ctx->G_cmd), LOG_DIRECT_OUT);
+        if (ctx->spp_timer_handle && ctx->spp_timer_handle->isActive()) {
+            ctx->spp_timer_handle->stop();
+        }
+    }
+}
 
+// 向后兼容:spp_timer_callback1
+void MainWindow::spp_timer_callback1()
+{
+    spp_timer_callback(0);
 }
 // uart收到的数据进行回显到显示栏
 void MainWindow::uart_rx_dispaly1(int buf_len, u8Piont buf)
 {
-    uart_rx_flag1 = true;
-    if (uart_rx_Ignoring_display) {
-        QString str((char *)buf);
-        if(str.contains("ADDR")){
+    // 使用端口0的上下文
+    SerialPortContext *ctx = port_contexts[0];
+    if (ctx) {
+        ctx->uart_rx_flag = true;
+        if (ctx->uart_rx_Ignoring_display) {
+            QString str((char *)buf);
+            if(str.contains("ADDR")){
 //            ui->ledit_dongle_mac->setText(str.mid(str.indexOf("=",0)+1,12));
+            }
+            return;
         }
-        return;
     }
     QString str;
     QByteArray data((const char*)buf, buf_len);
@@ -937,205 +1058,187 @@ void MainWindow::spp_connected_callback()
 {
     ui_display1("com send cmd failed! ",false);
 }
+// 向后兼容:spp_timer_callback2/3/4
 void MainWindow::spp_timer_callback2()
 {
-
+    spp_timer_callback(1);
 }
 void MainWindow::spp_timer_callback3()
 {
-
+    spp_timer_callback(2);
 }
 void MainWindow::spp_timer_callback4()
 {
-
+    spp_timer_callback(3);
 }
 
-void MainWindow::spp_timer_callback1()
-{
-   uart_rx_flag1 = false;
-   qDebug() << tr("AT命令超时:") << G_cmd;
-   
-   if(G_cmd==ATCMD_ADD_VOTE)
-   {
-       this->uart_send_data1(ATCMD_ADD_VOTE);
-   }
-   else if(G_cmd.contains("GETIDS"))
-   {
-       // GETIDS命令超时,跳过CPU ID获取,继续执行关机
-       ui_display1(tr("获取CPU ID超时,跳过此步骤\r\n"), LOG_DIRECT_OUT);
-       
-       // 直接跳到关机步骤
-       cmd_index_1 = 4; // 设置为4,这样下次会执行case 5(关机)
-       uart_rx_flag1 = false;
-       uart_process1(); // 直接处理,跳过CPU ID
-   }
-   else
-   {
-       ui_display1(tr("AT命令超时: %1\r\n").arg(G_cmd), LOG_DIRECT_OUT);
-       if (spp_timer_handle1->isActive())
-           spp_timer_handle1->stop();
-   }
-}
+// spp_timer_callback1已在后面实现为向后兼容函数
 
-void MainWindow::spp_connect_1()
+// 统一的spp_connect函数
+void MainWindow::spp_connect(int port_index)
 {
-    if (working_state_1 == false)
-    {
+    if (port_index < 0 || port_index >= MAX_SERIAL_PORTS) {
+        qDebug() << tr("无效的端口索引:") << port_index;
+        return;
+    }
+    
+    SerialPortContext *ctx = port_contexts[port_index];
+    if (ctx == nullptr || ctx->serialport == nullptr) {
+        qDebug() << tr("串口上下文未初始化,端口索引:") << port_index;
+        return;
+    }
+    
+    UIPortWidgets widgets = getUIPortWidgets(port_index);
+    
+    if (ctx->working_state == false) {
+        // 开始工作
         QString baud_rate = ui->cbox_uart_baud_select->currentText();
-        QString com_name = ui->cbox_uart_com_select_1->currentText();
+        QString com_name = widgets.cbox_uart_com_select->currentText();
 
-        qDebug() << tr("=== 开始连接串口1 ===");
+        qDebug() << tr("=== 开始连接串口%1 ===").arg(port_index + 1);
         qDebug() << tr("串口名称:") << com_name;
         qDebug() << tr("波特率:") << baud_rate;
 
-        serialport1->setPortName(com_name);
-        serialport1->setBaudRate(baud_rate.toInt());
+        ctx->serialport->setPortName(com_name);
+        ctx->serialport->setBaudRate(baud_rate.toInt());
         // 设置串口参数以提高兼容性
-        serialport1->setDataBits(QSerialPort::Data8);
-        serialport1->setParity(QSerialPort::NoParity);
-        serialport1->setStopBits(QSerialPort::OneStop);
-        serialport1->setFlowControl(QSerialPort::NoFlowControl);
+        ctx->serialport->setDataBits(QSerialPort::Data8);
+        ctx->serialport->setParity(QSerialPort::NoParity);
+        ctx->serialport->setStopBits(QSerialPort::OneStop);
+        ctx->serialport->setFlowControl(QSerialPort::NoFlowControl);
         
         // 设置更大的读缓冲区,提高数据处理能力
-        serialport1->setReadBufferSize(32768); // 32KB缓冲区
+        ctx->serialport->setReadBufferSize(32768); // 32KB缓冲区
         
-        qDebug() << tr("串口配置 - 波特率:") << serialport1->baudRate();
-        qDebug() << tr("串口配置 - 数据位:") << serialport1->dataBits();
-        qDebug() << tr("串口配置 - 停止位:") << serialport1->stopBits();
-        qDebug() << tr("串口配置 - 校验位:") << serialport1->parity();
-        qDebug() << tr("串口配置 - 流控制:") << serialport1->flowControl();
-        qDebug() << tr("串口读缓冲区大小:") << serialport1->readBufferSize();
-
-        ui->txtb_dispaly->clear();
-        if (serialport1->isOpen())
-        {
-            qDebug() << tr("串口已经打开,重置命令索引");
-            this->cmd_index_1 = 0;
-//            this->uart_send_data1(ATCMD_GET_MAC);
-
-    //
-        }else{
-           if (serialport1->open(QIODevice::ReadWrite)) {
-    //        serialport1->setEnabled(true);
-    //        serialport1->setLocalEchoEnabled(false);
-
-            qDebug() << tr("串口打开成功,连接信号槽");
-            connect(serialport1, &QSerialPort::readyRead, this, &MainWindow::readData1);
-            connect(serialport1, &QSerialPort::bytesWritten, this, &MainWindow::handleBytesWritten1);
-this->cmd_index_1 = 0;
-//            this->uart_send_data1(ATCMD_GET_MAC);
-    //        serialport1->close();
-    //        disconnect(serialport1, &QSerialPort::readyRead, this, &MainWindow::readData1);
-
+        qDebug() << tr("端口%1串口配置 - 波特率:").arg(port_index) << ctx->serialport->baudRate();
+        qDebug() << tr("端口%1串口配置 - 数据位:").arg(port_index) << ctx->serialport->dataBits();
+        qDebug() << tr("端口%1串口配置 - 停止位:").arg(port_index) << ctx->serialport->stopBits();
+        qDebug() << tr("端口%1串口配置 - 校验位:").arg(port_index) << ctx->serialport->parity();
+        qDebug() << tr("端口%1串口配置 - 流控制:").arg(port_index) << ctx->serialport->flowControl();
+        qDebug() << tr("端口%1串口读缓冲区大小:").arg(port_index) << ctx->serialport->readBufferSize();
+
+        widgets.txtb_dispaly->clear();
+        if (ctx->serialport->isOpen()) {
+            qDebug() << tr("端口%1串口已经打开,重置命令索引").arg(port_index);
+            ctx->cmd_index = 0;
+        } else {
+            if (ctx->serialport->open(QIODevice::ReadWrite)) {
+                qDebug() << tr("端口%1串口打开成功,连接信号槽").arg(port_index);
+                
+                // 使用lambda捕获port_index来连接信号槽
+                connect(ctx->serialport, &QSerialPort::readyRead, [this, port_index]() {
+                    this->readData(port_index);
+                });
+                connect(ctx->serialport, &QSerialPort::bytesWritten, [this, port_index](qint64 bytes) {
+                    this->handleBytesWritten(port_index, bytes);
+                });
+                
+                ctx->cmd_index = 0;
             } else {
-                qDebug() << tr("串口打开失败:") << serialport1->errorString();
-                QMessageBox::critical(this, tr("Error"), serialport1->errorString());
-
-                ui_display1(tr("Open error\r\n"),false);
+                qDebug() << tr("端口%1串口打开失败:").arg(port_index) << ctx->serialport->errorString();
+                QMessageBox::critical(this, tr("Error"), ctx->serialport->errorString());
+                ui_display(port_index, tr("Open error\r\n"), false);
                 return;
             }
         }
 
-        //        开始工作
-        qDebug() << tr("=== 开始写地址工作模式 ===");
-        qDebug() << tr("系统信息 - Qt版本:") << QT_VERSION_STR;
-        qDebug() << tr("系统信息 - 编译器:") << 
-        #ifdef _MSC_VER
-            "MSVC " + QString::number(_MSC_VER);
-        #elif defined(__GNUC__)
-            "GCC " + QString::number(__GNUC__) + "." + QString::number(__GNUC_MINOR__);
-        #else
-            "Unknown";
-        #endif
-        working_state_1 = true;
-        write_fail_count1= 0;
-        write_success_count1 =0;
-        
+        // 开始工作
+        qDebug() << tr("端口%1开始写地址工作模式").arg(port_index);
+        ctx->working_state = true;
+        ctx->write_fail_count = 0;
+        ctx->write_success_count = 0;
         
         // 初始化开机检测缓存
-        boot_detect_buffer.clear();
-        waiting_cmd1 = false; // 重置等待命令状态
-        startup_complete_detected = false; // 重置启动完成检测标志
-        // setuart_sent = false; // 重置SETUART指令发送标志 (已注释:不再使用SETUART)
-        qDebug() << tr("初始化开机检测缓存");
-        
+        ctx->boot_detect_buffer.clear();
+        ctx->waiting_cmd = false; // 重置等待命令状态
+        ctx->startup_complete_detected = false; // 重置启动完成检测标志
+        qDebug() << tr("端口%1初始化开机检测缓存").arg(port_index);
         
-        ui->label_result_fail1->setText(tr("失败%1").arg(write_fail_count1));
-        ui->label_result_success1->setText(tr("成功%1").arg(write_success_count1));
-        ui->pbtn_spp_reconnect_1->setText(tr("停止写地址"));
-ui->label_runtime_status1->setText(tr("等待手表开机"));
+        widgets.label_result_fail->setText(tr("失败%1").arg(ctx->write_fail_count));
+        widgets.label_result_success->setText(tr("成功%1").arg(ctx->write_success_count));
+        widgets.pbtn_spp_reconnect->setText(tr("停止写地址"));
+        widgets.label_runtime_status->setText(tr("等待手表开机"));
         
-        qDebug() << tr("工作状态设置: working_state_1 = true");
-        qDebug() << tr("等待检测手表开机信号:") << BOOT_UP_MSG;
-        qDebug() << tr("等待检测命令时机信号:") << TIME_FOR_CMD;
-
-//        QString avalible_mac = settings::getInstance().getAvalibleMac();
-//        ui->ledit_spp_addr_1->setText(avalible_mac);
-//        int ret =0;
-    //  ret = settings::getInstance().set_mac_used(avalible_mac,"",true);
-
-    //    qDebug()<< "set mac "<< avalible_mac<<" used , ret "<< ret;
-
+        qDebug() << tr("端口%1工作状态设置: working_state = true").arg(port_index);
+        qDebug() << tr("端口%1等待检测手表开机信号:").arg(port_index) << BOOT_UP_MSG;
+        qDebug() << tr("端口%1等待检测命令时机信号:").arg(port_index) << TIME_FOR_CMD;
 
-        qDebug()<<settings::getInstance().getmacStatusFull();
-
-
-
-    }else{
-        //停止工作
-        qDebug() << tr("=== 停止写地址工作模式 ===");
-        ui->pbtn_spp_reconnect_1->setText(tr("开始写地址"));
-        ui->label_runtime_status1->setText(tr("已停止写地址..."));
-        working_state_1 = false;
+        qDebug() << settings::getInstance().getmacStatusFull();
+    } else {
+        // 停止工作
+        qDebug() << tr("端口%1停止写地址工作模式").arg(port_index);
+        widgets.pbtn_spp_reconnect->setText(tr("开始写地址"));
+        widgets.label_runtime_status->setText(tr("已停止写地址..."));
+        ctx->working_state = false;
         
         // 清空开机检测缓存
-        boot_detect_buffer.clear();
-        qDebug() << tr("清空开机检测缓存");
+        ctx->boot_detect_buffer.clear();
+        qDebug() << tr("端口%1清空开机检测缓存").arg(port_index);
         
-        ui->txtb_dispaly->clear();
-        if(serialport1->isOpen())
-            serialport1->close();
-        disconnect(serialport1, &QSerialPort::readyRead, this, &MainWindow::readData1);
-        disconnect(serialport1, &QSerialPort::bytesWritten, this, &MainWindow::handleBytesWritten1);
-
-
+        widgets.txtb_dispaly->clear();
+        if (ctx->serialport->isOpen()) {
+            ctx->serialport->close();
+        }
+        disconnect(ctx->serialport, &QSerialPort::readyRead, this, nullptr);
+        disconnect(ctx->serialport, &QSerialPort::bytesWritten, this, nullptr);
     }
-      
+}
 
-//    this->serialport1->setBaudRate()
-//    ui_display1("connect com1 ",false);
+// 向后兼容:spp_connect_1
+void MainWindow::spp_connect_1()
+{
+    spp_connect(0);
 }
 
 
-void MainWindow::handleBytesWritten1(qint64 bytes)
+// 统一的handleBytesWritten函数
+void MainWindow::handleBytesWritten(int port_index, qint64 bytes)
 {
-    qDebug()<<" handleBytesWritten1 m_bytesToWrite1 "<<m_bytesToWrite1<<" written " <<bytes;
-    m_bytesToWrite1 -= bytes;
-    if (m_bytesToWrite1 == 0)
-    {
-        uart_rx_flag1 = true;
-        uart_rx_buff_array1.clear();
+    if (port_index < 0 || port_index >= MAX_SERIAL_PORTS) {
+        qDebug() << tr("无效的端口索引:") << port_index;
+        return;
+    }
+    
+    SerialPortContext *ctx = port_contexts[port_index];
+    if (ctx == nullptr) {
+        qDebug() << tr("串口上下文未初始化,端口索引:") << port_index;
+        return;
+    }
+    
+    qDebug() << tr("端口%1 handleBytesWritten m_bytesToWrite").arg(port_index) << ctx->m_bytesToWrite << tr("written") << bytes;
+    ctx->m_bytesToWrite -= bytes;
+    if (ctx->m_bytesToWrite == 0) {
+        ctx->uart_rx_flag = true;
+        ctx->uart_rx_buff_array.clear();
     }
 }
+
+// 向后兼容:handleBytesWritten1
+void MainWindow::handleBytesWritten1(qint64 bytes)
+{
+    handleBytesWritten(0, bytes);
+}
+// 向后兼容:spp_connect_2/3/4
 void MainWindow::spp_connect_2()
 {
-    ui_display2("connect com1 ",false);
-
+    spp_connect(1);
 }
 void MainWindow::spp_connect_3()
 {
-    ui_display3("connect com1 ",false);
-
+    spp_connect(2);
 }
 void MainWindow::spp_connect_4()
 {
-    ui_display4("connect com1 ",false);
-
+    spp_connect(3);
 }
 
 void MainWindow::spp_connect_all()
 {
-    uart_rx_Ignoring_display = true;
+    // 使用端口0的上下文
+    SerialPortContext *ctx = port_contexts[0];
+    if (ctx) {
+        ctx->uart_rx_Ignoring_display = true;
+    }
 //    dongle_is_connected = false;
 //    dongle_try_count = 0;
 //    spp_try_count = 0;
@@ -1144,7 +1247,9 @@ void MainWindow::spp_connect_all()
     ui_display1("spp connectting...",false);
 
     // spp查询定时器周期为1500ms
-    spp_timer_handle1->start(1500);
+    if (spp_timer_handles[0]) {
+        spp_timer_handles[0]->start(1500);
+    }
 //    ui->pbtn_spp_connect->setEnabled(false);
 }
 
index 609d94d..eedfe6c 100644 (file)
 #include "sqldbmanager.h"
 
 #include "settings.h"
+#include "serial_port_context.h"
+#include <QTextBrowser>
+#include <QLabel>
+#include <QLineEdit>
+#include <QComboBox>
+#include <QPushButton>
 
 #define COM_NUMBER 10
+#define MAX_SERIAL_PORTS 4
 
 // 封装了UI上需要调用的所有函数接口
 QT_BEGIN_NAMESPACE
@@ -42,32 +49,52 @@ private:
     bool LOG_DIRECT_OUT=false;
     bool LOG_DIRECT_IN=true;
     /* ------------------------uart------------------------------- */
-    Result_Thread *result_thread1;
-
-
-    /*----------写地址任务相关变量---------------*/
+    // 统一配置:4个串口的上下文数组
+    SerialPortContext *port_contexts[MAX_SERIAL_PORTS];
+    QTimer *spp_timer_handles[MAX_SERIAL_PORTS];
+    Result_Thread *result_threads[MAX_SERIAL_PORTS];
+    
+    // 向后兼容:保留原有变量名(映射到port_contexts[0])
+    // 这些变量将在实现中通过宏或内联函数映射到port_contexts[0]
     QSerialPort *serialport1;
-    //指令长度
-    qint64 m_bytesToWrite1=0;
-    //指令顺序, AT =0 , SET_MAC = 1 , GET_MAC = 2 , GET_CPUINFO = 3;
-    int cmd_index_1=0;
-    int write_success_count1=0;
-    int write_fail_count1=0;
-
-    // 是否忽略uart数据,不回显
-    bool uart_rx_Ignoring_display {false};
-    // 是否有uart通路数据上报
-    bool uart_rx_flag1 {false};
-    QByteArray uart_rx_buff_array1;
-    QTimer *spp_timer_handle1 {nullptr};
-    bool working_state_1=false; //true 说明写号执行过程中,false说明写号结束
-    bool waiting_cmd1 = false; //等待命令时机
-    bool startup_complete_detected = false; //启动完成信号已检测标志
-    // bool setuart_sent = false; //SETUART指令是否已发送标志 (已注释:不再使用SETUART)
-    QByteArray boot_detect_buffer; //用于缓存开机检测数据,处理分包情况
+    QSerialPort *serialport2;
+    QSerialPort *serialport3;
+    QSerialPort *serialport4;
+    Result_Thread *result_thread1;
+    Result_Thread *result_thread2;
+    Result_Thread *result_thread3;
+    Result_Thread *result_thread4;
+    
+    // UI控件映射辅助结构
+    struct UIPortWidgets {
+        QTextBrowser *txtb_dispaly;
+        QLabel *label_runtime_status;
+        QLineEdit *ledit_spp_addr;
+        QLabel *label_result_success;
+        QLabel *label_result_fail;
+        QComboBox *cbox_uart_com_select;  // 串口选择框
+        QPushButton *pbtn_spp_reconnect;  // 连接按钮
+    };
+    
+    // 获取指定端口的UI控件
+    UIPortWidgets getUIPortWidgets(int port_index);
+    
+    // 统一处理函数(支持多端口)
+    void readData(int port_index);
+    void uart_process(int port_index);
+    void uart_send_data(int port_index, QString cmd);
+    void handleBytesWritten(int port_index, qint64 bytes);
+    void spp_timer_callback(int port_index);
+    void spp_connect(int port_index);
+    void ui_display(int port_index, QString str, bool inOrOut);
+    void ui_show_result(int port_index, QString msg, bool success);
+    void poweroff_watch(int port_index);
+    
+    // 向后兼容:保留原有函数名(调用统一函数,port_index=0)
     void ui_display1(QString str,bool inOrOut);
     void ui_show_result1(QString msg,bool success);
     void poweroff_watch1();
+    void uart_send_data1(QString cmd);
 
     /*----------写地址任务相关变量---end------------*/
 
@@ -83,16 +110,6 @@ private:
 //    int dongle_try_count {0};
 //    int spp_try_count {0};
 
-    void uart_send_data1(QString cmd);
-
-
-    QSerialPort *serialport2;
-    QSerialPort *serialport3;
-    QSerialPort *serialport4;
-    Result_Thread *result_thread2;
-    Result_Thread *result_thread3;
-    Result_Thread *result_thread4;
-
 
     /* -------------------------UI------------------------------- */
     enum ui_page{
@@ -103,6 +120,7 @@ private:
     void ui_setting_read();
 
 
+    // 向后兼容:保留原有函数名(调用统一函数)
     void ui_display2(QString str,bool inOrOut);
     void ui_display3(QString str,bool inOrOut);
     void ui_display4(QString str,bool inOrOut);
index bbd187a..3d8081f 100644 (file)
      </item>\r
      <item>\r
       <widget class="QPushButton" name="pbtn_spp_connect_all">\r
-       <property name="enabled">\r
-        <bool>false</bool>\r
-       </property>\r
-       <property name="sizePolicy">\r
-        <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
-         <horstretch>0</horstretch>\r
-         <verstretch>0</verstretch>\r
-        </sizepolicy>\r
-       </property>\r
-       <property name="font">\r
-        <font>\r
-         <family>Arial</family>\r
-         <pointsize>14</pointsize>\r
-         <weight>50</weight>\r
-         <bold>false</bold>\r
-        </font>\r
-       </property>\r
-       <property name="text">\r
-        <string>全部开始写地址</string>\r
-       </property>\r
-       <property name="checkable">\r
-        <bool>false</bool>\r
-       </property>\r
-      </widget>\r
-     </item>\r
-     <item>\r
-      <widget class="QPushButton" name="pushButton_open_mac_config">\r
        <property name="enabled">\r
         <bool>true</bool>\r
        </property>\r
         </font>\r
        </property>\r
        <property name="text">\r
-        <string>设置Mac地址</string>\r
+        <string>全部开始测试</string>\r
        </property>\r
        <property name="checkable">\r
         <bool>false</bool>\r
         <string>&lt;!DOCTYPE HTML PUBLIC &quot;-//W3C//DTD HTML 4.0//EN&quot; &quot;http://www.w3.org/TR/REC-html40/strict.dtd&quot;&gt;\r
 &lt;html&gt;&lt;head&gt;&lt;meta name=&quot;qrichtext&quot; content=&quot;1&quot; /&gt;&lt;style type=&quot;text/css&quot;&gt;\r
 p, li { white-space: pre-wrap; }\r
-&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Arial'; font-size:14pt; font-weight:400; font-style:normal;&quot;&gt;\r
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'黑体'; font-size:9pt;&quot;&gt;28110601012D 至&lt;/span&gt;&lt;/p&gt;\r
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'黑体'; font-size:9pt;&quot;&gt;2811060287CD&lt;/span&gt;&lt;/p&gt;\r
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'黑体'; font-size:9pt;&quot;&gt;共 100000 地址&lt;/span&gt;&lt;/p&gt;\r
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'黑体'; font-size:9pt;&quot;&gt;截止:2024-11-1&lt;/span&gt;&lt;/p&gt;\r
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'黑体'; font-size:9pt;&quot;&gt;已成功写入 0 地址&lt;/span&gt;&lt;/p&gt;\r
-&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;&lt;span style=&quot; font-family:'黑体'; font-size:9pt;&quot;&gt;还剩余 1000 地址&lt;/span&gt;&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>\r
+&lt;/style&gt;&lt;/head&gt;&lt;body style=&quot; font-family:'Arial','Arial','黑体'; font-size:14pt; font-weight:400; font-style:normal;&quot;&gt;\r
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;已测试xxx设备&lt;/p&gt;\r
+&lt;p style=&quot; margin-top:0px; margin-bottom:0px; margin-left:0px; margin-right:0px; -qt-block-indent:0; text-indent:0px;&quot;&gt;xxx成功,xxx失败。&lt;/p&gt;&lt;/body&gt;&lt;/html&gt;</string>\r
        </property>\r
       </widget>\r
      </item>\r
@@ -359,7 +328,7 @@ p, li { white-space: pre-wrap; }
          </font>\r
         </property>\r
         <property name="text">\r
-         <string>开始写地址</string>\r
+         <string>开始测试</string>\r
         </property>\r
         <property name="checkable">\r
          <bool>false</bool>\r
@@ -433,7 +402,7 @@ font: 75 18pt &quot;Agra&quot;;</string>
       <item>\r
        <widget class="QLabel" name="label_runtime_status1">\r
         <property name="text">\r
-         <string>已停止写地址...</string>\r
+         <string>已停止测试...</string>\r
         </property>\r
        </widget>\r
       </item>\r
@@ -497,7 +466,7 @@ font: 75 18pt &quot;Agra&quot;;</string>
       <item>\r
        <widget class="QPushButton" name="pbtn_spp_reconnect_2">\r
         <property name="enabled">\r
-         <bool>false</bool>\r
+         <bool>true</bool>\r
         </property>\r
         <property name="sizePolicy">\r
          <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
@@ -514,7 +483,7 @@ font: 75 18pt &quot;Agra&quot;;</string>
          </font>\r
         </property>\r
         <property name="text">\r
-         <string>开始写地址</string>\r
+         <string>开始测试</string>\r
         </property>\r
         <property name="checkable">\r
          <bool>false</bool>\r
@@ -585,7 +554,7 @@ font: 75 18pt &quot;Agra&quot;;</string>
       <item>\r
        <widget class="QLabel" name="label_runtime_status2">\r
         <property name="text">\r
-         <string>已停止写地址...</string>\r
+         <string>已停止测试...</string>\r
         </property>\r
        </widget>\r
       </item>\r
@@ -649,7 +618,7 @@ font: 75 18pt &quot;Agra&quot;;</string>
       <item>\r
        <widget class="QPushButton" name="pbtn_spp_reconnect_3">\r
         <property name="enabled">\r
-         <bool>false</bool>\r
+         <bool>true</bool>\r
         </property>\r
         <property name="sizePolicy">\r
          <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
@@ -666,7 +635,7 @@ font: 75 18pt &quot;Agra&quot;;</string>
          </font>\r
         </property>\r
         <property name="text">\r
-         <string>开始写地址</string>\r
+         <string>开始测试</string>\r
         </property>\r
         <property name="checkable">\r
          <bool>false</bool>\r
@@ -737,7 +706,7 @@ font: 75 18pt &quot;Agra&quot;;</string>
       <item>\r
        <widget class="QLabel" name="label_runtime_status3">\r
         <property name="text">\r
-         <string>已停止写地址...</string>\r
+         <string>已停止测试...</string>\r
         </property>\r
        </widget>\r
       </item>\r
@@ -801,7 +770,7 @@ font: 75 18pt &quot;Agra&quot;;</string>
       <item>\r
        <widget class="QPushButton" name="pbtn_spp_reconnect_4">\r
         <property name="enabled">\r
-         <bool>false</bool>\r
+         <bool>true</bool>\r
         </property>\r
         <property name="sizePolicy">\r
          <sizepolicy hsizetype="Expanding" vsizetype="Fixed">\r
@@ -818,7 +787,7 @@ font: 75 18pt &quot;Agra&quot;;</string>
          </font>\r
         </property>\r
         <property name="text">\r
-         <string>开始写地址</string>\r
+         <string>开始测试</string>\r
         </property>\r
         <property name="checkable">\r
          <bool>false</bool>\r
@@ -889,7 +858,7 @@ font: 75 18pt &quot;Agra&quot;;</string>
       <item>\r
        <widget class="QLabel" name="label_runtime_status4">\r
         <property name="text">\r
-         <string>已停止写地址...</string>\r
+         <string>已停止测试...</string>\r
         </property>\r
        </widget>\r
       </item>\r
@@ -984,22 +953,6 @@ font: 75 18pt &quot;Agra&quot;;</string>
     </hint>\r
    </hints>\r
   </connection>\r
-  <connection>\r
-   <sender>pushButton_open_mac_config</sender>\r
-   <signal>clicked()</signal>\r
-   <receiver>MainWindow</receiver>\r
-   <slot>ui_open_mac_config()</slot>\r
-   <hints>\r
-    <hint type="sourcelabel">\r
-     <x>1192</x>\r
-     <y>126</y>\r
-    </hint>\r
-    <hint type="destinationlabel">\r
-     <x>676</x>\r
-     <y>346</y>\r
-    </hint>\r
-   </hints>\r
-  </connection>\r
   <connection>\r
    <sender>pushButton_openlogfolder</sender>\r
    <signal>clicked()</signal>\r
diff --git a/rebuild_fixed.ps1 b/rebuild_fixed.ps1
new file mode 100644 (file)
index 0000000..85fef03
--- /dev/null
@@ -0,0 +1,46 @@
+# 清理并重新编译项目(已修复链接顺序)\r
+\r
+$BuildDir = "D:\workspace\fd230_source_win\build-HiBTMacWriteTool-Desktop_Qt_5_14_2_MinGW_32_bit-Debug"\r
+$QtDir = "d:\Qt\Qt5.14.2\5.14.2\mingw73_32"\r
+$MingwDir = "D:\Qt\Qt5.14.2\Tools\mingw730_32"\r
+$env:QTDIR = $QtDir\r
+$env:PATH = "$MingwDir\bin;$QtDir\bin;$env:PATH"\r
+\r
+Write-Host "========================================" -ForegroundColor Green\r
+Write-Host "Clean and rebuild project" -ForegroundColor Green\r
+Write-Host "========================================" -ForegroundColor Green\r
+Write-Host ""\r
+\r
+Set-Location $BuildDir\r
+\r
+Write-Host "Step 1: Cleaning old build files..." -ForegroundColor Yellow\r
+& "$MingwDir\bin\mingw32-make.exe" clean *>&1 | Out-Null\r
+if ($LASTEXITCODE -ne 0) {\r
+    Write-Host "Warning: Clean failed, continuing..." -ForegroundColor Yellow\r
+}\r
+\r
+Write-Host ""\r
+Write-Host "Step 2: Fixing link order..." -ForegroundColor Yellow\r
+Set-Location "D:\workspace\fd230_source_win\HiBTMacWriteTool"\r
+& powershell -ExecutionPolicy Bypass -File "fix_link_order.ps1"\r
+\r
+Write-Host ""\r
+Write-Host "Step 3: Rebuilding..." -ForegroundColor Yellow\r
+Set-Location $BuildDir\r
+& "$MingwDir\bin\mingw32-make.exe"\r
+\r
+if ($LASTEXITCODE -ne 0) {\r
+    Write-Host ""\r
+    Write-Host "========================================" -ForegroundColor Red\r
+    Write-Host "Build failed!" -ForegroundColor Red\r
+    Write-Host "========================================" -ForegroundColor Red\r
+    Read-Host "Press Enter to exit"\r
+    exit 1\r
+}\r
+\r
+Write-Host ""\r
+Write-Host "========================================" -ForegroundColor Green\r
+Write-Host "Build successful!" -ForegroundColor Green\r
+Write-Host "========================================" -ForegroundColor Green\r
+Read-Host "Press Enter to exit"\r
+\r
diff --git a/serial_port_context.h b/serial_port_context.h
new file mode 100644 (file)
index 0000000..0f081a3
--- /dev/null
@@ -0,0 +1,92 @@
+#ifndef SERIAL_PORT_CONTEXT_H
+#define SERIAL_PORT_CONTEXT_H
+
+#include <QSerialPort>
+#include <QTimer>
+#include <QByteArray>
+#include <QString>
+
+// 前向声明
+class QSerialPort;
+class QTimer;
+
+// 串口上下文结构体 - 统一管理每个串口的状态
+struct SerialPortContext {
+    // 串口对象
+    QSerialPort *serialport;
+    
+    // 指令相关
+    qint64 m_bytesToWrite;           // 指令长度
+    int cmd_index;                    // 指令顺序: 0=AT投票, 1=GET_MAC, 2=SET_MAC, 3=GET_MAC验证, 4=GET_CPUID, 5=POWEROFF
+    QString G_cmd;                    // 当前执行的AT命令
+    
+    // 状态标志
+    bool working_state;               // true=写号执行中, false=写号结束
+    bool waiting_cmd;                 // 等待命令时机
+    bool startup_complete_detected;   // 启动完成信号已检测标志
+    bool uart_rx_flag;                // 是否有uart通路数据上报
+    bool uart_rx_Ignoring_display;   // 是否忽略uart数据,不回显
+    
+    // 数据缓冲区
+    QByteArray uart_rx_buff_array;    // AT命令响应缓冲区
+    QByteArray boot_detect_buffer;    // 开机检测数据缓存,处理分包情况
+    
+    // 定时器
+    QTimer *spp_timer_handle;         // AT命令超时定时器
+    
+    // 统计
+    int write_success_count;          // 成功计数
+    int write_fail_count;             // 失败计数
+    
+    // UI控件索引(用于区分不同串口的UI显示)
+    int port_index;                   // 端口索引: 1, 2, 3, 4
+    
+    // 构造函数
+    SerialPortContext(int index) 
+        : serialport(nullptr)
+        , m_bytesToWrite(0)
+        , cmd_index(0)
+        , working_state(false)
+        , waiting_cmd(false)
+        , startup_complete_detected(false)
+        , uart_rx_flag(false)
+        , uart_rx_Ignoring_display(false)
+        , spp_timer_handle(nullptr)
+        , write_success_count(0)
+        , write_fail_count(0)
+        , port_index(index)
+    {
+    }
+    
+    // 初始化函数
+    void init(QSerialPort *port, QTimer *timer) {
+        serialport = port;
+        spp_timer_handle = timer;
+        reset();
+    }
+    
+    // 重置状态
+    void reset() {
+        m_bytesToWrite = 0;
+        cmd_index = 0;
+        G_cmd.clear();
+        working_state = false;
+        waiting_cmd = false;
+        startup_complete_detected = false;
+        uart_rx_flag = false;
+        uart_rx_Ignoring_display = false;
+        uart_rx_buff_array.clear();
+        boot_detect_buffer.clear();
+        write_success_count = 0;
+        write_fail_count = 0;
+    }
+    
+    // 清理缓冲区
+    void clearBuffers() {
+        uart_rx_buff_array.clear();
+        boot_detect_buffer.clear();
+    }
+};
+
+#endif // SERIAL_PORT_CONTEXT_H
+
diff --git a/实现总结.md b/实现总结.md
new file mode 100644 (file)
index 0000000..447a94c
--- /dev/null
@@ -0,0 +1,173 @@
+# AT指令执行路径分析与4线程实现总结\r
+\r
+## 一、AT指令执行路径分析\r
+\r
+### 完整执行流程\r
+\r
+```\r
+1. spp_connect(port_index)\r
+   └─> 打开串口,设置 working_state = true\r
+   └─> 初始化状态变量\r
+\r
+2. readData(port_index) - 持续监听\r
+   ├─> 检测 BOOT_UP_MSG ("yaffs filesystem init start")\r
+   │   └─> waiting_cmd = true, cmd_index = 0\r
+   │   └─> 获取可用MAC地址\r
+   │\r
+   ├─> 检测 TIME_FOR_CMD ("bt enable_bt_stack ret")\r
+   │   └─> uart_send_data(ATCMD_ADD_VOTE) [cmd_index=0]\r
+   │\r
+   ├─> 检测 STARTUP_POST_INIT 和 STARTUP_POST_INIT_TASK\r
+   │   └─> startup_complete_detected = true\r
+   │\r
+   └─> 接收AT命令响应\r
+       └─> 检测结束标志 (OK~, power off device!, DSP0 power down)\r
+           └─> uart_process(port_index)\r
+\r
+3. uart_process(port_index) - 处理AT命令响应\r
+   ├─> case 0: 处理投票指令\r
+   │   └─> cmd_index++ → 1\r
+   │\r
+   ├─> case 1: 解析GET_MAC响应\r
+   │   ├─> 提取MAC地址\r
+   │   ├─> 检查是否已占用\r
+   │   └─> cmd_index++ → 2\r
+   │\r
+   ├─> case 2: 处理SET_MAC完成\r
+   │   └─> cmd_index++ → 3\r
+   │\r
+   ├─> case 3: 验证SET_MAC结果\r
+   │   └─> cmd_index++ → 4\r
+   │\r
+   ├─> case 4: 解析GET_CPUID响应\r
+   │   ├─> 提取CPU ID\r
+   │   ├─> 保存到数据库\r
+   │   └─> cmd_index++ → 5\r
+   │\r
+   └─> case 5: 处理关机完成\r
+       └─> cmd_index = -1, 工作完成\r
+\r
+4. 发送下一个AT命令 (在readData中)\r
+   └─> switch(cmd_index)\r
+       ├─> case 1: uart_send_data(ATCMD_GET_MAC)\r
+       ├─> case 2: uart_send_data(ATCMD_SET_MAC)\r
+       ├─> case 3: uart_send_data(ATCMD_GET_MAC)\r
+       ├─> case 4: uart_send_data(ATCMD_GET_CPUID) [需等待启动完成]\r
+       └─> case 5: uart_send_data(ATCMD_POWEROFF)\r
+```\r
+\r
+### AT指令列表\r
+\r
+| 指令 | 定义 | 用途 | 超时 | cmd_index |\r
+|------|------|------|------|-----------|\r
+| ATCMD_ADD_VOTE | `AT^PMADDVOTE\r\n` | 阻止休眠 | 1.5s | 0 |\r
+| ATCMD_GET_MAC | `AT^GETBTMAC\r\n` | 查询MAC | 3s | 1, 3 |\r
+| ATCMD_SET_MAC | `AT^BTADDR=%1 6\r\n` | 设置MAC | 1.5s | 2 |\r
+| ATCMD_GET_CPUID | `AT^GETIDS\r\n` | 获取CPU ID | 5s | 4 |\r
+| ATCMD_POWEROFF | `AT^POWEROFF\r\n` | 关机 | 1.5s | 5 |\r
+\r
+## 二、统一配置设计\r
+\r
+### 结构体设计\r
+\r
+已创建 `SerialPortContext` 结构体,统一管理每个串口的状态:\r
+\r
+```cpp\r
+struct SerialPortContext {\r
+    QSerialPort *serialport;          // 串口对象\r
+    QTimer *spp_timer_handle;         // 超时定时器\r
+    int cmd_index;                     // 当前命令索引\r
+    bool working_state;                // 工作状态\r
+    bool waiting_cmd;                  // 等待命令时机\r
+    bool startup_complete_detected;    // 启动完成标志\r
+    bool uart_rx_flag;                 // 接收标志\r
+    QByteArray uart_rx_buff_array;     // 响应缓冲区\r
+    QByteArray boot_detect_buffer;     // 开机检测缓存\r
+    QString G_cmd;                     // 当前命令\r
+    qint64 m_bytesToWrite;             // 待发送字节数\r
+    int write_success_count;           // 成功计数\r
+    int write_fail_count;              // 失败计数\r
+    int port_index;                    // 端口索引 (1-4)\r
+};\r
+```\r
+\r
+### 统一函数设计\r
+\r
+所有处理函数都接受 `port_index` 参数,使用 `port_contexts[port_index]` 访问对应上下文:\r
+\r
+- `readData(int port_index)` - 统一数据读取\r
+- `uart_process(int port_index)` - 统一命令处理\r
+- `uart_send_data(int port_index, QString cmd)` - 统一命令发送\r
+- `handleBytesWritten(int port_index, qint64 bytes)` - 统一发送完成处理\r
+- `spp_timer_callback(int port_index)` - 统一超时处理\r
+- `spp_connect(int port_index)` - 统一连接处理\r
+- `ui_display(int port_index, QString str, bool inOrOut)` - 统一UI显示\r
+- `ui_show_result(int port_index, QString msg, bool success)` - 统一结果显示\r
+\r
+## 三、4线程独立工作实现\r
+\r
+### 初始化\r
+\r
+在构造函数中:\r
+```cpp\r
+// 为4个串口创建独立的上下文\r
+for (int i = 0; i < MAX_SERIAL_PORTS; i++) {\r
+    port_contexts[i] = new SerialPortContext(i + 1);\r
+    spp_timer_handles[i] = new QTimer(this);\r
+    port_contexts[i]->init(ports[i], spp_timer_handles[i]);\r
+}\r
+```\r
+\r
+### 独立工作\r
+\r
+每个串口:\r
+- 有独立的上下文 (`port_contexts[i]`)\r
+- 有独立的定时器 (`spp_timer_handles[i]`)\r
+- 有独立的信号槽连接\r
+- 互不干扰,可以同时工作\r
+\r
+### 向后兼容\r
+\r
+保留原有函数名,内部调用统一函数:\r
+```cpp\r
+void MainWindow::readData1() {\r
+    readData(0);  // 调用统一函数,port_index=0\r
+}\r
+```\r
+\r
+## 四、实现状态\r
+\r
+### ✅ 已完成\r
+1. 创建 `SerialPortContext` 结构体\r
+2. 修改 `mainwindow.h`,添加统一配置数组\r
+3. 修改构造函数,初始化统一配置\r
+4. 修改析构函数,清理统一配置\r
+5. 创建分析文档\r
+\r
+### 🔄 待实现\r
+1. 实现统一的 `readData(int port_index)` 函数\r
+2. 实现统一的 `uart_process(int port_index)` 函数\r
+3. 实现统一的 `uart_send_data(int port_index, QString cmd)` 函数\r
+4. 实现其他统一处理函数\r
+5. 实现向后兼容的包装函数\r
+6. 实现UI控件映射(根据port_index映射到不同UI控件)\r
+7. 测试4个串口的独立工作\r
+\r
+## 五、下一步工作\r
+\r
+由于代码量很大(readData1函数有300+行),建议:\r
+\r
+1. **逐步重构**:先实现统一的 `readData` 函数,将 `readData1` 的逻辑提取出来\r
+2. **测试验证**:每完成一个统一函数,测试确保功能正常\r
+3. **UI映射**:创建辅助函数,根据 `port_index` 返回对应的UI控件\r
+4. **完整测试**:实现所有统一函数后,测试4个串口同时工作\r
+\r
+## 六、优势\r
+\r
+统一配置后的优势:\r
+1. **代码复用**:4个串口共享同一套处理逻辑\r
+2. **易于维护**:修改一处,所有串口生效\r
+3. **易于扩展**:添加新功能只需修改统一函数\r
+4. **独立工作**:每个串口有独立上下文,互不干扰\r
+5. **向后兼容**:保留原有函数名,不影响现有代码\r
+\r
diff --git a/统一配置实现方案.md b/统一配置实现方案.md
new file mode 100644 (file)
index 0000000..bbe3343
--- /dev/null
@@ -0,0 +1,78 @@
+# 统一配置实现方案\r
+\r
+## 实现步骤\r
+\r
+### 1. 已完成\r
+- ✅ 创建 `SerialPortContext` 结构体\r
+- ✅ 修改 `mainwindow.h`,添加统一配置数组\r
+- ✅ 修改构造函数,初始化统一配置\r
+- ✅ 修改析构函数,清理统一配置\r
+\r
+### 2. 待实现\r
+\r
+#### 2.1 统一处理函数\r
+需要创建以下统一函数(接受 `port_index` 参数):\r
+- `void readData(int port_index)` - 统一的数据读取函数\r
+- `void uart_process(int port_index)` - 统一的AT命令处理函数\r
+- `void uart_send_data(int port_index, QString cmd)` - 统一的AT命令发送函数\r
+- `void handleBytesWritten(int port_index, qint64 bytes)` - 统一的发送完成处理\r
+- `void spp_timer_callback(int port_index)` - 统一的超时处理\r
+- `void spp_connect(int port_index)` - 统一的串口连接函数\r
+- `void ui_display(int port_index, QString str, bool inOrOut)` - 统一的UI显示函数\r
+- `void ui_show_result(int port_index, QString msg, bool success)` - 统一的结果显示函数\r
+- `void poweroff_watch(int port_index)` - 统一的关机函数\r
+\r
+#### 2.2 向后兼容函数\r
+保留原有函数名,内部调用统一函数(port_index=0):\r
+- `readData1()` → `readData(0)`\r
+- `readData2()` → `readData(1)`\r
+- `readData3()` → `readData(2)`\r
+- `readData4()` → `readData(3)`\r
+- 其他函数类似\r
+\r
+#### 2.3 UI控件映射\r
+需要根据 `port_index` 映射到不同的UI控件:\r
+- port_index=0: `ui->txtb_dispaly`, `ui->label_runtime_status1`, `ui->ledit_spp_addr_1` 等\r
+- port_index=1: `ui->txtb_dispaly_2`, `ui->label_runtime_status2`, `ui->ledit_spp_addr_2` 等\r
+- port_index=2: `ui->txtb_dispaly_3`, `ui->label_runtime_status3`, `ui->ledit_spp_addr_3` 等\r
+- port_index=3: `ui->txtb_dispaly_4`, `ui->label_runtime_status4`, `ui->ledit_spp_addr_4` 等\r
+\r
+## 代码重构要点\r
+\r
+### 变量替换规则\r
+原代码中的变量需要替换为 `port_contexts[port_index]->xxx`:\r
+\r
+| 原变量 | 新变量 |\r
+|--------|--------|\r
+| `cmd_index_1` | `port_contexts[port_index]->cmd_index` |\r
+| `uart_rx_flag1` | `port_contexts[port_index]->uart_rx_flag` |\r
+| `uart_rx_buff_array1` | `port_contexts[port_index]->uart_rx_buff_array` |\r
+| `boot_detect_buffer` | `port_contexts[port_index]->boot_detect_buffer` |\r
+| `working_state_1` | `port_contexts[port_index]->working_state` |\r
+| `waiting_cmd1` | `port_contexts[port_index]->waiting_cmd` |\r
+| `startup_complete_detected` | `port_contexts[port_index]->startup_complete_detected` |\r
+| `m_bytesToWrite1` | `port_contexts[port_index]->m_bytesToWrite` |\r
+| `G_cmd` | `port_contexts[port_index]->G_cmd` |\r
+| `spp_timer_handle1` | `port_contexts[port_index]->spp_timer_handle` |\r
+| `serialport1` | `port_contexts[port_index]->serialport` |\r
+| `write_success_count1` | `port_contexts[port_index]->write_success_count` |\r
+| `write_fail_count1` | `port_contexts[port_index]->write_fail_count` |\r
+\r
+## 实现建议\r
+\r
+由于代码量很大,建议分阶段实现:\r
+\r
+1. **第一阶段**:实现统一的 `readData(int port_index)` 函数\r
+2. **第二阶段**:实现统一的 `uart_process(int port_index)` 函数\r
+3. **第三阶段**:实现统一的 `uart_send_data(int port_index, QString cmd)` 函数\r
+4. **第四阶段**:实现其他统一函数\r
+5. **第五阶段**:修改所有向后兼容函数,调用统一函数\r
+6. **第六阶段**:测试4个串口的独立工作\r
+\r
+## 注意事项\r
+\r
+1. **线程安全**:确保多线程访问串口上下文时使用适当的锁\r
+2. **UI更新**:UI更新需要在主线程中进行,使用信号槽机制\r
+3. **错误处理**:每个端口应该有独立的错误处理\r
+4. **资源管理**:确保每个端口的资源正确释放\r
+\r