基础太弱,看似很简单的程序也很费周折,MFC熟吗?VC++6.0的环境熟吗?MSComm控件熟吗?任何一件小事儿对于初学者来说都不易,问题太过简单就无人可问,网上查找资料太过费时。今天学习串口编程,原本很小的程序,折腾我大半天,记录存档。例子是《Visual C++ 串口通信技术详解》李景峰、杨丽娜、潘恒著,机械工业出版社2010年6月第1版,这本书中的例子。
1.打开VC++6.0,NEW,创建一个名为TTYReceiveMSComm的基于MFC的对话框应用程序。
2.选对话框
3.注意:一定要勾选ActiveX Controls,因为MSComm就是ActiveX Controls控件,所以一定要支持它,否则出错。如不勾选,在实例化MSComm控件的时候将出来如下的错误,这个问题指向了MFC框架内部,暂时还不会解决。
出错:
4.NEXT
5.NEXT
6.NEXT
7.向项目中添加MSComm控件的方法详见《20120904-加载MSComm控件的方法》这篇文章
8.主界面如下
9.在资源管理标签页内,右键Dialog虚拟文件夹,Insert一个Dialog
10.这个设置串口的界面如下.
11.建立控件变量如下
12.建立控件变量如下:
13.双击设置串口的IDD_DIALOG1对话框空白处,为该对话框新建一个类
14.起名字如下
15.在TTYReceiveMSCommDlg.h中引用如下库文件
#include "mscomm.h"
#include "SetupDlg.h"
#include
16.在CTTYReceiveMSCommDlg类的实现部分添加如下变量
CMSComm myComm;
CSetupDlg mySetupDlg;
BYTE myCom;
CString myParity;
CString myBaudRate;
17.主对话框建立的时候,实例化一个MSComm控件,添加OnCreate()函数
int CTTYReceiveMSCommDlg::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CDialog::OnCreate(lpCreateStruct) == -1)
return -1;
DWORD style=WS_VISIBLE|WS_CHILD;
if (!myComm.Create(NULL,style,CRect(0,0,0,0),this,IDC_MSCOMM1))
{
AfxMessageBox("创建MSComm控件失败!");
m_Opencom.EnableWindow(false);
m_Closecom.EnableWindow(false);
m_Setupcom.EnableWindow(false);
return -1;
}
m_Para="COM1,9600,N,8,1";
return 0;
}
18.添加Setup()函数
void CTTYReceiveMSCommDlg::OnSetup()
{
CString strStatus,strTemp;
double dblBaud;
if(mySetupDlg.DoModal()==IDOK)
{
myCom=mySetupDlg.m_Com+1;
dblBaud=pow(2,(double)mySetupDlg.m_BaudRate);
dblBaud=19200/dblBaud;
strStatus.Format("%.0f",dblBaud);
myBaudRate=strStatus;
switch(mySetupDlg.m_Parity)
{
case 0:
{
myParity="N";
break;
}
case 1:
{
myParity="O";
break;
}
case 2:
{
myParity="E";
break;
}
}
strStatus="COM";
strTemp.Format("%d",myCom);
strStatus+=strTemp;
strStatus+=",";
strStatus+=myBaudRate;
strStatus+=",";
strStatus+=myParity;
strStatus+=",8,1";
m_Para=strStatus;
UpdateData(false);
}
}
19.添加opencom函数
void CTTYReceiveMSCommDlg::OnOpencom()
{
//以下的初始化只是一个例子,根据实际程序要求的不同,
//初始化代码可能与此有差别。斜体字代码是必须的。
CString strPara; //串口参数
myComm.SetCommPort(myCom); //指定串口号myCom
strPara=myBaudRate;
strPara+=",";
strPara+=myParity;
strPara+=",8,1";
myComm.SetSettings(strPara); //通信参数设置
myComm.SetInBufferSize(1024); //指定接收缓冲区大小
myComm.SetInBufferCount(0); //清空接收缓冲区
myComm.SetInputMode(1); //设置数据获取方式
myComm.SetInputLen(0); //设置每次读取长度
myComm.SetRThreshold(1); //设置接收OnComm事件门限值
myComm.SetPortOpen(1); //打开串口
m_Opencom.EnableWindow(false); //使“打开串口”按钮无效
m_Closecom.EnableWindow(true); //使“关闭串口”按钮生效
m_Setupcom.EnableWindow(false); //使“设置”按钮无效
m_Exit.EnableWindow(false); //使“退出”按钮无效
AfxMessageBox("串口打开成功!");
}
20.添加关闭串口
void CTTYReceiveMSCommDlg::OnClosecom()
{
myComm.SetPortOpen(0);
AfxMessageBox("串口关闭成功!");
m_Opencom.EnableWindow(true);
m_Closecom.EnableWindow(false);
m_Setupcom.EnableWindow(true);
m_Exit.EnableWindow(true);
}
21.退出函数
void CTTYReceiveMSCommDlg::OnExit()
{
this->EndDialog(IDOK);
}
22.添加接收响应函数
void CTTYReceiveMSCommDlg::OnOnCommMscomm1()
{
VARIANT input1;
BYTE rxdata[2048];
long len1,k;
COleSafeArray safearray1;
CString strDis;
switch(myComm.GetCommEvent())
{
case 2:
//收到 RThreshold 个字符
//添加接收处理代码
input1=myComm.GetInput();
//将VARAIANT变量赋值给COleSafeArray类的实例
safearray1=input1;
//使用COleSafeArray类的成员函数获取数据长度
len1=safearray1.GetOneDimSize();
for(k=0;k=32)
{
strDis+=rxdata[k];
m_Edit1.SetSel(1000000,1000000);
m_Edit1.ReplaceSel(strDis);
strDis="";
UpdateData(false);
}
}
}
}
}
************************************************************************************************
************************************************************************************************
代码上传自我的资源中。
此刻起,再不忽视任何一件小事,谨记!
2012.09.08 于家中