本节内容为电脑串口通信上位机的编写,使用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=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