首先电脑应该有MSCOMM32.OCX并注册,我在相关文章写了安装过程
建立项目
使用VS2005新建一个基于对话框的MFC项,在资源视图,右键窗体,插入ActiveX控件,选择Microsoft Communications Control

之后窗体就会出现一个电话图标,表示MSCOMM控件,这个图标在运行时并不会显示

添加MSCOMM控件变量
给MSCOMM控件添加一个变量,有两种办法,
==方法一==
直接对控件右键,添加变量

填写变量名字,系统会自动生成变量。并且建立一个CMscomm1类和它的头文件、源文件

==方法二==
在解决方案管理器,点击项目,添加类,选择ActiveX控件中的MFC类

在可用的ActiveX控件,选择Microsoft Communications Control,下面的接口使用>移动到右侧生成的类,点击完成,系统自动创建一个CMSComm类、它的头文件CMSComm.h和源文件CMSComm.cpp

在窗体类的头文件里包含
定义一个变量
在窗体的DoDataExchange函数里建立与ocx控件IDC_MSCOMM1的数据关联
void CSerialPortQDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_MSCOMM1, m_MSComm);
}
变量就添加完成了
串口的打开和关闭
在窗体添加两个按钮,打开和关闭串口,实现功能
打开串口
void CSerialPortQDlg::OnBnClickedButton1()
{
// TODO: 在此添加控件通知处理程序代码
if(m_MSComm.get_PortOpen())//如果串口已打开则返回
{
return;
}
m_MSComm.put_CommPort(2);//选择COM2
m_MSComm.put_InputLen(0);//设置当前接收区数据长度为0
m_MSComm.put_InputMode(1);//1表示以二进制方式读写数据
m_MSComm.put_RThreshold(1);//接收缓冲区有1个及1个以上字符时,将引发接收数据的OnComm事件
m_MSComm.put_Settings(_T("9600,n,8,1"));//波特率9600 无检验位,8个数据位,1个停止位
m_MSComm.put_PortOpen(TRUE);//打开串口
m_MSComm.get_Input();//预读缓冲区以清除残留数据
MessageBox(L"打开串口成功");
}
关闭串口
void CSerialPortQDlg::OnBnClickedButton2()
{
// TODO: 在此添加控件通知处理程序代码
if(m_MSComm.get_PortOpen())//如果串口已打开则关闭
{
m_MSComm.put_PortOpen(FALSE);
MessageBox(L"关闭串口成功");
}
}

串口发送和接收数据
窗体添加两个CEdit控件,一个显示接收数据,一个发送数据。
其中接收数据的控件,属性里面
Vertical Scroll设置ture
Multiline设置true
Read Only设置true
为了方便显示收发数据,在窗体类添加两个CString变量,并与两个CEdit建立关联
在DoDataExchange里面将变量与控件建立数据交换
void CSerialPortQDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
DDX_Control(pDX, IDC_MSCOMM1, m_MSComm);
DDX_Text( pDX, IDC_EDIT1, m_strGet);//接收的数据
DDX_Text( pDX, IDC_EDIT2, m_strSend);//发送的数据
}
数据接收
对OCX控件右键,添加事件处理程序。选择OnComm消息,添加编辑

void CSerialPortQDlg::OnCommMscomm1()
{
// TODO: 在此处添加消息处理程序代码
VARIANT variant_inp;
COleSafeArray safearray_inp;
LONG len,k;
BYTE rxdata[2048]; //设置BYTE数组 An 8-bit integer that is not signed.
CString strtemp;
if(m_MSComm.get_CommEvent()==2) //事件值为2表示接收缓冲区内有字符
{
variant_inp=m_MSComm.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(L"%c",bt); //将字符送入临时变量strtemp存放
m_strGet += strtemp; //字符追加到接收编辑框对应的字符串变量
}
}
m_strGet += L"\r\n";//加换行
UpdateData(FALSE); //将数据更新到控件
}
数据发送
void CSerialPortQDlg::OnBnClickedButton3()
{
// TODO: 在此添加控件通知处理程序代码
UpdateData(TRUE);//控件数据更新到字符串变量
m_MSComm.put_Output(COleVariant(m_strSend));//发送数据
}

16进制数据的收发
添加一个选择框,决定16进制发送,右键选择框,添加一个变量

转换函数
用到函数将CString转化为CByteArray
char ConvertHexChar(char ch)
{
if((ch>='0')&&(ch<='9'))
return ch-0x30;
else if((ch>='A')&&(ch<='F'))
return ch-'A'+10;
else if((ch>='a')&&(ch<='f'))
return ch-'a'+10;
else return (-1);
}
int String2Hex(CString str, CByteArray &senddata)
{
int hexdata,lowhexdata;
int hexdatalen=0;
int len=str.GetLength();
senddata.SetSize(len/2);
for(int i=0;i<len;)
{
char lstr,hstr=str[i];
if(hstr==' ')
{
i++;
continue;
}
i++;
if(i>=len){
break;
}
lstr=str[i];
hexdata=ConvertHexChar(hstr);
lowhexdata=ConvertHexChar(lstr);
if((hexdata==16)||(lowhexdata==16)){
break;
}else{
hexdata=hexdata*16+lowhexdata;
}
i++;
senddata[hexdatalen]=(char)hexdata;
hexdatalen++;
}
senddata.SetSize(hexdatalen);
return hexdatalen;
}
数据发送
void CSerialportDlg::OnBnClickedButton4()
{
UpdateData(TRUE);//控件数据更新到字符串变量
if(m_16Check.GetCheck()){
CByteArray hexdata;
int len=String2Hex(m_strSend,hexdata); //此处返回的len可以用于计算发送了多少个十六进制数
m_MSComm.put_Output(COleVariant(hexdata)); //发送十六进制数据
}else{
m_MSComm.put_Output(COleVariant(m_strSend));//发送数据
}
}
数据接收
void CSerialPortQDlg::OnCommMscomm1()
{
// TODO: 在此处添加消息处理程序代码
VARIANT variant_inp;
COleSafeArray safearray_inp;
LONG len,k;
BYTE rxdata[2048]; //设置BYTE数组 An 8-bit integer that is not signed.
CString strtemp;
if(m_MSComm.get_CommEvent()==2) //事件值为2表示接收缓冲区内有字符
{
variant_inp=m_MSComm.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); //字符型
if(m_16Check.GetCheck()){
strtemp.Format(L"%02x ",bt); //将字符以十六进制方式送入临时变量strtemp存放
}else{
strtemp.Format(L"%c",bt); //将字符送入临时变量strtemp存放
}
m_strGet += strtemp; //字符追加到接收编辑框对应的字符串变量
}
}
m_strGet += L"\r\n";//加换行
UpdateData(FALSE); //将数据更新到控件
