深入淺出VC++串列埠程式設計之基於控制元件
1.MSComm控制元件
Visual C++為我們提供了一種好用的ActiveX控制元件Microsoft Communications Control(即MSComm)來支援應用程式對串列埠的訪問,在應用程式中插入MSComm控制元件後就可以較為方便地實現對通過計算機串列埠收發資料。
要使用ActiveX控制元件MSComm,程式設計師必須將其新增入工程,其方法是:
(1)單擊主選單project的子選單Add To project的Components and Controls選項;
(2)在彈出的"Components and Controls Gallery"對話方塊中選擇Registered ActiveX Controls資料夾中的"Microsoft Communications Control,version 6.0"選項,如下圖:
單擊其中的"Insert"按鈕,MSComm控制元件就被增加到工程中了。與此同時,類CMSComm的相關檔案mscomm.h和mscomm.cpp也一併被加入Project的Header Files和Source Files中。當然,程式設計師可以自己修改檔名,如下圖:
直接分析mscomm.h標頭檔案就可以完備地獲取這個控制元件的使用方法(主要是public型別的介面函式),下面我們摘取了標頭檔案的主要程式碼並對其關鍵部分給出了註釋:
#if !defined(AFX_MSCOMM_H__) #define AFX_MSCOMM_H__ #if _MSC_VER > 1000 #pragma once #endif // _MSC_VER > 1000 // Machine generated IDispatch wrapper class(es) created by Microsoft Visual C++ // NOTE: Do not modify the contents of this file. If this class is regenerated by // Microsoft Visual C++, your modifications will be overwritten. ///////////////////////////////////////////////////////////////////////////// // CMSComm wrapper class class CMSComm : public CWnd { protected: DECLARE_DYNCREATE(CMSComm) public: CLSID const& GetClsid() { static CLSID const clsid = { 0x648a5600, 0x2c6e, 0x101b, { 0x82, 0xb6, 0x0, 0x0, 0x0, 0x0, 0x0, 0x14 } }; return clsid; } virtual BOOL Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext = NULL) { return CreateControl(GetClsid(), lpszWindowName, dwStyle, rect, pParentWnd, nID); } BOOL Create(LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CFile* pPersist = NULL, BOOL bStorage = FALSE, BSTR bstrLicKey = NULL) { return CreateControl(GetClsid(), lpszWindowName, dwStyle, rect, pParentWnd, nID, pPersist, bStorage, bstrLicKey); } // Attributes public: // Operations public: void SetCDHolding(BOOL bNewValue); BOOL GetCDHolding(); void SetCommID(long nNewValue); long GetCommID(); void SetCommPort(short nNewValue); //設定埠號,如nNewValue =1表示COM1 short GetCommPort(); void SetCTSHolding(BOOL bNewValue); BOOL GetCTSHolding(); void SetDSRHolding(BOOL bNewValue); BOOL GetDSRHolding(); void SetDTREnable(BOOL bNewValue); BOOL GetDTREnable(); void SetHandshaking(long nNewValue); long GetHandshaking(); void SetInBufferSize(short nNewValue); short GetInBufferSize(); void SetInBufferCount(short nNewValue); short GetInBufferCount(); void SetBreak(BOOL bNewValue); BOOL GetBreak(); void SetInputLen(short nNewValue); short GetInputLen(); void SetNullDiscard(BOOL bNewValue); BOOL GetNullDiscard(); void SetOutBufferSize(short nNewValue); short GetOutBufferSize(); void SetOutBufferCount(short nNewValue); short GetOutBufferCount(); void SetParityReplace(LPCTSTR lpszNewValue); CString GetParityReplace(); void SetPortOpen(BOOL bNewValue); //開啟或關閉串列埠,TRUE:開啟,FALSE:關閉 BOOL GetPortOpen(); //串列埠是否已開啟,TRUE:開啟,FALSE:關閉 void SetRThreshold(short nNewValue); //如果設定為1,表示一接收到字元就傳送2號事件 short GetRThreshold(); void SetRTSEnable(BOOL bNewValue); //硬體握手使能? BOOL GetRTSEnable(); void SetSettings(LPCTSTR lpszNewValue); //Settings由4部分組成,其格式為:"BBBB,P,D,S",即"波特率,是否奇偶校驗,資料位 //個數,停止位",如設定為:"9600,n,8,1" CString GetSettings(); void SetSThreshold(short nNewValue); //如果保持預設值0不變,則表示傳送資料的過程中串列埠上不發生事件 short GetSThreshold(); void SetOutput(const VARIANT& newValue); //一個非常重要的函式,用於寫串列埠,注意其接收的輸入引數為VARIANT型別物件, //我們需要將字串轉化為VARIANT型別物件 VARIANT GetOutput(); void SetInput(const VARIANT& newValue); VARIANT GetInput(); //一個非常重要的函式,用於讀串列埠,注意其返回的是VARIANT型別物件,我們需要 //將其轉化為字串 void SetCommEvent(short nNewValue); short GetCommEvent(); //一個非常重要的函式,獲得串列埠上剛發生的事件("事件"可以理解為軟體意義上的 //"訊息"或硬體意義上的"中斷"),事件的傳送會導致OnComm訊息的誕生! void SetEOFEnable(BOOL bNewValue); BOOL GetEOFEnable(); void SetInputMode(long nNewValue); long GetInputMode(); }; //{{AFX_INSERT_LOCATION}} // Microsoft Visual C++ will insert additional declarations immediately before the previous line. #endif |
分析上述原始碼可知,基本上,MSComm的諸多介面可以分為如下幾類:
(1)開啟與設定串列埠介面函式;
(2)獲得串列埠設定和串列埠狀態介面函式;
(3)設定串列埠傳送資料方式、緩衝區介面及傳送資料介面函式;
(4)設定串列埠接收資料方式、緩衝區介面及接收資料介面函式;
(5)設定與獲取串列埠上發生的事件介面函式。
2.例程
程式的功能和介面(如下圖)都與本文連載三中《基於WIN32 API的串列埠程式設計》相同,不同的只是連載三的串列埠通訊以API實現,而本節的串列埠通訊則以MSComm控制元件實現。
使用第1節的方法將控制元件新增入工程並新增mscomm.h和mscomm.cpp檔案後,為了使用控制元件,我們將控制元件拖入對話方塊內任意一個位置(執行時"電話"圖示會隱藏),其操作如下圖:
|
有趣而極富人性化的是我們可以直接右鍵單擊這個"電話",來設定串列埠的屬性,如下圖:
接著,我們需要為控制元件新增一個對應的成員變數m_mscom,其對應的變數型別為CMSComm,如下圖:
這樣就建立了m_mscom和IDC_MSCOMM1控制元件的相互對映:
void CSerialPortActivexDlg::DoDataExchange(CDataExchange* pDX) { CDialog::DoDataExchange(pDX); //{{AFX_DATA_MAP(CSerialPortActivexDlg) DDX_Text(pDX, IDC_RECV_EDIT, m_recv); DDX_Text(pDX, IDC_SEND_EDIT, m_send); DDX_Control(pDX, IDC_MSCOMM1, m_mscom); //}}AFX_DATA_MAP } |
同時,在對話方塊的標頭檔案也會由"MFC類嚮導"自動定義CSerialPortActivexDlg類的CMSComm型成員變數m_mscom:
CMSComm m_mscom; |
在對話方塊初始化時(即在CSerialPortActivexDlg::OnInitDialog函式中)開啟串列埠1:
BOOL CSerialPortActivexDlg::OnInitDialog() { CDialog::OnInitDialog(); // Add "About..." menu item to system menu. // IDM_ABOUTBOX must be in the system command range. ASSERT((IDM_ABOUTBOX & 0xFFF0) == IDM_ABOUTBOX); ASSERT(IDM_ABOUTBOX < 0xF000); CMenu* pSysMenu = GetSystemMenu(FALSE); if (pSysMenu != NULL) { CString strAboutMenu; strAboutMenu.LoadString(IDS_ABOUTBOX); if (!strAboutMenu.IsEmpty()) { pSysMenu->AppendMenu(MF_SEPARATOR); pSysMenu->AppendMenu(MF_STRING, IDM_ABOUTBOX, strAboutMenu); } } // Set the icon for this dialog. The framework does this automatically // when the application's main window is not a dialog SetIcon(m_hIcon, TRUE); // Set big icon SetIcon(m_hIcon, FALSE); // Set small icon // TODO: Add extra initialization here m_mscom.SetCommPort(1); //串列埠1 m_mscom.SetInBufferSize(1024); //設定輸入緩衝區的大小,Bytes m_mscom.SetOutBufferSize(512); //設定輸入緩衝區的大小,Bytes if(!m_mscom.GetPortOpen()) //開啟串列埠 { m_mscom.SetPortOpen(true); } m_mscom.SetInputMode(1); //設定輸入方式為二進位制方式 m_mscom.SetSettings("9600,n,8,1"); //設定波特率等引數 m_mscom.SetRThreshold(1); //為1表示有一個字元即引發事件 m_mscom.SetInputLen(0); return TRUE; // return TRUE unless you set the focus to a control } |
最核心的傳送串列埠資料函式("傳送"按鈕單擊事件)如下:
void CSerialPortActivexDlg::OnSendButton() |
3. 為了處理接收事件,我們需要為MScomm控制元件新增對應的訊息處理函式。如下圖,我們通過"MFC類嚮導"添加了CSerialPortActivexDlg 類的成員函式OnCommMscomm1():
這樣,在對話方塊的標頭檔案中就會自動增加下面兩句:
afx_msg void OnCommMscomm1();//函式宣告 DECLARE_EVENTSINK_MAP() |
來自AFX_MSG部分:
// Generated message map functions //{{AFX_MSG(CSerialPortActivexDlg) virtual BOOL OnInitDialog(); afx_msg void OnSysCommand(UINT nID, LPARAM lParam); afx_msg void OnPaint(); afx_msg HCURSOR OnQueryDragIcon(); afx_msg void OnClearButton(); afx_msg void OnSendButton(); afx_msg void OnCommMscomm1(); DECLARE_EVENTSINK_MAP() //}}AFX_MSG |
同時在對話方塊的.cpp檔案中會增加下列程式碼實現串列埠訊息對映:
BEGIN_EVENTSINK_MAP(CSerialPortActivexDlg, CDialog) //{{AFX_EVENTSINK_MAP(CSerialPortActivexDlg) ON_EVENT(CSerialPortActivexDlg, IDC_MSCOMM1, 1 /* OnComm */, OnCommMscomm1, VTS_NONE) //}}AFX_EVENTSINK_MAP END_EVENTSINK_MAP() |
我們定義CSerialPortActivexDlg::OnCommMscomm1()函式主要處理資料的接收,其原始碼為:
void CSerialPortActivexDlg::OnCommMscomm1() { // TODO: Add your control notification handler code here UpdateData(true); VARIANT variant_inp; COleSafeArray safearray_inp; long i = 0; int len; char rxdata[1000]; CString tmp; switch (m_mscom.GetCommEvent()) { case 2: //表示接收緩衝區內有字元 { variant_inp = m_mscom.GetInput(); safearray_inp = variant_inp; len = safearray_inp.GetOneDimSize(); for (i = 0; i < len; i++) { safearray_inp.GetElement(&i, &rxdata[i]); } rxdata[i] = '/0'; } m_recv += rxdata; UpdateData(false); break; default: break; } } |
最後,與連載三類似,再次藉助"串列埠除錯助手"以例項驗證了本程式的正確性,如下圖:
最後,需要特別提示的是:如果要在基於"文件/檢視"的框架結構程式而非對話方塊程式中使用串列埠控制元件,我們不能輕鬆地使用"MFC類嚮導",這時候必須手動地新增相關程式碼。
在MainFrm.h標頭檔案中加入:
afx_msg void OnCommMscomm(); DECLARE_EVENTSINK_MAP() |
並定義CMSComm成員變數:
CMSComm m_ComPort; |
在MainFrm.cpp檔案中新增
BEGIN_EVENTSINK_MAP(CMainFrame, CFrameWnd) ON_EVENT(CMainFrame,ID_COMMCTRL,1,OnCommMscomm,VTS_NONE) //對映ACTIVEX控制元件的事件 END_EVENTSINK_MAP() |
在MainFrm.cpp檔案的OnCreate(LPCREATESTRUCT lpCreateStruct)函式中新增:
ComPort.Create(NULL, WS_VISIBLE | WS_CHILD, CRect(0,0,0,0),this, ID_COMMCTRL); |
以建立CMSComm控制元件。
此後,我們就可以在CMainFrame類的函式中使用串列埠控制元件對應的ComPort控制元件成員變數。
相關推薦
深入淺出VC++串列埠程式設計之基於控制元件
1.MSComm控制元件 Visual C++為我們提供了一種好用的ActiveX控制元件Microsoft Communications Control(即MSComm)來支援應用程式對串列埠的訪問,在應用程式中插入MSComm控制元件後就可以較為方便地實現對通
深入淺出VC++串列埠程式設計之基本概念
除錯工具 在MS-DOS下使用的程式設計環境是TC 2.0; 在Windows 2000下的程式設計環境是VC++ 6.0; 藉助工具:串列埠除錯助手2.1(圖8)。 圖8 串列埠除錯助手 串列埠除錯助手是由《Visual C++/Turbo C串列埠通訊程式設計實踐》一書作者龔建偉編寫的
深入淺出VC++串列埠程式設計之DOS的串列埠程式設計
/* Name : Sample Comm's Program - 1024 Byte Buffer - buff1024.c *//* Written By : Craig Peacock <[email protected]> */#include <dos.h>#inc
深入淺出VC++串列埠程式設計之簡訊應用開發
前面數次連載我們以較長的篇幅講解了串列埠通訊的硬體原理、DOS平臺控制以及基於WIN32 API、控制元件和第三方類的串列埠程式設計。作為本系列文章的最後一次連載,本章將給出一個典型的應用例項:西門子簡訊服務模組TC35
深入淺出VC++串列埠程式設計--簡訊應用開發
前面數次連載我們以較長的篇幅講解了串列埠通訊的硬體原理、DOS平臺控制以及基於WIN32 API、控制元件和第三方類的串列埠程式設計。作為本系列文章的最後一次連載,本章將給出一個典型的應用例項:西門子簡訊服務模組TC35的串列埠控制。 1.簡訊控制終端 作為簡訊 (Sho
Vc 串列埠程式設計 Win32 控制元件
在工業控制中,工控機(一般都基於Windows平臺)經常需要與智慧儀表通過串列埠進行通訊。串列埠通訊方便易行,應用廣泛。 一般情況下,工控機和各智慧儀表通過RS485匯流排進行通訊。RS485的通訊方式是半雙工的,只能由作為主節點的工控PC機依次輪詢網路上的各智慧控
串列埠程式設計之串列埠初始化
Linux串列埠程式設計 常見資料通訊方式:並行通訊,序列通訊 UART的主要操作: 資料傳送及接受 產生中斷 產生波特率 Loopback模式 紅外模式 自動流控模式 串列埠引數的配置主要包括:波特率、資料位
VC串列埠程式設計的例項1
本例程採用同步串列埠操作,我們只介紹軟體部分,RS485介面接線方法不作介紹,感興趣的讀者可以查閱相關資料。 開啟VC++6.0,新建基於對話方塊的工程RS485Comm,在主對話方塊視窗IDD_RS485COMM_DIALOG上新增兩個按鈕,ID分別
VC串列埠程式設計的例項2
本例程採用非同步串列埠操作,我們只介紹軟體部分,RS485介面接線方法不作介紹,感興趣的讀者可以查閱相關資料。 開啟VC++6.0,新建基於對話方塊的工程RS485Comm,在主對話方塊視窗IDD_RS485COMM_DIALOG上新增兩個按鈕,ID分
[轉]js串列埠通訊 呼叫MSCOMM32控制元件 連結電子秤
本文轉自:https://www.cnblogs.com/x-j-p/p/7819724.html 硬體環境:RS232轉USB串列埠線*1 電子秤*1(本人採用G&G E600Y-C型號稱重儀) 電子秤原裝RS232資料線*1 計算機*1 軟體環境:RS232
基於VC++的串列埠程式設計
序列通訊介面標準有多個版本,但是基本上都是在RS-232標準的基礎上發展而來。RS-232C標準時美國EIA和BELL等公司一起開發並於1969年公佈的通訊協議。1997年TIA發不了最新的一個版本,命名為TIA/EIA-232-F。ITU和CCITT釋出了一個類似的標準-V
Android之串列埠程式設計
閱讀時長:10分鐘 原文地址:juejin.im/post/5bd96c… 原文作者:YKamh 技術預備:Java基礎 如今我們生活中充滿了各種智慧裝置,方便了我們的生活,這正是物聯網時代。如果我們要開發智慧裝置,那麼Android串列埠程式設計是我們應該必備的技能。 在投身到An
菜鳥江濤帶你學最小物聯網系統之模組篇(02)——STM32通過串列埠傳送AT指令控制ESP模組連線伺服器
接著上一篇繼續,這篇部落格我將帶大家使用STM32的串列埠來發送AT指令給ESP模組連線伺服器。當然目前測試使用的是區域網,自己的電腦當伺服器使用。使用TCP連線伺服器,STM32通過ESP12F模組透傳上傳溫溼度資料到伺服器。看下效果圖片 好了,看下主要的實現程式
linux串列埠程式設計(控制流與終端)
流控制 資料在兩個串列埠之間傳輸時,常常會出現丟失資料的現象,或者兩臺計算機的處理速度不同,如桌上型電腦與微控制器之間的通訊,接收端資料緩衝區已滿,則此時繼續傳送來的資料就會丟失。流控制能解決這個問題,當接收端資料處理不過來時,就發出“不再接收”的訊號,傳送端就停止傳送,直到收到“可以繼續傳送”
Android基於藍芽串列埠程式設計實現HC-05通訊
Android基於藍芽串列埠程式設計實現HC-05通訊 最近接了個工程自動化的專案,需求是實時接收從微控制器傳過來的資料,並進行資料分析處理再進行顯示,在查閱大量的相關部落格和自己踩了不少的坑後,想說把自己的一些經驗分享出來給後來人做個參考www 先介紹下藍芽串列埠的定義
Android 之 USB Host 串列埠程式設計
1.OTG: A.手機作為Host,裝置作為Device,手機給裝置充電,需要通過OTG線實現(microUSB);(裝置可以為鍵盤/滑鼠/主機等等) B.手機作為Host,另一手機作為Device,通過OTG可以通訊; 2.PC連線Android:(不需要OTG) A.
vc串列埠原始碼除錯-控制元件初學者必看!
<pre name="code" class="cpp">// pj20Dlg.cpp : 實現檔案 // #include "stdafx.h" #include "pj20.h" #include "pj20Dlg.h" #ifdef _DEBUG #d
Unity之串列埠通訊(基於三姿態感測器)
/*******************************/ using UnityEngine; using System.Collections; //Other libraries using System; using System.Threading; using System.Collect
UART0串列埠程式設計系列 串列埠(UART0)之UC/OS(一)
一.在UC/OS中設計串列埠程式所要考慮的問題 1. 串列埠通訊資料以幀為單位進行處理,如果需要接收大量資料,則幀緩衝區規模必然很大;如果需要傳送大量資料,則可將原始資料快看作緩衝區,不需要另外再建立幀緩衝區。 2. 幀緩衝區是全域性資料結構,通常為共
20160426 VC++(VS2013)串列埠程式設計圖文教程(MSComm的使用)
1、新建MFC對話方塊工程如下 2、給編輯框控制元件新增變數,其中Edit Box新增Value變數,Button新增Control變數,ID和變數分別為: IDC_BTNOPEN()