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

C++ 串口通訊實戰:基於 MSComm ActiveX 控件

     編輯:關於C++

串口通訊將資料位元組分解為單一位元流循序傳輸,結構簡單、連接線少、應用極廣。本文採用 Microsoft Communications Control (MSComm) ActiveX 控件實作,利用 Windows ActiveX 技術簡化串口程式設計,僅需少量代碼即可高效完成任務。適用於 Visual Studio 2010/2012/2013 及 VC++ 6.0。

軟硬體環境

  • CPU:P4 2GHz 以上、相容 80x86 架構
  • 記憶體:1GB 以上
  • 硬碟:80GB 以上
  • 網卡:100Mbps 以上
  • 作業系統:Windows XP 以上
  • 開發工具:VS2010/2012/2013、Visual C++ 6.0、Keil uVision3/4、STC_ISP_V488/友善串口助手

MSComm 控件常用屬性

屬性說明
CommPort設定/取得通訊埠號
Settings以字串設定鮑率、奇偶校驗、資料位、停止位(如 "9600,n,8,1")
PortOpen設定/取得埠開啟狀態
Input從接收緩衝區讀取並移除字元
Output向發送緩衝區寫入字串
InputLen每次讀取字元數,0 表示讀取全部
InBufferCount接收緩衝區已接收字元數,歸零可清除緩衝區
InputMode0=文字模式,1=二進位模式
RThreshold/SThreshold觸發 OnComm 事件的接收/發送緩衝區字元閾值

專案建立步驟

1. 建立 MFC 對話方塊專案

VC++ 6.0:專案 → 加入至專案 → 元件與控制項 → 已註冊的 ActiveX 控制項 → 選擇 Microsoft Communications Control 6.0 → 插入。將控件加入對話方塊,設定 ID 為 IDC_MSCOMM。

VS2010/2012/2013:操作類似,透過工具箱或專案屬性加入 COM 元件。

2. 介面控件配置

  • 移除「取消」按鈕,將「確定」改為「退出」
  • 加入靜態文字、下拉式方塊(選擇串口 IDC_COMBO_SELECT、設定鮑率 IDC_COMBO_BTLSET)
  • 加入「開始收發」按鈕 IDC_BUTTON_START
  • 加入發送/接收編輯框 IDC_EDIT_SEND、IDC_EDIT_RECEIVE

介面配置完成圖

3. 控件變數映射

控件 ID變數名稱變數型別
IDC_EDIT_RECEIVEm_strReceiveCString
IDC_EDIT_SENDm_strSendCString
IDC_MSCOMMm_MSCommCMSComm
IDC_COMBO_SELECTm_nPortint

變數映射截圖

4. 核心功能代碼實作

打開串口

void CMyDlg::OnButtonOpen() {
    if (m_MSComm.GetPortOpen()) {
        AfxMessageBox(_T("請先關閉串口!"));
        return;
    }
    UpdateData(TRUE);
    if (m_nPort == -1) {
        AfxMessageBox(_T("請選擇串口!"));
        return;
    }
    m_MSComm.SetCommPort(m_nPort);
    m_MSComm.SetInBufferSize(1024);
    m_MSComm.SetOutBufferSize(1024);
    m_MSComm.SetInputLen(0);
    m_MSComm.SetInputMode(1);  // 二進位模式
    m_MSComm.SetRThreshold(1); // 收到 1 字元觸發事件
    m_MSComm.SetPortOpen(TRUE);

    if (m_MSComm.GetPortOpen()) {
        GetDlgItem(IDC_BUTTON_OPEN)->EnableWindow(FALSE);
        GetDlgItem(IDC_BUTTON_CLOSE)->EnableWindow(TRUE);
    } else {
        CString strInfo;
        strInfo.Format(_T("打開串口 COM%d 失敗!"), m_nPort);
        AfxMessageBox(strInfo);
    }
}

發送資料

void CMyDlg::OnButtonSend() {
    if (!m_MSComm.GetPortOpen()) {
        AfxMessageBox(_T("請先打開串口!"));
        return;
    }
    UpdateData(TRUE);
    int nSendLength = m_strSend.GetLength();
    CByteArray byteArray;
    byteArray.RemoveAll();
    byteArray.SetSize(nSendLength);
    for (int i = 0; i < nSendLength; i++) {
        byteArray.SetAt(i, (BYTE)m_strSend.GetAt(i));
    }
    m_MSComm.SetOutput(COleVariant(byteArray));
}

關閉串口

void CMyDlg::OnButtonClose() {
    if (!m_MSComm.GetPortOpen()) {
        AfxMessageBox(_T("請先打開串口!"));
        return;
    }
    m_MSComm.SetPortOpen(FALSE);
    GetDlgItem(IDC_BUTTON_OPEN)->EnableWindow(TRUE);
    GetDlgItem(IDC_BUTTON_CLOSE)->EnableWindow(FALSE);
}

鮑率設定

void CMyDlg::OnSelchangeBps() {
    UpdateData(TRUE);
    int nIndex = m_bps.GetCurSel();
    switch (nIndex) {
        case 0: m_MSComm.SetSettings(_T("19200,n,8,1")); break;
        case 1: m_MSComm.SetSettings(_T("14400,n,8,1")); break;
        case 2: m_MSComm.SetSettings(_T("9600,n,8,1")); break;
        case 3: m_MSComm.SetSettings(_T("4800,n,8,1")); break;
    }
    UpdateData(FALSE);
}

接收資料處理

void CMyDlg::OnOnCommMscomm() {
    if (m_MSComm.GetCommEvent() == 2) { // 接收緩衝區有字元
        VARIANT variantInput = m_MSComm.GetInput();
        COleSafeArray safeArray(variantInput);
        long length = safeArray.GetOneDimSize();
        BYTE* pData = new BYTE[length];
        safeArray.AccessData((void**)&pData);

        CString strTmp;
        for (long i = 0; i < length; i++) {
            BYTE bt = pData[i];
            if (m_bDisplayAsChar) // 假設有單選鈕控制顯示模式
                strTmp.Format(_T("%c"), bt);
            else
                strTmp.Format(_T("%02X "), bt);
            m_strReceive += strTmp;
        }
        safeArray.UnaccessData();
        delete[] pData;
        UpdateData(FALSE);
    }
}

測試結果

編譯生成 EXE,連接串口線後執行:

  • 整數顯示模式:整數顯示
  • 字元顯示模式:字元顯示
  • 外設測試:外設測試
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved