VC++下串行通信的编程方法

张 力 吕振肃 赵庆林

1 引言

  串行通信程序是微机监控软件中基础、关键的一个环节,如何有效地开发通信程序,是软件开发人员所关心的话题。Microsoft公司从1993年推出VC++1.0开始,不断升级,从 VC++1.52到目前最新的 VC++5.0,拥有大量的用户,用VC++开发串行通信程序也随版本的不同各有特点。本文详细地介绍了用VC编写通信程序的两种方法:
  . 用API(Application Programm Interface用户程序接口)函数;
  .
用OLE(Object Linking and Embedding对象链接与嵌入)控件。

2 用API函数实现串行通信

  API函数是Windows程序开发使用的主要函数集,其中提供了十几个专门的通信函数。对应Windows3.x和Win95及 NT开发环境,有16位和32位通信API函数,VC++ 2.0和以前的版本都保持16位和32位两个版本,从 VC++4.0 以后,软件只支持32位应用程序的开发。目前较多的应用是在Win95及NT的32位开发环境下,但也存在着Windows3.x下开发的16位通信程序向32位程序的移植问题。基于这种考虑,16位通信函数也列举出来。

2.1 主要通信函数的对比

  32位通信函数与16位函数的主要区别在于,32位API函数把对通信口的操作当作一个普通文件。这是因为在Windows95和NT下,WMCOMMNOTIFY消息已被取消,操作系统已将通信设备封装起来了,系统为每个通信设备定义了用户可定义大小的读/写缓冲区,应用程序只对读/写缓冲区操作,而不用和通信驱动程序打交道。
功能描述16位函数改进的32位函数打开通信资源OpenCommCreatFile关闭通信资源CloseCommCloseHandle读通信缓冲区ReadCommReadFile写通信缓冲区WriteCommWriteFile设置通信事件SetCommEventSetCommMask通信错误检查GetCommErrorClearCommError

2.2 用API函数编程的过程

  首先由应用向导(AppWizard)生成程序的主框架。在集成开发环境下选File/New菜单(以VC5.0为例),弹出New对话框,单击project标签后选MFC AppWizard (exe)项,在创建的第一步选中单文档,其他五步接受缺省选项,只需编辑生成的视类.cpp文件即可。可以用两种方法编程:一种是利用Windows的 WMCOMMNOTIFY消息,映射出该消息的处理函数,通信编码就放在该函数中,这主要适用于VC2.0及以前的版本 ;另一种方法是直接在.CPP文件中编写通信部分,把通信当作视类的成员函数。不论用哪种方法,编程思路是相同的:设置初始化并打开串口—配置串口—在双方间传输数据,并进行校验等处理—不需要时释放串口,供其他程序使用。

2.3 注意事项

  在Windows 3.x 中,有专门的消息WMCOMMNOTIFY用于通信。在Windows95和NT下,该消息已被取消,但用户也可以用自定义的WMCOMMNOTIFY消息,这时要注意消息映射的声明必须如下:
  ONMESSAGE (WMCOMMNOTIFY,memberFxn); 其中memberFxn是该消息的处理函数名。
  Win95中新增了基于线程的多任务,当应用程序希望仅在通信设备有数据出现时才对其操作,应创建线程来监视通信设备。考虑到通信较费时,建议使用多线程来管理通信,让通信在后台完成。在VC++的 MFC(Microsoft Foundation Classes 微软基础类库)中提供了专门管理线程的类 CwinThread,同时VC++还提供了一些与线程有关的全局函数,如AfxBeginThread等。多线程中资源共享时,必须借助一些Win32同步函数来协调线程的活动,避免冲突。VC的MFC也提供了几个与同步有关的类,如CSyncObject、CMutex、CSemaphore、Cevent等。在视类的.cpp文件下可创建通信线程,并根据实际需要确定线程的优先级,合理调用 API函数以实现通信。

3 用OLE通信控件实现串行通信

  用VC++的OLE控件实现串行通信,是一种简洁的编程方法。VC4.0版和VC5.0版所提供的通信控件略有不同,下面针对这两个版本,对OLE通信控件做具体介绍。

3.1 通信控件的插入

  在VC++4.0 下,首先生成一个项目,或者打开一个存在的项目。选择菜单Insert/Component…,出现Component Gallery窗口,选中OLE Controls下的Microsoft CommControl,双击就将控件嵌入到项目文件中了。在VC++5.0下,选菜单Project/Add To Project,将会有一子菜单, 选中 Component and Controls项(注意如果没有打开项目,Component项不会出现在子菜单项中),接着双击Registered ActiveX Controls,在其中会找到通信控件5.0,双击之便可插入。此时打开对话框编辑器,在工具条中会看到新增的通信控件。

3.2 在程序中使用通信控件

  象所有其他OLE控件一样,通信控件也是用一系列的属性和用户接口,用户用Get…函数得到属性的当前值,用 Set…函数设置属性值。控件提供了27个属性,大部分属性仅和Modem连接有关,现将常用的属性列举如下:
  CommPort: 设置并返回通信口号,缺省值为COM1,可设置1—16个。
  Settings: 设置并返回波特率、奇偶校验、数据位、停止位的字符串。其中波特率的范围为300b/s-19200b/s。
  PortOpen: 设置并返回通信口的状态,同时用来打开和关闭通信口。
  InputLen: 决定每次Input读入的字符个数,缺省为0,表示读取接收缓冲区的全部内容。
  Input: 读入并清除接收缓冲区的字符。
  InBufferCount: 返回接收缓冲区已接收的字符数,通过置0可清除接收缓冲区。
  Output: 将发送的字符串或数组写到发送缓冲区。
  InputMode: 定义Inpput属性获得数据的方式(VC5.0新增属性)。
  Rthreshold: 设置、返回在通信控件置 ComEvRecieve并激发 OnComm事件前要接收的字符数。
  SThreshold: 设置、返回通信控件置ComEvSend并激发OnComm事件前发送缓冲区中的最少字符数。
  将通信控件放到对话框中,当作一个普通的控件来用。控件提供了两种处理方法:一是查询,一是事件驱动。对于较简单的通信任务,可通过查询串口的CommEvent属性来了解最近发生的事件或错误并进行相应的处理,较复杂的通信任务就应使用事件驱动接口。用事件驱动方法时,要定义CMSComm变量,以后针对此对象操作即可。添加消息处理函数时要用类向导ClassWizard,选中定义的 CMSComm变量并单击,在消息栏双击 OnComm项就生成了消息处理函数。 在编写发送和接收函数时,要重点注意几个属性的用法。比如InBufferCount属性返回接收缓冲区中已收到的字节数,查询方法可利用该属性,看是否收到了规定数目的字节。还有 Rthreshold 和 SThreshold属性,对由发送和接收激发的OnComm事件起着决定性的作用。Rthreshold 的值代表每当接收缓冲区中有该数目的字符时就产生 OnComm事件, 这对固定长度的帧接收非常有用,可将 Rthreshold 设为帧长度,每收到一帧就会激发 OnComm事件,在消息处理函数中添加代码就能完成接收后的处理。发送比接收简单,只不过用SThreshold属性。
  概括起来,用控件实现串行通信应该遵循和用API函数编写程序相同的过程,只不过这里用控件的属性代替了API函数。

3.3 其它注意事项

  VC4.0下和VC5.0下Input属性的返回值不同。在 VC4.0下Input 返回的是CString类,而在VC5.0下,返回 COleVariant类。COleVariant类封装了VARIANT数据类型,该结构也是Output属性所要求的类型。要用好控件就必须了解 VARIANT结构, 该结构囊括了所有常用的简单数据类型。但是结构中每次可用的数据类型只有一种,由结构的成员vt识别。例如对字符串bstrVal,vt=8,对short类型,vt=2等等。同时注意到VC5.0控件增加了 InputMode属性,提供两种输入模式:文本和二进制。两种方式决定了Input接收的两种数据类型。在文本方式下,Input返回值在成员bstrVal中,类型为vt=8,这和VC4.0下返回CString类是相同的。在二进制模式下,Input接受值在安全数组parray中,类型为 vt=0x2000 ,这是编程时容易忽略的地方。一般上下位机通信时,下位机的数据是以16进制形式存放,编写通信程序建议选择二进制输入模式。用文本模式就必须在编码时仔细考虑,否则容易丢失数据。另外,用事件驱动方法编程时还应注意,OnComm事件在通信事件或错误发生时都会激发, 在处理函数中应将各种可能的情况列举出来分别处理,很重要的一点是及时处理通信错误。

4 结束语

  总而言之,比起繁多的API函数,通信控件不失为一种简洁有效的实现串行通信的途径。只要掌握好控件的属性,就能轻松地编写通信程序。笔者在编写一套电力系统的实时监控软件时,用VC++5.0下的通信控件成功地实现了微机与下位机——3720ACM 仪表之间的通信,该仪表是加拿大PML公司生产的高级电力综合监控仪表。

张 力 硕士研究生。研究方向:计算机控制与信息工程。 吕振肃 硕士,教授。从事计算机控制与信息工程、CAD等方面的教学与研究工作。 赵庆林 硕士研究生。研究方向:计算机控制与信息工程。

作者单位: 兰州大学电子与信息科学系 甘肃.兰州(730000)

参考文献

 [1] [美]Microsoft Corporation.Microsoft Win32程序员参考大全(二). 北京:清华大学出版社,1995
 [2] [美]Scott Stanfield Ralph Arvesen.Visual C++ 4开发人员指南.北京:机械工业出版社,1997