基础太弱,看似很简单的程序也很费周折,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 <math.h>
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<len1;k++) //使用COleSafeArray类的成员函数将数据写入数组 safearray1.GetElement(&k,rxdata+k); for(k=0;k<1;k++) { if(rxdata[k]==13) { m_Edit1.SetSel(1000000,1000000); m_Edit1.ReplaceSel("\15\12"); UpdateData(false); } else { if(rxdata[k]<=126 && rxdata[k]>=32) { strDis+=rxdata[k]; m_Edit1.SetSel(1000000,1000000); m_Edit1.ReplaceSel(strDis); strDis=""; UpdateData(false); } } } } }
************************************************************************************************
************************************************************************************************
代码上传自我的资源中。
此刻起,再不忽视任何一件小事,谨记!
2012.09.08 于家中