1. 程式人生 > >VS2010 基於MFC 的串列埠通訊上位機總結

VS2010 基於MFC 的串列埠通訊上位機總結

VS2010 基於MFC 串列埠通訊上位機,實現串列埠傳送、接收資料及接收資料儲存。
提示:不清楚的函式可在MSDN 內查詢

  1. 開啟VS2010 建立 MFC應用程式,選擇基於對話方塊類 ,勾選最大化框、最小化框後 選擇下一步完成。

  2. 將對話方塊上原有的控制元件刪除,新增所需的控制元件。
    傳送部分: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");
    }

}

這裡寫圖片描述
使用虛擬串列埠測試,可以實現 資料傳送、接收、儲存 。