天津科技大学2011届本科生毕业论文
To Project→ Components and Controls”菜单命令,在弹出的对话框中选择 Registerd ActiveX文件夹中的 Microsoft Communications Controls,Version6.0,单击工nsert按钮牛可以完成添加MSComm控件的操作。
MSComm提供两种处理通信问题的方法,一是事件驱动方法,一是查询法。
在此系统中使用事件驱动方法。
事件驱动通信是处理串行端口交互作用的一种非常有效的方法。在许多情况下,在事件发生时需要得到通知,例如,在串口接收缓冲区中有字符,或者Carrier Detect(CD)或 Request To Send(RTS)线上一个字符到达或一个事件发生时。在这些情况下,可以利用MSComm控件的OnComm事件捕获并处理这些通信事件。OnComm事件还可以检查和处理通信错误。在编程过程中,只需要在OnComm事件处理函数中加入自己的处理代码。这种方法的优点是程序相应及时,可靠性高。 2)MSComm控件的属性
MSComm控件有很多重要的属性。在此介绍本系统使用的一些属性。 CommPort属性
这一属性用于设置并返回连接的串行端口号。windows会利用该串口和外界 通信。在设计时,端口号可以设置为1^16中的任意一个,但是如果用Port OPen 打开一个并不存在的端口时,MSComm控件会产生错误68(设备无效)。 Setting属性
该属性用于设置并返回数据传输速率、奇偶校验、数据比特位数、停止比特参数。‘场端[J打开时,如果设置参数非法,则MSComm控件,山二‘}三错误380(非法属性值)。其传递参数山四个设置值组成,组成格式如下:
“BBBB,P,D,S”,本系统使用的设置值为 :115200,N,8,l。 这里BBBB为数据传输速率,合法值可以是 110,300,600,1200,2400等;
P为奇偶校验参数,其合法值可以是E(偶校验)、M(标号校验)、N(无校 验)、O(奇校验);
D为数据比特数,合法值为5^8; S为空格校验。 RThreshold 属性
当接收字符后,若RthreShold属性设置为0(默认值)则不产生OnCollun事件。否则,该属性为一闭值,当接收缓冲区内字节个数达到或超过该之后就会 产生OnCommn事件。例如,设置RThreshold为l,接收缓冲区收到每一个字符都会使MSComm控件产生OnComm事件。本系统将RThreshold设为1。 InBuffersize和outBuffersize属性
这两个属性用于设置或返回输入/输出缓冲区大小。
26
天津科技大学2011届本科生毕业论文
InputMode属性
该属性用于设置或返回传输数据的类型。其值若取0,则表示以文本方式取 回数据;取1则表示以二进制方式取回数据。 PortOpen属性
PortOpen属性用于打开或者关闭端口。如果传递参数为TRUE,则打开串口;如果为FALSE,则关闭串口。在打开端口前,需要确定CommPort属性设置了正确的端口号;Settings属性也己经正确设置。在关闭程序时,端口会被自动关闭。 3)MSComm设置流程 在当前工程插入MSComm控件
通过在A.MSColnln控件概述中介绍的方法将MSColnln空间添加到控件工具箱面板,然后将工具箱中代表MSComm的图标—小电话标志拖入工程界面中,就
在当前工程添加了MSComln控件。要使用MSComm控件,还需要在ClassWizard中为该控件声明一个变量。本系统声明的变量为m_ctrlComm。其实,这就相当将类实例化为对象。 初始化并打一开串口
? 对串口进行初始化一般说来要完成以下几个设置:
? 设定通信端口号,即Commport属性.设定传输速率等参数,即Setting属
性
? 设定其他参数,有必要时再加上其他的属性设定 ? 打开通信端口,即将PortOpen属性设为TRUE 下面对本系统使用的初始化代码进行简要说明:
m_ctrIComm.SetCommPort(1); //选择COM1
m_ctrlComm.SetlnputMode(1); //输入方式为二进制方式 m_crtlComm.SetlnBuff6rsize(1024); //设置输入缓冲区大小 m_crtlComm.Setout日uffersize(512); //设置输出缓冲区大小 //波特率 115200,无校验,8个数据位,1个停止位 m_crtIComm.Setsettings(\115200,n,8,1\ if(!m_crtlComm.GetPortOpen())
m_crtlComm.SetportOPen(TRUE);//打开串口 //参数1表示每当串口接收缓冲区中有多于
//或等于1个字符时将引发一个接收数据的OnComm事件 m_ctrlComm.SetRThreshold(1)
m_ctrlComm.SetlnputLen(0)://设置当前接收区数据长度为0
27
天津科技大学2011届本科生毕业论文
? 串口读写
串口读写使用GetInput()和SetOutput()函数。这两个函数的原型是: VARIANT GetInput():
Void SetOutput(const VARIANT&newValue);
它们都使用VARIANT类型进行参数传递。程序内部平时使用char字符串,在此时需要进行类型转换。 ? 关闭串口
手工关闭串口可以使用SetPortopen(FALSE)方法。点击界面“CloseCom”按钮就可关闭串口。
4)使用MSComm时相关的数据类型转换
? 发送过程:将数据转换成VAR工ANT类型关闭串口
VARIANT其实是一个C++结构类型,COleVariant类型对VARIANT做了进一步的封装和扩展,提供了许多新的功能和操作方法,支持OLE自动化,且更容易向其数据成员填入数据。由于C01eVariant类型由VARIANT派生而来,因此将COleVariant类型的变量传递给Setoutput函数更为方便。另外,Setoutput的参数newValue类型必须是存放字节类型数据的动态数组。因此,可以利用visua1 C++提供CByteArray类型来构造COlevar.iant类型的对象,并将其传递给Setoutput函数。对CByteArray类型变量的操作相对来说要容易的多,比如其成员函数SetSize可用来设置动态数组的大小,下标操作符[]可用来为其元素赋值等等。
用BYTE →CByteArray →COleVariant的方法可以很方便地发送ASCII数据。关键实现代码如下所示:
// 从串口发送存放在缓冲区strBuf中的 100个字节的数据 BYTE strBuf[1281; CByteArray OutBuf; COleVariant varOutPut; ......
OutBuf.SetSize(100): for(i=0;i<100:i++)
OutBuf[i]=strBuf[i]; //BYTE转CByteArray varOutput=OutBuf: //CByteArray转COleVariant m_pCommDlg→m_Comm.SetOutput(varoutput):
? 接收过程:将vARIANT类型转换为其他类型
28
天津科技大学2011届本科生毕业论文
将VARIANT类型转换为可用类型可以使用多种方法,比如
VARIANT→COleVariant→CByteArray或VARIANT→COlesafeArray→CString。由于 CString处理字符串十分方便,因此本系统使用第二种转换方法。
if(m_ctrlcomm.GetCommEvent()==2)//事件值为2表示接收缓冲区内有字符 {
Variant_inp=m_ctrlComm.GetInput()://读缓冲区
Safearray_inp=variant_inp://VARIANT型变量转换为ColeSafeArray型变量 Len=safearray_Inp.GetOneDimSize();//得到有效数据长度 for(k=0;k Safearray_inp.GetElement(&k,rxdata+k);//转换为BYTE型数组 for(k=0;k BYTE showString; Showstring=*(char*)(rxdata); //字符型 //strtemp.Format(\c\,showString); //将字符送入临时变量strtemp存放 strtemp.Format(\02x\showString); //十六进制显示 m_stateShow+=strtemP; // 加入接收编辑框对应字符串 4.2 解码温度数据 从FPGA得来的温度数据是以十六进制存储的,终端程序需要将十六进制的数据解码,转换成以摄氏温度表示的温度值。 由于接收到的数据Byte0是低位数据,Byte1是高位数据。本系统采用12位精度采样。因此,温度换算可以用 (4-1)式表示: 温度= 实现此功能的关键代码如下: (4-1) Case read1: //接收Byte 0 temperature.Format(\d”,showString);/lshowstring转十进制整数 temp=atoi((LPCTSTR)temperature): break; 29 天津科技大学2011届本科生毕业论文 Case read 2: //接收Byte 1 temperature.Forrnat(\d\,showString); // showString转十进制整数 Temp= temP+256*atoi((LPCTSTR)temperature); //temp是整数 Tem_f(double)temp*0.0625; //temp_f为浮点型 temperature.Format(\4f\,temp): //显示格式为4位精度的小数 m_temperature=temperature; //输出到界面上的文本框 break; 4.3 程序设计关键点 在串口事件处理程序中,相关的变量有两个:一个是串日接收到的内容,上面智能温度采集控制器体系架构另一个是当前状态。对这样的事件处理,可以使用两种思想方法:首先检查接收到的数据,然后再根据当前状态进行后续处理;或者相反,先查看当前状态,再根据接收到的内容进行后续处理。前者一般使用标志位进行处理,后者一般使用状态机的方法。 为了使程序思虑更清晰,本系统使用了类似状态机的方法。该方法使用一个全局变量State记录每次事件执行的状态,在本状态事务处理完毕之后,将State改写为下一次事件发生时应该处于的状态。 Static enum statetype { init,init2,init3,readrominit,convert,readpad,readByte,readBit,readrom,disPlay ID,read1,read2,matehrom1,matehrom2,sendid1,sendid2,searehrom,error,idle }; enum statetype state; //定义状态机类型为枚举类型 switch(state) //通过switeh…ease…结构完成状态机描述 { Case init: ..... State=matchrom; //执行完init状态应完成的任务后改变state为下一状态 break; Case matchrom: ... Break; ...} 30