MFC串列埠通訊(二)——使用MSComm控制元件實現串列埠通訊
阿新 • • 發佈:2018-12-11
由於專案需要,最近在寫一個簡單的串列埠通訊,基於MFC框架,寫完之後特此回顧記錄一下學習的過程:
串列埠通訊主體框架
(1) 初始化介面(自動獲取全部可用串列埠)
(2) 開啟串列埠 (讀取串列埠號,初始化串列埠引數(波特率、校驗位、資料位等),若串列埠已經開啟則關閉串列埠)
(3) 傳送資料 (更新控制元件狀態,進入MSComm事件驅動函式,讀緩衝區,資料轉換,更新編輯框成員函式,更新編輯框內容)
(4) 退出介面 (檢測串列埠是否開啟,若開啟則關閉串列埠,再進行退出)
- 在MFC中建立對話方塊的基礎上,新增兩個控制元件CComBox和Button控制元件,CComBox負責掃描所有可用串列埠,Button用於開啟和關閉串列埠,然後右鍵滑鼠,點選插入ActiveX控制元件,選擇控制元件,出現如控制元件(電話圖示),則表示插入控制元件成功
- 給控制元件新增變數,變數名為m_mscom,之後專案中會出現對應.h和.cpp檔案
- 加Eidit Control控制元件用於接受訊息,繫結變數m_EditReveive,然後新增串列埠控制元件事件處理處理程式
點選新增編輯按鈕(第一次新增會是新增編輯,再次新增的話會是編輯程式碼按鈕),會出現如下程式碼:
void CCommTestDlg::OnCommMscomm2()
{
// TODO: 在此處新增訊息處理程式程式碼
}
新增自動接收程式碼(專案中通訊協議是測試結果自動上傳),並直接顯示在接收控制元件中,程式碼如下:
void CComCommunicateDlg::OnCommMscomm2() //事件驅動 { if (m_mscom.get_CommEvent() == 2) //事件值為2表示接收緩衝區內有字元 { char str[1024] = { 0 }; long k; VARIANT InputData = m_mscom.get_Input(); //讀緩衝區 COleSafeArray fs; fs = InputData; //VARIANT型變數轉換為COleSafeArray型變數 for (k = 0; k<fs.GetOneDimSize(); k++) fs.GetElement(&k, str + k); //轉換為BYTE型陣列 m_EditReveive += str; // 接收到編輯框裡面 //SetTimer(1,10,NULL); //延時10ms UpdateData(false); //更新到控制元件 } }
- 由於專案比較簡單,就將串列埠引數寫死了,若想修改引數可以在原始碼裡修改,開啟/關閉串列埠程式碼實現如下:
void CComCommunicateDlg::OnBnClickedButtonOpen() //開啟串列埠按鈕
{
CString str, n; //定義字串
GetDlgItemText(IDC_BUTTON_OPEN, str); //獲取給定控制元件的文字
CWnd *h1;
h1 = GetDlgItem(IDC_BUTTON_OPEN); //指向控制元件的caption
if (!m_mscom.get_PortOpen())
{
try
{
m_mscom.put_CommPort(num); //選擇串列埠
}
catch (CException* e)
{
m_mscom.put_OutBufferCount(0);
AfxMessageBox(L"開啟串列埠 失敗");
return;
}
m_mscom.put_InputMode(1); //設定輸入方式為二進位制方式
m_mscom.put_Settings(_T("115200,n,8,1")); //設定串列埠引數,波特率,無奇偶校驗,位停止位,位資料位
m_mscom.put_InputLen(1024); //設定當前接收區資料長度為1024
m_mscom.put_RThreshold(1); //接收緩衝區有1個及1個以上字元時,觸發OnComm事件
m_mscom.put_RTSEnable(1); //設定RT允許
m_mscom.put_PortOpen(true); //開啟串列埠
if (m_mscom.get_PortOpen())
{
str = _T("關閉串列埠");
UpdateData(true);
h1->SetWindowText(str); //改變按鈕名稱為‘’關閉串列埠”
}
}
else
{
m_mscom.put_PortOpen(false); //關閉串列埠
if (str != _T("開啟串列埠"))
{
str = _T("開啟串列埠");
UpdateData(true); //將控制元件的狀態傳給其關聯的變數
h1->SetWindowText(str); //改變按鈕名稱為開啟串列埠
}
}
}
- 最後是選擇串列埠下拉框,起初用的比較笨的方法,新增在ComBox新增1-8個串列埠,然後到裝置管理器中檢視串列埠資訊,再開啟串列埠。後來改用自動掃描已開啟埠號,其功能封裝在GetCom()函式裡,在初始化的時候執行即可。程式碼如下
void CComCommunicateDlg::GetCom()
{
//程式啟動時獲取全部可用串列埠
HANDLE hCom;
int i, k;
CString str;
BOOL flag;
((CComboBox *)GetDlgItem(IDC_COMBO1))->ResetContent();
flag = FALSE;
num = 0;
for (i = 1; i <= 16; i++)
{//此程式支援16個串列埠
str.Format(L"\\\\.\\COM%d", i);
hCom = CreateFile(str, 0, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if (INVALID_HANDLE_VALUE != hCom)
{//能開啟該串列埠,則新增該串列埠
CloseHandle(hCom);
str = str.Mid(4);
((CComboBox *)GetDlgItem(IDC_COMBO1))->AddString(str);
if (flag == FALSE)
{
flag = TRUE;
num = i;
}
}
}
i = ((CComboBox *)GetDlgItem(IDC_COMBO1))->GetCount();
if (i == 0)
{//若找不到可用串列埠則禁用“開啟串列埠”功能
((CComboBox *)GetDlgItem(IDC_COMBO1))->EnableWindow(FALSE);
}
else
{
k = ((CComboBox *)GetDlgItem((IDC_COMBO1)))->GetCount();
((CComboBox *)GetDlgItem(IDC_COMBO1))->SetCurSel(k - 1);
//mCom.BindCommPort(num);
}
}
- 最終軟體執行頁面,串列埠通訊訊息的傳送暫時沒有用到,以後用到了再進行記錄