http://blog.csdn.net/a_runing_man/article/details/9947343
本人之前從未接觸MFC編程,由於項目需要,所以上網查閱了相關資料,並實現了上位機串口通信。由於網上的資料還不夠詳細,本人決定寫一個圖文並茂的詳細教程。因為本人只是初學,如有錯誤,歡迎指點。
開發環境是:VC 6.0
串口編程方法:32位控件
參考資料:http://leadtheway.iteye.com/blog/705760
第一步:建工程
運行VC 6.0,文件-〉新建,選擇MFC AppWizard(exe) ,工程名稱:CommTest。確定


進入MFC應用程序向導-步驟1
選擇基本對話框,其他的都默認,所以可以直接點擊完成。

這樣工程就建立完畢。

第二步:控件布局與設置
工程建立后,出現如下對話框:


刪除上面的一個靜態文本和兩個按鈕。從控件工具欄拖入兩個靜態文本,兩個編輯框,兩個按鈕和一個組框。如果沒有控件工具欄,可以鼠標右鍵點擊菜單欄空白處,選擇控件。布局后的效果:


接下來開始設置顯示的文字和ID號。
選中按鈕1,右鍵-〉屬性。ID號設為IDC_BtnOpen,標題為打開。用於打開串口


選中按鈕2,右鍵-〉屬性。ID號設為IDC_BtnSend,標題為發送。用於發送數據。


選擇第一個編輯框,右鍵-〉屬性,更改ID為IDC_EditRxData,用於顯示接收的數據。


同理選擇第二個編輯框,更改ID為IDC_EditTxData。用於輸入待發送的數據。

分別選中靜態文本和組框,更改標題,不需要更改ID號。
最終效果如下:


現在先編譯運行一次,避免出現錯誤而影響到后面的操作。
接下來這一步是關鍵的一步:
在對話框中鼠標右鍵-〉選中插入ActiveX控件。選擇Microsoft Communication Control,ver......(后面的字母沒看到)。確定

這時出現了一個電話的控件,右鍵該控件-〉選擇類向導……,出現如下對話框:


先設置每個控件的變量,選擇Member Variables,選擇IDC_BtnOpen,然后Add Variable。

設置變量名為m_BtnOpen,名稱與ID號相似只是為了方便記憶,可隨便定義。其他默認。同理添加其他控件的變量,在添加MSCOMM1的變量時,會出現提示,選擇“是”。



添加完畢后:

變量添加完畢后選回Message Maps,選擇IDC_BtnOpen->BN_CLICKED->Add Function,默認函數名就好了,OK。

同理分別添加IDC_BtnSend->BN_CLICKED函數和IDC_MSCOMM1->OnComm函數。確定。
編譯運行,避免有錯誤。如果出錯,詳細檢查有沒有誤操作。一般不會出錯的。
第三步:添加代碼
選擇左邊信息欄的File View,雙擊打開CommTestDlg.cpp,在文件尾部可以看到剛剛添加的三個函數。


在OnBtnOpen()函數添加代碼:
void CCommTestDlg::OnBtnOpen()
{
// TODO: Add your control notification handler code here
if(m_Comm1.GetPortOpen())
m_Comm1.SetPortOpen(FALSE);
m_Comm1.SetCommPort(1); //選擇com1,可根據具體情況更改
m_Comm1.SetInBufferSize(1024); //設置輸入緩沖區的大小,Bytes
m_Comm1.SetOutBufferSize(1024); //設置輸入緩沖區的大小,Bytes//
m_Comm1.SetSettings("9600,n,8,1"); //波特率9600,無校驗,8個數據位,1個停止位
m_Comm1.SetInputMode(1); //1:表示以二進制方式檢取數據
m_Comm1.SetRThreshold(1);
//參數1表示每當串口接收緩沖區中有多於或等於1個字符時將引發一個接收數據的OnComm事件
m_Comm1.SetInputLen(0); //設置當前接收區數據長度為0
if( !m_Comm1.GetPortOpen())
m_Comm1.SetPortOpen(TRUE);//打開串口
else
AfxMessageBox("cannot open serial port");
m_Comm1.GetInput();//先預讀緩沖區以清除殘留數據
UpdateData(false);
}

編譯運行。
在OnOnCommMscomm1()函數添加代碼:
void CCommTestDlg::OnOnCommMscomm1()
{
// TODO: Add your control notification handler code here
VARIANT variant_inp;
COleSafeArray safearray_inp;
LONG len,k;
BYTE rxdata[2048]; //設置BYTE數組 An 8-bit integerthat is not signed.
CString strtemp;
if(m_Comm1.GetCommEvent()==2) //事件值為2表示接收緩沖區內有字符
{ ////////以下你可以根據自己的通信協議加入處理代碼
variant_inp=m_Comm1.GetInput(); //讀緩沖區
safearray_inp=variant_inp; //VARIANT型變量轉換為ColeSafeArray型變量
len=safearray_inp.GetOneDimSize(); //得到有效數據長度
for(k=0;k<len;k++)
safearray_inp.GetElement(&k,rxdata+k);//轉換為BYTE型數組
for(k=0;k<len;k++) //將數組轉換為Cstring型變量
{
BYTE bt=*(char*)(rxdata+k); //字符型
strtemp.Format("%c",bt); //將字符送入臨時變量strtemp存放
m_EditRxData+=strtemp; //加入接收編輯框對應字符串
}
}
//UpdateData(FALSE); //更新編輯框內容
SetDlgItemText(IDC_EditRxData,m_EditRxData);//不使用UpdateData(FALSE);的原因是該函數會
//刷新整個對話框的數據,而SetDlgItemText()
//只更新接收編輯框的數據。
}

現在可以接上串口做測試了。我是用單片機做串口發送,上位機做串口接收。單片機持續發送字符' D '.上位機正常接收:

接着添加發送功能,
void CCommTestDlg::OnBtnSend()
{
// TODO: Add your control notification handler code here
UpdateData(TRUE); //讀取編輯框內容
m_Comm1.SetOutput(COleVariant(m_EditTxData));//發送數據
}

發送大寫字母N,在單片機用LED顯示。‘N’對應的ASCII碼的二進制是0100 1110。實物結果如圖:


