在實驗室與工控領域,受限於佈線成本,RS-232-C 串口長期作為電腦與串列設備通訊的首選通道。本文基於 Visual C++ 6.0 / Windows 9x 環境,構建一套支援後台非阻塞運行、即時接收處理數據、指令下發控制外設的監控軟體。
| 挑戰 | 解決方案 | 關鍵技術 |
|---|---|---|
| 前後台並行不阻塞 | 多執行緒分離 UI 與通訊 | AfxBeginThread、臨界區同步 |
| 數據即時捕獲不丟包 | 中斷驅動異步讀取 | WaitCommEvent、OVERLAPPED 結構 |
| 即時介面刷新 | 定時器輪詢顯示緩衝區 | SetTimer/WM_TIMER |
typedef struct tagCOM_CONFIG {
int nPort; // COM1~COM4
int nBaud; // 1200~57600 (CBR_1200~CBR_57600)
int nData; // 7/8 bits
int nStop; // 1/1.5/2 stop bits
int nParity; // NOPARITY/ODDPARITY/EVENPARITY
} COM_CONFIG;
// 以檔案方式開啟串口
idComDev = CreateFile(g_szCom_Port[g_com_config.nPort],
GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
DCB dcb; dcb.DCBlength = sizeof(DCB);
GetCommState(idComDev, &dcb);
// 緩衝區 4KB
SetupComm(idComDev, 4096, 4096);
PurgeComm(idComDev, PURGE_TXABORT|PURGE_RXABORT|PURGE_TXCLEAR|PURGE_RXCLEAR);
// 參數套用
dcb.BaudRate = g_Com_Baud[g_com_config.nBaud];
dcb.ByteSize = g_Com_ByteSize[g_com_config.nData];
dcb.Parity = g_Com_Parity[g_com_config.nParity];
dcb.StopBits = g_Com_StopBits[g_com_config.nStop];
// 關閉硬/軟流控
dcb.fDtrControl = DTR_CONTROL_DISABLE;
dcb.fOutxCtsFlow = FALSE;
dcb.fRtsControl = RTS_CONTROL_DISABLE;
dcb.fInX = dcb.fOutX = FALSE;
// 超時設定:讀無限等待,寫依波特率動態
COMMTIMEOUTS cto = {0};
cto.ReadIntervalTimeout = MAXDWORD;
cto.WriteTotalTimeoutMultiplier = 2*9600/dcb.BaudRate;
cto.WriteTotalTimeoutConstant = 25;
SetCommTimeouts(idComDev, &cto);
// 啟動讀取執行緒
if (SetCommState(idComDev, &dcb)) {
m_bComPortOpen = TRUE;
g_hCom = idComDev;
AfxBeginThread(COMReadThreadProc, NULL, THREAD_PRIORITY_NORMAL);
}
BOOL CCOMReadBuf::GetOneByte(BYTE* cb) {
m_Lock.Lock();
if (m_nHead == m_nTail) { m_Lock.Unlock(); return FALSE; }
*cb = m_readbuf[m_nTail];
m_nTail = (m_nTail + 1) % m_nBufSize;
m_Lock.Unlock(); return TRUE;
}
void CCOMReadBuf::Add(BYTE buf[], int nBytes) {
m_Lock.Lock();
for (int i=0; i
CString cmd; m_wndDlgBar.GetDlgItemText(IDC_EDIT_SEND, cmd);
if (!cmd.IsEmpty()) {
cmd += '\r';
DWORD dwWritten;
WriteFile(g_hCom, cmd, cmd.GetLength(), &dwWritten, NULL);
}
void CMyView::OnTimer(UINT nIDEvent) {
CListCtrl& list = GetListCtrl();
CTime t = CTime::GetCurrentTime();
CString timeStr; timeStr.Format(_T("%02d:%02d:%02d"), t.GetHour(), t.GetMinute(), t.GetSecond());
// 從緩衝區取數據填入 m_Buf...
int idx = list.InsertItem(0, timeStr);
if (idx != -1) list.SetItemText(idx, 1, m_Buf);
}
Comdebug 驗證硬體串口正常;本方案結合多執行緒解耦、異步事件驅動、執行緒安全緩衝、定時器 UI 解耦四大支柱,構建出高可靠、低延遲的串口監控系統。同樣架構易擴展至其他串列協議(RS-485、USB 轉串口等),具備極強工程復用價值。