首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 編程語言 >  >> C語言 >> 關於C語言

MFC 串口通訊實戰:MSComm ActiveX 控件屬性、事件與收發程式碼完整指南

     編輯:關於C語言

Windows API 直接操作串口(CreateFile/ReadFile/WriteFile + DCB 結構)雖功能完整,但設定繁瑣、錯誤易發。Microsoft 提供的 MSComm ActiveX 控件(MSCOMM32.OCX)將串口操作封裝為屬性/方法/事件模型,極大降低開發門檻。本文詳細列出關鍵屬性、事件處理架構,並提供完整的初始化、接收、發送程式碼範例。

專案整合 MSComm 控件

  1. 對話框編輯器右鍵 → 插入 ActiveX 控件 → 選擇 Microsoft Comm Control 6.0。
  2. 類別精靈為控件加入成員變數 m_comm (型別 MSComm 或 CMSComm)。
  3. 確認專案連結 mscomm32.ocx (通常自動註冊)。

核心屬性完整對照表

屬性型別說明典型值
CommPortshort串口號 (1=COM1, 2=COM2...)1~4
SettingsCString通訊參數字串 "Baud,Parity,Data,Stop""9600,N,8,1"
PortOpenBOOL開啟/關閉串口,讀取可得知狀態TRUE/FALSE
InputModelong接收緩衝區讀取模式0=Text, 1=Binary
InputVARIANT從接收緩衝區讀取資料 (唯讀)—
InBufferCountshort接收緩衝區位元組數—
InBufferSizeshort接收緩衝區大小 (預設 1024)1024~65535
OutputVARIANT寫入發送緩衝區 (唯寫)—
OutBufferCountshort發送緩衝區待發位元組數—
OutBufferSizeshort發送緩衝區大小 (預設 512)512~65535
InputLenshort每次 Input 讀取位元組數 (0=全部)0~65535
RThresholdshort接收觸發 OnComm 事件的字元數1 (每字元觸發)
SThresholdshort發送緩衝區剩餘觸發 OnComm 字元數0 (不觸發)
CommEventshort最近發生的通訊事件碼 (唯讀)見下表
EOFEnableBOOLText 模式下是否啟用 EOF 字元檢測FALSE
EOFCharBYTEEOF 字元值 (預設 0x1A/Ctrl+Z)0x0D (CR), 0x0A (LF)

OnComm 事件代碼

常數值事件描述
comEventBreak1斷線偵測
comEventCTS2CTS 訊號變化
comEventDSR4DSR 訊號變化
comEventRing8電話響鈴偵測
comEventRLSD16RLSD (CD) 訊號變化
comEventReceive2接收緩衝區達 RThreshold
comEventSend4發送緩衝區低於 SThreshold
comEventEOF8Text 模式偵測到 EOF 字元

完整程式碼範例

1. 串口初始化 (OnInitDialog 或按鈕)

void CMyDlg::InitSerialPort()
{
    if (m_comm.GetPortOpen()) return; // 已開啟

    m_comm.SetCommPort(1);           // COM1
    m_comm.SetSettings(_T("9600,N,8,1")); // 9600,無校驗,8資料位,1停止位
    m_comm.SetInputMode(0);          // Text 模式
    m_comm.SetRThreshold(1);         // 每收 1 字元觸發 OnComm
    m_comm.SetInputLen(0);           // 讀取所有可用字元
    m_comm.SetInBufferSize(4096);    // 擴大接收緩衝
    m_comm.SetOutBufferSize(2048);   // 擴大發送緩衝

    m_comm.SetPortOpen(TRUE);        // 開啟串口
    if (!m_comm.GetPortOpen()) {
        AfxMessageBox(_T("串口開啟失敗,請檢查埠號與驅動"));
    }
}

2. 接收資料 (OnComm 事件處理)

void CMyDlg::OnComm()
{
    // 僅處理接收事件
    if (m_comm.GetCommEvent() != 2) return; // comEventReceive = 2

    VARIANT var = m_comm.GetInput(); // 讀取接收緩衝區
    if (var.vt == VT_BSTR) {
        CString str = var.bstrVal; // Text 模式直接得 BSTR
        m_strReceived += str;
        UpdateData(FALSE); // 顯示至 Edit Control
    }
    else if (var.vt == (VT_ARRAY | VT_UI1)) {
        // Binary 模式: SAFEARRAY of BYTE
        SAFEARRAY* psa = var.parray;
        long lBound, uBound;
        SafeArrayGetLBound(psa, 1, &lBound);
        SafeArrayGetUBound(psa, 1, &uBound);
        long count = uBound - lBound + 1;
        BYTE* pData = new BYTE[count];
        SafeArrayAccessData(psa, (void**)&pData);
        // 處理二進位資料...
        SafeArrayUnaccessData(psa);
        delete[] pData;
    }
    VariantClear(&var);
}

3. 發送資料

// 發送文字
void CMyDlg::OnSendText()
{
    CString str = _T("Hello Serial!");
    m_comm.SetOutput(COleVariant(str)); // 自動轉 BSTR
}

// 發送二進位
void CMyDlg::OnSendBinary()
{
    BYTE cmd[] = {0xAA, 0x55, 0x01, 0x02, 0x03};
    SAFEARRAYBOUND bound = {5, 0};
    SAFEARRAY* psa = SafeArrayCreate(VT_UI1, 1, &bound);
    BYTE* pData; SafeArrayAccessData(psa, (void**)&pData);
    memcpy(pData, cmd, 5); SafeArrayUnaccessData(psa);
    m_comm.SetOutput(COleVariant(psa));
    SafeArrayDestroy(psa);
}

4. 關閉串口 (OnDestroy 或按鈕)

void CMyDlg::CloseSerialPort()
{
    if (m_comm.GetPortOpen()) {
        m_comm.SetPortOpen(FALSE);
    }
}

進階技巧

常見錯誤排查

  • OnComm 不觸發:檢查 RThreshold > 0、InputMode 正確、控件已正確訊息映射 (ON_EVENT)。
  • 亂碼:確認雙方 Settings 完全一致 (鮑率、校驗、資料位、停止位)。
  • 發送無反應:檢查 OutBufferCount 是否長期累積 (對方未讀取/流控)。
  • 部署缺少 OCX:安裝程式需包含 MSCOMM32.OCX 並註冊 (regsvr32)。

總結

MSComm ActiveX 控件以屬性/方法/事件模型將串口通訊簡化為「設定屬性 → 開啟埠 → 事件驅動收發」,適合快速開發儀器控制、POS 周邊、模組通訊等應用。掌握 Settings 字串格式、OnComm 事件分派、VARIANT 資料轉換三大核心,即可輕鬆駕馭串口通訊。

  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved
需求實作方法
非標準鮑率 (如 250000)Settings 不支援,需用 Win32 API SetCommState 直接設定 DCB
硬體流控 (RTS/CTS)MSComm 不直接支援,需 EscapeCommFunction + DCB.fRtsControl
多執行緒讀取MSComm 非執行緒安全,建議單一 UI 執行緒處理 OnComm,資料放入佇列供工作者執行緒取用
自動偵測可用 COM 埠列舉登錄 HKEY_LOCAL_MACHINE\HARDWARE\DEVICEMAP\SERIALCOMM
替代方案新專案建議用 Win32 API 或 CSerial 開源類別,避免 OCX 部署相依