本節內容爲電腦串口通信上位機的編寫,使用MFC編寫串口通信上位機程序,主要是通過微軟提供的MSComm控件來編寫的。使用控件提供的API函數,編寫上位機較爲簡單,利於開發。本例程是基於電壓採集實驗完成的,下位機使用的是TI的C2000系列DSP TMS320F280049C,下位機將採集到的電壓數據通過串口發送給上位機上顯示,上位機中添加了TeeChart控件來顯示採集到的電壓波形。TeeChart控件的使用將會在後續的博客中講述,敬請關注。
(1)MSComm控件介紹
MSComm控件的下載網址如下:https://download.csdn.net/download/fanxianyan1993/10990498
MSComm控件的常用屬性如下所示:
CommPort: | 設置和獲取當前的串口號 put_CommPort,get_CommPort函數 |
PortOpen: | 打開或者關閉串口 put_PortOpen函數 |
Settings: | 設置和獲取當前通信的數據格式 put_Settings,get_Settings函數 |
Input: |
從接收緩衝區返回和刪除字符 |
Output: |
向傳輸緩衝區寫一個字符串 |
MSComm控件的常用函數的使用方式如下所示:
- m_ctrlComm.get_PortOpen(); 獲取當前端口的狀態。
- m_ctrlComm.put_CommPort(BOOL newValue); 設置串口編號。
- m_ctrlComm.put_PortOpen(TRUE); 打開串口。
- m_ctrlComm.put_Settings(_T("460800,n,8,1"));設定串口的通信格式。
- m_ctrlComm.put_InputMode(1); 0:以文本方式取回數據;1:以二進制方式檢取數據。
- m_ctrlComm.put_RThreshold(1); 參數1表示每當串口接收緩衝區中有多於或等於1個字符時將引發一個接收數據的OnComm事件。
- m_ctrlComm.put_InputLen(0); 設置當前接收區數據長度爲0。
(2)建立工程
先創建基於對話框的MFC程序,在對話框中添加MSComm控件。在對話框界面上點擊右鍵,點擊插入ActiveX控件(X),再選擇Microsoft Communications Control,version 6.0(SP6)。這時對話框界面上就會出現一個電話的圖標,任意放個位置,程序運行後看不到該圖標。
(3)連接串口
串口連接的程序如下所示,打開串口前先判斷串口是否已經被打開了,如果串口已經打開了,先關閉串口,再對串口進行操作。打開串口後再對串口進行配置,主要包括數據格式、輸入模式以及緩衝區的設置。
void CMFC_COM_Test02Dlg::OnBnClickedComOpen()
{
if(nConnectFlag == 0)
{
if(m_ctrlComm.get_PortOpen())
m_ctrlComm.put_PortOpen(FALSE);
m_ctrlComm.put_CommPort(m_nCom+1);
m_ComBo.SetCurSel(m_nCom);
if(!m_ctrlComm.get_PortOpen())
{
m_ctrlComm.put_PortOpen(TRUE); //打開串口
// AfxMessageBox(_T("打開串口成功!"));
GetDlgItem(IDC_COM_OPEN) ->SetWindowText(_T("關閉串口"));
nConnectFlag=1;
}
else
AfxMessageBox(_T("打開串口失敗!"));
m_ctrlComm.put_Settings(_T("460800,n,8,1"));
m_ctrlComm.put_InputMode(1); //1:表示以二進制方式檢取數據
m_ctrlComm.put_RThreshold(1);
//參數1表示每當串口接收緩衝區中有多於或等於1個字符時將引發一個接收數據的OnComm事件
m_ctrlComm.put_InputLen(0); //設置當前接收區數據長度爲0
m_ctrlComm.get_Input(); //先預讀緩衝區以清除殘留數據
}
else
{
if(m_ctrlComm.get_PortOpen())
{
m_ctrlComm.put_PortOpen(FALSE); //關閉串口
}
GetDlgItem(IDC_COM_OPEN) ->SetWindowText(_T("開啓串口"));
nConnectFlag = 0;
AfxMessageBox(_T("串口關閉成功!"));
}
}
(4)自動識別串口
當電腦上插入了串口線後,需要上位機軟件選擇相應的串口號來打開串口。添加自動串口識別程序後,當電腦上接入了串口後,上位機軟件就能自動識別串口號。在MFC編程中,通過調用CreateFile函數打開串口,通過函數返回的句柄來判斷串口是否存在。串口識別的代碼需放在對話框初始化函數OnInitDialog()當中,這樣當打開串口時就能獲得有效的串口編號。串口識別的源代碼如下所示:
HANDLE hComm;
CString ComName[] = {_T("COM1"),_T("COM2"),_T("COM3"),_T("COM4"),
_T("COM5"),_T("COM6"),_T("COM7"),_T("COM8"),_T("COM9")};
for(int i=0;i<9;i++)
{
hComm =(HANDLE)CreateFile(ComName[i], GENERIC_READ | GENERIC_WRITE, 0,
NULL,OPEN_EXISTING, 0, NULL);
if(hComm != INVALID_HANDLE_VALUE)
{
m_nCom = i;
m_ComBo.SetCurSel(m_nCom);
CloseHandle(hComm); //關閉句柄,不然出錯
break;
}
}
(5)數據接收
上位機接收數據時,需要添加消息響應函數來獲取串口發送的數據。鼠標右鍵點擊串口通信的控件,點擊添加事件處理程序,再點擊添加編輯後,編譯器就會添加消息處理函數OnCommMscomm()。
消息響應函數中主要通過get_Input()函數從緩衝區中讀取數據,數據接收的源代碼如下所示:
void CMFC_COM_Test02Dlg::OnCommMscomm()
{
VARIANT variant_inp;
COleSafeArray safearray_inp;
LONG len,k;
BYTE RxData[2048]; //設置BYTE數組 An 8-bit integerthat is not signed.
CString strTemp;
CString RX_Data;
if(m_ctrlComm.get_CommEvent()==2) //事件值爲2表示接收緩衝區內有字符
{ //以下你可以根據自己的通信協議加入處理代碼
variant_inp=m_ctrlComm.get_Input(); //讀緩衝區
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(_T("%c"),bt); //將字符送入臨時變量strtemp存放
RX_Data += strTemp;
}
m_Voltage = RX_Data;
if(nDisplayFlag)
{
m_chart.Series(0).AddXY(m_nCount,_ttoi(RX_Data),NULL,NULL);
m_nCount++;
if(m_nCount>=2000)
{
m_chart.Series(0).Clear();
m_nCount=0;
}
}
}
UpdateData(FALSE);
}
(6)發送數據
上位機發送數據時,只需調用put_Output()即可。程序的源碼如下所示:
void CMFC_COM_Test01Dlg::OnBnClickedSend()
{
UpdateData(TRUE); //從控件上獲取數據
CString strTxData;
int nLen = m_RichEditRXData.GetTextLength();
m_RichEditRXData.SetSel(0,nLen);
strTxData = m_RichEditRXData.GetSelText();
m_ctrlComm.put_Output(COleVariant(strTxData));
m_TxNum++;
UpdateData(FALSE);
}
(7)上位機軟件
最後,編寫的上位機軟件如下圖所示。下位機通過串口將採集到的電壓(圖中並非實際採集到的的電壓,而是下位機隨意發送的數據)發送給上位機,上位機再將電壓以波形的形式顯示出來。
程序源碼的下載地址爲:https://download.csdn.net/download/fanxianyan1993/10991289
提問方式:有啥不懂的可以隨時向我提問哈,掃描下方二維碼我會在第一時間給大家回覆的哈,謝謝。