VS2010 基於MFC 的串列埠通訊上位機總結
VS2010 基於MFC 串列埠通訊上位機,實現串列埠傳送、接收資料及接收資料儲存。
提示:不清楚的函式可在MSDN 內查詢
開啟VS2010 建立 MFC應用程式,選擇基於對話方塊類 ,勾選最大化框、最小化框後 選擇下一步完成。
將對話方塊上原有的控制元件刪除,新增所需的控制元件。
傳送部分:Radio Button、Combo Box
接收部分:Edit Control
選擇串列埠、波特率:Combo Box
按鍵:開啟串列埠、傳送資料、清除資料、儲存資料、退出
圖示顯示:指示串列埠開啟、關閉狀態
Activex 串列埠控制元件:Microsoft Communications Control,Version 6.0
3.為各控制元件新增控制程式
① 開啟串列埠按鈕 ,顯示指示圖示
提示:雙擊開啟按鈕 會直接跳轉到 void C串列埠Dlg::OnBnClickedButtonOpen() 函式
void C串列埠Dlg::OnBnClickedButtonOpen()
{
// TODO: 在此新增控制元件通知處理程式程式碼
CString str,str1,n; //定義3個CString變數
GetDlgItemText(IDC_BUTTON_OPEN,str); //獲取開啟串列埠按鍵的Caption,IDC_BUTTON_OPEN:開啟串列埠按鍵的ID
CWnd *h1; //定義控制代碼類的指標
h1 = GetDlgItem(IDC_BUTTON_OPEN); // h1 賦為 指向IDC_BUTTON_OPEN 按鍵的控制代碼
if(!m_mscom.get_PortOpen()) //如果串列埠未開啟
{
//m_comb3:波特率選擇組合框的 成員變數
m_comb3.GetLBText(m_comb3.GetCurSel(),str1); //取得波特率口當前的選擇值,存放在str1裡
str1 = str1 + _T(",n,8,1");
m_mscom.put_Settings(str1);// 設定波特率、無校驗,8資料位,1個停止位
m_mscom.put_InBufferSize(1024); //接收緩衝區大小設定
m_mscom.put_OutBufferSize(1024);//傳送緩衝區大小設定
m_mscom.put_CommPort((m_comb1.GetCurSel()+1)); //選擇串列埠,m_comb1:串列埠選擇組合框的 成員變數
m_mscom.put_InputMode(1); //設定輸入方式 二進位制方式
m_mscom.put_InputLen(0);// 設定當前接收區資料長度為0,表示全部讀取
m_mscom.put_RThreshold(2); // 緩衝區有2個字元引發OnComm事件
m_mscom.put_PortOpen(true); //開啟串列埠
m_mscom.get_Input(); //先預讀緩衝區以清除殘留資料
if(m_mscom.get_PortOpen()) //如果串列埠開啟
{
str = _T("關閉串列埠"); // str開啟按鈕的Caption 賦為 “關閉串列埠”
UpdateData(TRUE);//用於將螢幕上控制元件中的資料交換到變數中
h1->SetWindowText(str); //開啟串列埠按鍵 文字將被修改
m_Icon.SetIcon(m_hIcon_Open); //顯示開啟圖示
}
}
else
{
m_mscom.put_PortOpen(false); //關閉串列埠
if(str != _T("開啟串列埠"))
{
str = _T("開啟串列埠");
UpdateData(TRUE);
h1->SetWindowText(str);
m_Icon.SetIcon(m_hIcon_Close); //顯示關閉圖示
}
}
}
② 串列埠開啟、關閉 圖示顯示
首先,準備好2個Icon 圖示, 在資源檢視內右鍵—>新增資源—>匯入 ,選擇2個Icon。 匯入後自動分配了ID: IDI_ICON1\ IDI_ICON2 .
在BOOL C串列埠Dlg::OnInitDialog() 內新增如下程式碼:
//m_hIcon_Open:串列埠開啟圖示的HICON 型別的成員變數
//m_hIcon_Close :串列埠關閉圖示的HICON 型別的成員變數
//LoadIcon從與應用程式例項相關聯的可執行檔案(.EXE)檔案中載入指定的圖示資源
m_hIcon_Open = LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDI_ICON1));
m_hIcon_Close = LoadIcon(AfxGetInstanceHandle(),MAKEINTRESOURCE(IDI_ICON2));
m_Icon.SetIcon(m_hIcon_Close); //設定初始顯示為關閉圖示
③選擇串列埠 與 波特率 的 Combo Box 設定
在BOOL C串列埠Dlg::OnInitDialog() 內新增如下程式碼:
// 串列埠組合框:顯示com1~com15
CString str;
for(i=0;i<15;i++)
{
str.Format(_T("com %d"),i+1);
m_comb1.InsertString(i,str);
}
m_comb1.SetCurSel(0);
//波特率組合框
CString str1[]={_T("4800"),_T("9600"),_T("19200"),_T("38400"),_T("43000"),_T("56000"),_T("57600"),_T("115200")};
for(int i = 0; i<8 ; i++)
{
int judge_tf=m_comb3.AddString(str1[i]);
if((judge_tf==CB_ERR)|(judge_tf==CB_ERRSPACE))
MessageBox(_T("設定波特率錯誤"));
}
m_comb3.SetCurSel(7);
//執行次數選項框
int i;
CString str2[]={_T("1"),_T("2"),_T("3"),_T("4"),_T("5"),_T("6"),_T("7"),_T("8"),_T("9")};
for(int i = 0; i<9 ; i++)
{
int judge_times=m_Runtime.AddString(str2[i]);
if((judge_times==CB_ERR)|(judge_times==CB_ERRSPACE))
MessageBox(_T("未設定執行次數"));
}
m_Runtime.SetCurSel(0);
④ Radio選擇框設定,傳送資料按鈕
多個Radio Button 將第一個的Group改為True 按照Tab順序會將其他Radio Button 分為一組,返回值分別為0,1,2 …
雙擊發送資料按鈕,新增控制程式:
void C串列埠Dlg::OnBnClickedButtonSend()
{
// TODO: 在此新增控制元件通知處理程式程式碼
CString str,str1,SendData;
UpdateData(TRUE); //將控制元件的狀態傳給其關聯的變數
str.Format(_T("%d"),m_MMSet); //將 單選按鈕的 int變數值強制轉換成CString型別
m_Runtime.GetLBText(m_Runtime.GetCurSel(),str1);//執行次數選擇框返回值
SendData = str + str1; //傳送的資料
//UpdateData(TRUE);
m_mscom.put_Output(COleVariant(SendData)); //資料傳送
}
⑤清除資料按鈕
void C串列埠Dlg::OnBnClickedButtonClean()
{
// TODO: 在此新增控制元件通知處理程式程式碼
m_Edit1_Rev1 = _T(""); //給接收編輯框傳送空格符
m_Edit1_Rev2 = _T("");
m_Edit1_Rev3 = _T("");
m_Edit1_Rev4 = _T("");
m_Edit1_Rev5 = _T("");
UpdateData(FALSE);//將資料在螢幕中對應控制元件中顯示出來
}
⑥ 關閉按鈕
void C串列埠Dlg::OnBnClickedButtonClose()
{
// TODO: 在此新增控制元件通知處理程式程式碼
if(m_mscom.get_PortOpen())
m_mscom.put_PortOpen(FALSE);
CDialogEx::OnCancel();
}
⑦ 串列埠控制元件程式:點選Activex 控制元件,右鍵 為控制元件新增處理程式
功能 :多個接收編輯框分別顯示接收資料
void C串列埠Dlg::OnCommMscomm1()
{
// TODO: 在此處新增訊息處理程式程式碼
CString strtemp;
if(m_mscom.get_CommEvent()==2) //事件值為2 表示接收快取區內有字元
{
BYTE str[2048]={0};
long len,k;
COleSafeArray fs;
int flag,i=0;
VARIANT InputData = m_mscom.get_Input(); //讀緩衝區
fs = InputData; //Variant型別變數轉換成 COleSafeArray型變數
len = fs.GetOneDimSize(); //得到有效資料長度
for(k = 0;k < len;k++)
fs.GetElement(&k,str+k); //轉換成BYTE型陣列
for(k = 0;k < len;k++) //將陣列轉換為CString型變數
{
BYTE bt=*(char*)(str+k); //字元型
strtemp.Format(_T("%c"),bt); //將字元輸入臨時變數strtemp
//輸出為多個顯示框,顯示位置標誌
if(strtemp == 'a')
{
flag = 0;
}
else if(strtemp == 'b')
{
flag = 1;
}
else if(strtemp == 'c')
{
flag = 2;
}
.....
//顯示資料寫入
switch(flag)
{
case 0:
m_Edit1_Rev1 = _T(""); //清空顯示
for(k=1;k<len;k++)
{
bt=*(char*)(str+k); //字元型
strtemp.Format(_T("%c"),bt); //將字元輸入臨時變數strtemp
m_Edit1_Rev1 += strtemp;
}
break;
case 1:
m_Edit1_Rev2 = _T("");
for(k=1;k<len;k++)
{
bt=*(char*)(str+k); //字元型
strtemp.Format(_T("%c"),bt); //將字元輸入臨時變數strtemp
m_Edit1_Rev2 += strtemp;
}
break;
case 2:
m_Edit1_Rev3 = _T(""); //清空顯示
for(k=1;k<len;k++)
{
bt=*(char*)(str+k); //字元型
strtemp.Format(_T("%c"),bt); //將字元輸入臨時變數strtemp
m_Edit1_Rev3 += strtemp;
}
break;
}
}
UpdateData(FALSE); // 更新編輯框內容
}
}
⑧ 資料儲存按鍵
將資料儲存為csv格式
void C串列埠Dlg::OnBnClickedButtonSave()
{
// TODO: 在此新增控制元件通知處理程式程式碼
CString str,str1,str2,str3,str4;
//構建檔案儲存為對話方塊,預設副檔名為.csv,初始檔名為空...
CFileDialog fg(false,_T("*.csv"),NULL,OFN_HIDEREADONLY|OFN_OVERWRITEPROMPT,
_T("Text File(*.txt)|*.txt|Excel CSV File(*.csv)|*.csv|All Flie(*.*)|*.*||"),NULL);
str1 = _T("文字,");//文字為行標題,換單元格
str2 = _T("文字,");
str3 = _T("文字,");
str4 = _T("文字,");
str8 = _T(",文字,文字,文字\n"); // 文字為列標題
if(fg.DoModal()==IDOK) //建立對話方塊成功
{
CString filename = fg.GetPathName(); //檔案的完整路徑
CStdioFile mFile(filename,CFile::modeCreate|CFile::modeWrite); //指定檔案路徑、建立只寫模式
//寫入第1個 Radio Button控制的資料
switch (m_MMSet)
{
case 0:
mFile.Write(str1,str1.GetLength());
GetDlgItemText(IDC_RADIO1,str);
mFile.WriteString(str+"\n");
break;
case 1:
mFile.Write(str1,str1.GetLength());
GetDlgItemText(IDC_RADIO2,str);
mFile.WriteString(str+"\n");
break;
case 2:
mFile.Write(str1,str1.GetLength());
GetDlgItemText(IDC_RADIO3,str);
mFile.WriteString(str+"\n");
break;
default:
break;
}
//寫入第2個文字 的資料
mFile.Write(str2,str2.GetLength());
GetDlgItemText(IDC_COMBO1,str);
mFile.WriteString(str+"\n");
mFile.Write(str8,str8.GetLength()); //寫列標題
//寫入接收框1的資料
mFile.Write(str3,str3.GetLength());
GetDlgItemText(IDC_EDIT1_Rev1,str); //寫入接收框資料
mFile.WriteString(str);//指定一個指向包含空終止文字字串的緩衝區的指標。
GetDlgItemText(IDC_EDIT2_Rev1,str);
mFile.WriteString(",");
mFile.WriteString(str);
GetDlgItemText(IDC_EDIT3_Rev1,str);
mFile.WriteString(",");
mFile.WriteString(str+"\n");
//寫入接收框2的資料
mFile.Write(str4,str4.GetLength());
GetDlgItemText(IDC_EDIT1_Rev2,str);
mFile.WriteString(str);
GetDlgItemText(IDC_EDIT2_Rev2,str);
mFile.WriteString(",");
mFile.WriteString(str);
GetDlgItemText(IDC_EDIT3_Rev2,str);
mFile.WriteString(",");
mFile.WriteString(str+"\n");
}
}
使用虛擬串列埠測試,可以實現 資料傳送、接收、儲存 。