|
值得注意的是 第一種方法的發(fā)送方式是發(fā)送不了0X00的,第二種方法中解決啦0x 00不能發(fā)送的問題;
建立基于對話框的MFC工程,命名為“CommTest”,應(yīng)用程序選擇”基于對話框“
建立好工程如下圖所示:

刪除默認(rèn)的按鈕以及靜態(tài)文本框,添加如下對話框控件:
A:打開串口控件,工具欄中拖一個botton 到 diadlg 上 ,并修改Caption 為 ”打開串口“,修改ID 為 IDC_BOTTON_OPEN
B: 關(guān)閉串口控件,工具欄中拖一個botton 到 diadlg 上 ,并修改Caption 為 ”關(guān)閉串口“,修改ID 為 IDC_BOTTON_CLOSE
C:發(fā)送控件,工具欄中拖一個botton 到 diadlg 上 ,并修改Caption 為 ”發(fā)送“,修改ID 為 IDC_BOTTON_SEND
D:發(fā)送編輯框 和 接受編輯框

添加通信串口控件,在對話框上右鍵

 
在對話框右下角電話樣子的就是串口通信控件
給控件添加變量
在電話圖標(biāo)上右擊:


命名如圖示,點擊完成 在工程中會自動生成mscomm.h 和mscomm.cpp兩個文件;
給兩個編輯框添加成員變量

  
添加三個按鈕的事件
直接雙擊 三個按鈕 會在程序中自動添加如下函數(shù)
- void CCommTestDlg::OnBnClickedButtonSend()
- {
- // TODO: 在此添加控件通知處理程序代碼
- }
- void CCommTestDlg::OnBnClickedButtonOpen()
- {
- // TODO: 在此添加控件通知處理程序代碼
-
- }
- void CCommTestDlg::OnBnClickedButtonClose()
- {
- // TODO: 在此添加控件通知處理程序代碼
- }
添加控件事件處理函數(shù):


點擊添加編輯即可,在CommTestDlg.cpp中會生成函數(shù):
- void CCommTestDlg::OnCommMscomm1()
- {
- // TODO: 在此處添加消息處理程序代碼
- }
數(shù)據(jù)接收都是從這個函數(shù)處理
打開串口函數(shù)實現(xiàn):
- void CCommTestDlg::OnBnClickedButtonOpen()
- {
- // TODO: 在此添加控件通知處理程序代碼
- if(m_mscomm.get_PortOpen())
- {
- m_mscomm.put_PortOpen(FALSE);
- }
- m_mscomm.put_CommPort(3); //選擇COM3
- m_mscomm.put_InBufferSize(1024); //接收緩沖區(qū)
- m_mscomm.put_OutBufferSize(1024);//發(fā)送緩沖區(qū)
- m_mscomm.put_InputLen(0);//設(shè)置當(dāng)前接收區(qū)數(shù)據(jù)長度為0,表示全部讀取
- m_mscomm.put_InputMode(1);//以二進制方式讀寫數(shù)據(jù)
- m_mscomm.put_RThreshold(1);//接收緩沖區(qū)有1個及1個以上字符時,將引發(fā)接收數(shù)據(jù)的OnComm
- m_mscomm.put_Settings(_T("9600,n,8,1"));//波特率9600無檢驗位,8個數(shù)據(jù)位,1個停止位
-
- if(!m_mscomm.get_PortOpen())//如果串口沒有打開則打開
- {
- m_mscomm.put_PortOpen(TRUE);//打開串口
- AfxMessageBox(_T("串口3打開成功"));
- }
- else
- {
- m_mscomm.put_OutBufferCount(0);
- AfxMessageBox(_T("串口3打開失敗"));
- }
-
- }
關(guān)閉按鈕實現(xiàn):
- void CCommTestDlg::OnBnClickedButtonClose()
- {
- // TODO: 在此添加控件通知處理程序代碼
- m_mscomm.put_PortOpen(FALSE);//關(guān)閉串口
- AfxMessageBox(_T("串口 3 已關(guān)閉"));
- }
發(fā)送代碼實現(xiàn):
- void CCommTestDlg::OnBnClickedButtonSend()
- {
- // TODO: 在此添加控件通知處理程序代碼
- UpdateData(true); //讀取編輯框內(nèi)容
- m_mscomm.put_Output(COleVariant(m_EditSend));//發(fā)送數(shù)據(jù)
- m_EditSend.Empty(); //發(fā)送后清空輸入框
- UpdateData(false); //更新編輯框內(nèi)容
- }
接受數(shù)據(jù)實現(xiàn):
- void CCommTestDlg::OnCommMscomm1()
- {
- // TODO: 在此處添加消息處理程序代碼
- static unsigned int cnt=0;
- VARIANT variant_inp;
- COleSafeArray safearray_inp;
- long len,k;
- unsigned int data[1024]={0};
- byte rxdata[1024]; //設(shè)置 BYTE 數(shù)組
- CString strtemp;
- if(m_mscomm.get_CommEvent()==2) //值為 2 表示接收緩沖區(qū)內(nèi)有字符
- {
- cnt++;
- variant_inp=m_mscomm.get_Input(); //讀緩沖區(qū)消息
- safearray_inp=variant_inp; ///變量轉(zhuǎn)換
- len=safearray_inp.GetOneDimSize(); //得到有效的數(shù)據(jù)長度
- for(k=0;k<len;k++)
- {
- safearray_inp.GetElement(&k,rxdata+k);
- }
- for(k=0;k<len;k++) //將數(shù)組轉(zhuǎn)換為 CString 型變量
- {
- strtemp.Format(_T("%c"),*(rxdata+k));
- m_EditReceive+=strtemp;
- CString temp=_T("\r\n"); //換行
- m_EditReceive+=temp;
- }
- }
- UpdateData(FALSE); //更新編輯框內(nèi)容
- }
//接收到的數(shù)據(jù)存放在
//byte 型數(shù)組 rxdata[1024]中,再進行進一步處理,此處只是
//以 16 進制顯示出來
//說明(自己的理解):上面是基于事件驅(qū)動型的串口通信方式,感覺事件驅(qū)動與中斷類似,但
//絕對不是中斷,每一次響應(yīng)事件的時候接收緩沖區(qū)的數(shù)據(jù)的長度不是固定的。例如:我的下
//位機發(fā)送了 10 個 BYTE 的數(shù)據(jù),第一次上位機響應(yīng)的時候只接收到 8 個,第二次響應(yīng)時接收
//到另外兩個。并不是每收到一個數(shù)據(jù)就響應(yīng)一次。
下圖是測試結(jié)果 收到的是a,b......顯示的是數(shù)字碼;

特被注意的是這樣編程并不是所有的電腦都會兼容MSCOMM32.OCX,這時候就需要我們手動的在代碼里面動態(tài)的注冊MSCOMM32.OCX控件,函數(shù)的實現(xiàn)都是成APP函數(shù)開始 ,我們在APP函數(shù)的初始化函數(shù)中注冊這個控件
實現(xiàn)代碼:
- BOOL CProgrammerApp::InitInstance()
- {
- HINSTANCE h;
- h = ::LoadLibrary(_T("MSCOMM32.OCX"));
- FARPROC pFunc = ::GetProcAddress((HMODULE)h,"DllRegisterServer");
- if (pFunc==NULL)
- {
- ::MessageBox(NULL,_T("OCX控件加載失?。?),_T("錯誤"),MB_ICONERROR);
- return FALSE;
- }
- pFunc();
- ......
- 略
- }
解決不能發(fā)送oXoo 的問題
上面不能實現(xiàn)0x00發(fā)送的原因是因為字符串本身就是以0x00默認(rèn)作為結(jié)束符,所以在數(shù)據(jù)發(fā)送到0x00時候就會默認(rèn)的發(fā)錯 而且 大于127是負(fù)數(shù) ,系統(tǒng)并不知道你是帶符號還是不帶符號 上面的方法系統(tǒng)會默認(rèn)帶符號 所以發(fā)送0x00或則大于127的數(shù)據(jù)就會發(fā)送錯誤。
下面是實現(xiàn)的方法
實現(xiàn)的方法是 將需要發(fā)送的內(nèi)容通過二進制發(fā)送
- void CProgrammerDlg::TranSmitt(void)
- {
- int i;
- unsigned short sum = 0; //計算校驗和
- CByteArray array;
-
- for(i=0; i< m_sendlength; i++) //計算校驗和
- {
- sum += Txbufer[i];
- }
-
- sum =sum^0xFFFF;
- Txbufer[m_sendlength++] = (unsigned char)(sum&0x00FF);
- Txbufer[m_sendlength++] = (unsigned char)((sum&0xFF00) >> 8); //存儲校驗和
-
- array.RemoveAll(); //清空數(shù)組
- array.SetSize(m_sendlength); //設(shè)置數(shù)組大小為幀長度
-
- for(i=0; i< m_sendlength; i++) //把待發(fā)送數(shù)據(jù)存入數(shù)組
- {
- array.SetAt(i,Txbufer[i]);
- }
- m_mscomm.put_Output(COleVariant(array));
- }
|