Windows CE 為 Unicode 專屬系統,且不支援重疊 I/O (OVERLAPPED),導致桌面版串口類無法直接移植。本文提供從 SDK 範例移植改寫的 MFC 版 CSerial 類,採「主動發送請求、被動接收回應」模型,單一接收執行緒設計。
#if !defined(AFX_SERIAL_H__INCLUDED_)
#define AFX_SERIAL_H__INCLUDED_
#if _MSC_VER > 1000
#pragma once
#endif
DWORD WINAPI ReadPortThread(LPVOID lpVoid); // 接收執行緒
class CSerial {
public:
CSerial();
virtual ~CSerial();
BOOL OpenPort(LPCTSTR lpszPortName); // 開啟串口 (如 "COM1:")
BOOL ClosePort(HANDLE hCommPort); // 關閉串口
DWORD WritePort(TCHAR* buf, DWORD dwBytesToWrite); // 發送資料
BOOL InitDCB(); // 設定 DCB (鮑率、資料位、停止位、奇偶校驗)
BOOL InitCommTimeouts(); // 設定逾時參數
BOOL m_bConnected;
HANDLE hReadThread;
};
#endif
BOOL CSerial::OpenPort(LPCTSTR lpszPortName) {
if (hPort) return FALSE; // 已開啟
// 1. CreateFile 開啟裝置 (CE 不支援 FILE_FLAG_OVERLAPPED)
hPort = CreateFile(lpszPortName, GENERIC_READ | GENERIC_WRITE,
0, NULL, OPEN_EXISTING, 0, NULL);
if (hPort == INVALID_HANDLE_VALUE) {
CString err; err.Format(_T("無法開啟 %s, 錯誤碼=%d"), lpszPortName, GetLastError());
MessageBox(NULL, err, _T("Error"), MB_OK);
return FALSE;
}
// 2. 設定事件遮罩:僅關注接收字元
SetCommMask(hPort, EV_RXCHAR);
// 3. 配置緩衝區
SetupComm(hPort, 512, 512);
PurgeComm(hPort, PURGE_TXCLEAR | PURGE_RXCLEAR);
// 4. DCB 與逾時初始化
if (!InitDCB() || !InitCommTimeouts()) return FALSE;
// 5. 啟動 DTR/RTS 訊號
EscapeCommFunction(hPort, SETDTR);
EscapeCommFunction(hPort, SETRTS);
// 6. 建立接收執行緒
DWORD dwThreadId;
hReadThread = CreateThread(NULL, 0, ReadPortThread, this, 0, &dwThreadId);
m_bConnected = (hReadThread != NULL);
return m_bConnected;
}
DWORD WINAPI ReadPortThread(LPVOID lpVoid) {
CSerial* pThis = (CSerial*)lpVoid;
BYTE buf[256];
DWORD dwRead, dwError;
COMSTAT comStat;
while (pThis->m_bConnected) {
if (WaitCommEvent(pThis->hPort, &dwEvent, NULL)) {
if (dwEvent & EV_RXCHAR) {
ClearCommError(pThis->hPort, &dwError, &comStat);
if (comStat.cbInQue > 0) {
ReadFile(pThis->hPort, buf, min(sizeof(buf), comStat.cbInQue), &dwRead, NULL);
// 將 buf 處理或發送通知給主執行緒 (PostMessage/PostThreadMessage)
}
}
}
Sleep(10); // 降低 CPU 佔用
}
return 0;
}
DWORD CSerial::WritePort(TCHAR* buf, DWORD dwBytesToWrite) {
DWORD dwWritten;
WriteFile(hPort, buf, dwBytesToWrite, &dwWritten, NULL);
return dwWritten;
}
TCHAR/LPCTSTR,專案設定為 Unicode。CreateFile 旗標不含 FILE_FLAG_OVERLAPPED,ReadFile/WriteFile 同步阻塞。WaitCommEvent 替代重疊 I/O 完成通知。SetupComm、PurgeComm、ClearCommError 配合 COMSTAT 監控隊列。歡迎 CE 開發者交流指正,共同完善。E-mail: zhenxizhou@elong.com