在 32 位 Windows 環境下實現串口(COM 口)通訊,主要有四種技術路線,各有適用場景與優劣權衡。本文系統梳理這四種方案的核心 API、代碼骨架與選型建議。
最通用、最推薦的方式。串口在 Windows 中視為檔案物件,使用 CreateFile、ReadFile、WriteFile 等標準 I/O API,支援同步/非同步(Overlapped I/O)模式。
// 1. 開啟串口
HANDLE hComm = CreateFile(
L"COM1", // 埠名
GENERIC_READ | GENERIC_WRITE, // 讀寫權限
0, // 獨佔存取
NULL, // 安全屬性
OPEN_EXISTING, // 必須存在
FILE_FLAG_OVERLAPPED, // 非同步 I/O 關鍵旗標
NULL);
if (hComm == INVALID_HANDLE_VALUE) { /* 錯誤處理 */ }
// 2. 設定通訊參數 (DCB 結構)
DCB dcb = {0};
dcb.DCBlength = sizeof(DCB);
GetCommState(hComm, &dcb);
dcb.BaudRate = CBR_115200;
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT;
SetCommState(hComm, &dcb);
// 3. 設定逾時 (COMMTIMEOUTS)
COMMTIMEOUTS ct = {0};
ct.ReadIntervalTimeout = 50;
ct.ReadTotalTimeoutMultiplier = 10;
ct.ReadTotalTimeoutConstant = 1000;
SetCommTimeouts(hComm, &ct);
// 4. 非同步讀寫 (需 OVERLAPPED 結構 + 事件通知/完成埠)
OVERLAPPED ov = {0};
ov.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
WriteFile(hComm, buffer, len, &written, &ov);
ReadFile(hComm, buffer, len, &read, &ov);
// 配合 GetOverlappedResult / WaitForSingleObject / IOCP 完成
OnComm),極大降低開發門檻。// BCB __fastcall 慣例:參數經由 EAX、EDX 傳遞
unsigned char __fastcall ReadByte(WORD port) {
asm {
mov dx, ax
in al, dx
}
}
void __fastcall WriteByte(unsigned char val, WORD port) {
asm {
mov dx, ax
out dx, al
}
}
IN/OUT 指令,會觸發權限違規例外。| 場景 | 推薦方案 | 理由 |
|---|---|---|
| 一般工業/儀器/嵌入式上位機 | 方案一 (Win32 API + Overlapped I/O) | 標準、穩定、可控、跨版本相容 |
| 快速原型、維護舊 VB/BCB 專案 | 方案二 (MSComm/第三方控件) | 開發效率最高,封裝良好 |
| DOS/Win9x 古董設備維護 | 方案三 (內嵌組語) | 唯一可行路徑 |
| 極致效能、核心級硬體互動 | 方案四 (KMDF 驅動) | 突破 Ring 3 限制 |
CreateFile 回傳值,失敗時呼叫 GetLastError() 診斷(常見:埠被佔用、權限不足、名稱錯誤)。OVERLAPPED.hEvent 或 I/O 完成埠,避免輪詢浪費 CPU。ClearCommError 回傳的錯誤碼(溢位、幀錯、奇偶校驗錯)。PurgeComm 清空緩衝區,再 CloseHandle。現代 Windows 串口開發首選方案一,掌握 Win32 非同步 I/O 模型是核心競爭力;方案二適合快速交付;方案三已成歷史;方案四留給驅動開發專家。理解四者邊界,才能在專案中做出最合理的架構決策。