分層封裝:底層 bmLightComm 處理 Win32 Serial API,中層 bmLightControl 管理單控制器 4 通道亮度,上層 bmLightManage 統籌 3 個控制器(COM1~COM3),最上層 Qt GUI 提供滑桿同步調節 12 通道。
bmLightComm — 同步串口收發class bmLightComm {
HANDLE mCom;
public:
bool openPort(const char* port); // CreateFile
bool setupPort(DWORD baud, BYTE byteSize, BYTE stopBits, DWORD parity, BYTE parityMode); // DCB 設定
bool setBufferAreaSize(DWORD inQ, DWORD outQ); // SetupComm
bool setComTimeout(DWORD readInt, DWORD readMul, DWORD readConst, DWORD writeMul, DWORD writeConst); // COMMTIMEOUTS
bool purgePort(DWORD flags); // PurgeComm (TX/RX 清空)
bool closePort(); // CloseHandle
bool sendBuff(const char* data, unsigned int len); // WriteFile
char readBuff(); // ReadFile (單字元)
};
DCB:BaudRate=19200, ByteSize=8, StopBits=ONESTOPBIT, Parity=NOPARITY, fParity=FALSE。SetupComm(mCom, 1024, 1024)。ReadTotalTimeoutConstant 避免永久阻塞。PurgeComm 清空對應緩衝區,確保同步收發無殘留資料。bmLightControl每控制器 4 通道,協定格式:S + CH0 + CH1 + CH2 + CH3 + C#
T/F)。128T。sendBright() 組裝 18 字元指令字串發送,並讀取 1 字元回應。class qttestcomm : public QWidget {
QSlider mslider; // 0~255
bmLightManage m; // 3 控制器
public slots:
void slot1(int va) { // 滑桿值變化
std::vector ll;
for (int dev=0; dev<3; dev++)
for (int ch=0; ch<4; ch++)
ll.emplace_back(dev, ch, true, va); // 全開、同亮度
m.setBright(ll);
}
};
| 問題 | 風險 | 改進 |
|---|---|---|
sendBuff 用 sizeof(const char)*len | sizeof(const char) 永遠是 1,語義誤導 | 直接用 len 或 strlen(data) |
readBuff 僅讀 1 字元 | 回應可能超過 1 字元,導致殘留 | 改為讀取指定長度或直到終止符 |
| 無錯誤碼轉換為例外/錯誤碼 | 上層難以區分錯誤類型 | 回傳 enum 或 std::error_code |
| Qt 介面直接在 UI 線程阻塞串口 | 通訊延遲會凍結介面 | 移至 QThread 或使用 QSerialPort 非同步模式 |
| 硬編碼 COM1~COM3 | 部署機器埠號不同需改碼 | 掃描可用埠或讀取設定檔 |
QSerialPort(跨平台、非同步、信號槽整合),無需手寫 Win32 封裝。boost::asio::serial_port 或 C++20 std::execution 配合平台抽象層。termios API + epoll 非阻塞 I/O。此專案展示了從 Win32 底層 API 到業務邏輯封裝、再到 GUI 整合的完整串口應用開發流程。雖然代碼風格偏向「首次嘗試」階段(硬編碼、同步阻塞、錯誤處理簡易),但架構分層清晰,協定封裝得當,是嵌入式上位機開發的優秀入門範例。