2024年6月11日发(作者:)

23

卷第

2

2004

6

计 算 技 术 与 自 动 化

ComputingTechnologyandAutomation

Vol

1

23,No

1

2

 

Jun

1

2004

文章编号

:1003-6199

(

2004

)

02-0070-04

Win32

环境下基于

VC++6.0

串口通信编程方法

杨 锋

,

桂卫华

,

陈 峰

,

冯磊华

(

中南大学 信息科学与工程学院

,

湖南 长沙 

410083

)

  摘 要

:

本文介绍了在

Windows32

环境下串口通信的实现机制

,

提出了用

VC++6.0

实现目前常用串口通信程序的四种方法

,

同时分析了这四种方法的优缺点。最后结合深海底

自动采矿实例

,

实现水下工控机与光端机之间串口数据通信。

关键词

:

串口通信

;API

标准通信函数

;

单线程

;

多线程

中图分类号

:TP311.11

        文献标识码

:A

SerialCommunicationProgrammingMethodsBasedVisual

C++6.0inWin32Environment

YANGFeng,GUIWei

2

hua,CHENFeng,FENGLei

2

hua

(

CollegeofInformationScienceandEngineering,CentralSouthUniversity,Changsha410083,China

)

  

Abstract:Therealizedpri

putsforwardfourmethodswhichisusuallyusedtoserialcommunicationprogrammingusingVisualC++6.

0now.,oneofthefourmethods

isusedindeepseabedautomaticminingandtheserialdatacommunicationbetweenthedeepseaengineering

controlmachineandthefiberoptionsisfinished.

Keywords:serialcommunication;APIstandardcommunicationfunction;singleprocess;multipleprocess

1

 引言

在远程监控和工业自动化领域系统中

,

串口通

信的应用越来越广泛。在

DOS

环境下

,

其系统接

口中

DOSINT21H

03H

04H

号功能调用为

异步串行通信的接受和发送功能

,

BIOS

INT14H

4

组功能调用为串行通信服务

,

因此采

用寄存器直接读写

,BIOS

调用

,

通信中断程序等方

法就可以比较容易实现串口通信。但是在

Win

2

dows

环境下

,Windows

采用消息驱动和设备统一

管理

,

以及利用消息队列进行程序控制

,

所以

DOS

下的方法都不宜采用。在

Windows

中为实现串口

通信

,Windows

SDK

提供了完备的

API

函数和

以中断方式驱动的通信驱动程序

,

使编程变得较为

容易。

Windows

提供的标准通信

API

函数很多。

VisualC++

由于功能强大和应用灵活

,

同时得到

Miscrosoft

系统的最好支持

,

因此

VisualC++

常用作串口通信开发工具。本文就

Win32

环境下

基于

VC++

开发串口通信四种方式的编程问题展

开讨论

,

最后给出用其中的一种方法

-MSComm

控件实现深海底自动采矿系统中水下工控机与光

端机之间的串口通信应用实例。

2

 基于

VC++

串口通信编程的四种方式

及其比较

2

1

1

 基于

VC++

串口通信编程的四种方式

2.1.1

 利用

VC++

运行时库的标准通信函数实

现串口编程

(

1

)

初始化串行通讯口

通过计算机串口进行通讯之前

,

必须根据监控

设备的有关通讯参数

,

约定双方的通讯方式

,

包括

波特率的设置、奇偶位校验及停止位的设立。确定

收稿日期

:2004-02-05

)

,

,

湖北黄冈人

,

硕士研究生

,

主要研究方向

:

工业过程监控

,

自动化仪表。作者简介

:

杨锋

(

1979

23

卷第

2

期杨 锋等

:Win32

环境下基于

VC++6.0

串口通信编程方法

71

数据传输帧格式

,

确定

UART

操作方式。逐个对

线路控制寄存器、波特率因子寄存器和

MODEM

寄存器写入操作。

(

2

)

查询发送流程

———只需

CPU

检测到

UART

发送器保持寄

存器为空

,

即向

UART

输出一个字符。发送方首

先输出

RTS

DTR

有效

,

检测

MODEM

寄存器

,

只有收到

DEC

输入的

CTS

DSR

有效

,CPU

才向

UART

输出一发送字符。

(

3

)

查询接收流程

———只需

CPU

检测到

UART

接收器数据准

备就绪

,

即可从接收器数据寄存器中读取一字符。

接收方首先输出数据终端就绪有效

(

DTR=1

)

,

后检测

MODEM

状态寄存器

,

只有

DSR=1,CPU

才接收一字符。

2.1.2

 采用

ActiveX

控件

(

MSComm

控件

)

编程

MicrosoftCommunicationsControl

(

以下简称

MSComm

)

Microsoft

公司提供的简化

Windows

下串行通信编程的

ActiveX

控件

,

它为应用程序提

供了通过串行接口收发数据的简便方法。具体地

,

它提供了两种处理通信问题的方法

:

一是事件

驱动

(

Event-driven

)

方法

:

主要是利用

OnComm

事件捕获并处理这些通信事件

,

也可以检查和处理

通信错误

;

一是查询法

:

在这种情况下

,

每当应用程

序执行完某一串行口操作后

,

将不断检查

MSComm

控件的

CommEvent

属性以检查执行结

果或者检查某一事件是否发生。

以下介绍在

VC

集成开发环境下对该控件编

程的步骤。

(

1

)

在当前的

Workspace

中插入

MSComm

控件

(

2

)

MainFrm.h

中加入

MSComm

控件

protected:

CMSCommm

-

ComPort;

(

3

)

初始化串口

m

-

mPort

(

1

)

;//

选择

COM1

m

-

ufferSize

(

1024

)

;//

设置

输入缓冲区的大小

,Bytes

m

-

BufferSize

(

512

)

;//

设置

有一个字符引发一个事件

m

-

utLen

(

0

)

;

(

4

)

捕捉串口事件

MSComm

控件可以采用轮询或事件驱动的两

种方法从端口获取数据。比较常用的是事件驱动

方法

:

有事件

(

如接收到数据

)

时通知程序。在程序

中需要捕获并处理这些通讯事件。

(

5

)

串口读写

完成读写的两个函数的原型是

VARIANT

GetInput

()

;

voidSetOutput

(

constVARIANT&

newValue

)

;

都要使用

VARIANT

类型。首先由函

GetInBufferCount

()

检查串口接收到的字符数

,

然后由

GetInput

()

函数读取这些已接收的字节。

SetOutput

函数将数据从串口发送出去。

2.1.3

 在单线程中实现自定义的串口通信类

———控件简单易用

,

但由于必须拿到对话框

中使用

,

在一些需要在线程中实现通信的应用场

,

控件的使用显得捉襟见肘。此时

,

若能够按不

同需要定制灵活的串口通信类将弥补控件的不足

,

以下将介绍如何在单线程中建立自定义的通信类。

———该通信类

CSimpleComm

需手动加入头文

件与源文件

,

其基类为

CObject,

大致建立步骤如下

:

(

1

)

打开串口

,

获取串口资源句柄

———通信程序从

CreateFile

处指定串口设备

及相关的操作属性

,

再返回一个句柄

,

该句柄将被

用于后续的通信操作

,

并贯穿整个通信过程。

(

2

)

串口设置

———串口打开后

,

其属性被设置为默认值

,

据具体需要

,

通过调用

GetCommState

(

hComm,

&dcb

)

读取当前串口设备控制块

DCB

(

DeviceCon

2

trolBlock

)

设置

,

修改后通过

SetCommState

(

hComm,&dcb

)

将其写入。再需注意异步读写的

超时控制设置

,

通过

COMMTIMEOUTS

结构设

置超时

,

调用

SetCommTimeouts

(

hComm,&time

2

outs

)

将结果写入。见下示例

:BOOLCSim

2

pleComm::Open

()

{

DCBdcb;

m

-

hIDComDev=CreateFile

(

COM2

,

GENERIC

-

READ|GENERIC

-

WRITE,0,

NULL,OPEN

-

EXISTING,FILE

-

ATTRIBUTE

-

NORMAL|FILE

-

FLAG

-

OVERLAPPED,

NULL

)

;//

打开串口

,

异步操作

if

(

m

-

hIDComDev==NULL

)

return

(

FALSE

)

;

gth=sizeof

(

DCB

)

;

输出缓冲区的大小

,Bytes,

if

(

!m

-

tOpen

())

;//

打开串口

m

-

tOpen

(

TRUE

)

;

m

-

utMode

(

1

)

;//

设置输入

方式为二进制方式

(

9600,n,8,1

)

;//m

-

tings

设置波特率等参数

m

-

reshold

(

1

)

;//

1

表示

72

计算技术与自动化

2004

6

GetCommState

(

m

-

hIDComDev,&dcb

)

;//

获得端口默认设置

te=CBR

-

4800;

……

}

(

3

)

串口读写操作

———主要运用

ReadFile

()

WriteFile

()

API

函数

,

若为异步通信方式

,

两函数中最后一个参数

为指向

OVERLAPPED

结构的非空指针

,

在读写函

数返回值为

FALSE

的情况下

,

调用

GetLastError

()

函数

,

返回值为

ERROR

-

IO

-

PENDING,

表明

I/O

操作悬挂

,

即操作转入后台继续执行。此时

,

可以用

WaitForSingleObject

()

来等待结束信号并

设置最长等待时间。举例如下

:

BOOLbReadStatus;

bReadStatus=ReadFile

(

m

-

hIDComDev,

buffer,dwBytesRead,&dwBytesRead,&m

-

OverlappedRead

)

;

if

(

!bReadStatus

)

{

if

(

GetLastError

()

==ERROR

-

IO

-

PEND

2

ING

)

{

WaitForSingleObject

(

m

-

OverlappedRead.

hEvent,1000

)

;

return

((

int

)

dwBytesRead

)

;}

return

(

0

)

;}

return

((

int

)

dwBytesRead

)

;}

———定义全局变量

m

-

Serial

作为新建通信类

CSimpleComm

的对象

,

通过调用类的成员函数即

可实现所需串行通信功能。与方法二相比

,

方法三

赋予串行通信程序设计较大的灵活性

,

端口的读写

可选择较简单的查询式

,

或通过设置与外设数据发

送时间间隔

TimeCycle

相同的定时器

:SetTimer

(

1,TimeCycle,NULL

)

,

进行定时读取或发送。

———若对端口数据的响应时间要求较严格

,

采用事件驱动

I/O

读写

,Windows

定义了

9

种口

通信事件

,

较常用的有

:EV

-

RXCHAR

EV

-

TX

2

EMPTYEV

-

RXFLAG

。在用

SetCommMask

()

定了有用的事件后

,

应用程序可调用

WaitCom

2

mEvent

()

来等待事件的发生。

SetCommMask

(

hComm,0

)

可使

WaitCommEvent

()

中止。

2.1.4

 多线程下实现串行通信

———

VC++

把线程分为两种

:

用户界面线程和

实现方式

优点

缺点

运用标准通信函数

编程原理简单

需要了解硬件电路

结构原理

CMSComm

控件

工作者线程。用户界面线程能够提供界面和用户交

,

通常用于处理用户输入并相应各种事件和消息

;

而工作者线程主要用来处理程序的后台任务。程序

通过调用

AfxBeginThread

()

函数就会自动创建一个

CWinThread

对象

,

从而开始一个进程。线程的终止

取决于下列事件之一

:

线程函数返回

;

线程调用

ExitThread

()

退出

;

异常情况下用线程的句柄调用

TerminateThread

()

退出

;

线程所属的进程被终止。进

行串口通信处理的不同线程之间需要协调运行。

VC++

提供了同步对象来协调多线程的并行

,

常用

的有以下几种

:Csemaphore

(

信号灯对象

)

Cmutex

(

互斥量对象

)

Cevent

(

事件对象

)

CcriticalSection

(

临界区对象

)

多线程下串口初始化与单线程相似。

在串口初始化成功后

,

就可以建立监控线程处理串

口通信事件。下面是该线程的关键代码。

UINTCommThread

(

LPVOIDpParam

)

//

于监控串口的工作者线程

{BOOLbResult=FALSE;

if

(

m

-

hComm

)

//

查看端口是否打开

PurgeComm

(

m

-

hComm,PURGE

-

RX

2

CLEAR|PURGE

-

TXCLEAR|PURGE

-

RX

2

ABORT|PURGE

-

TXABORT

)

;

for

(

;;

)

//

只要线程运行

,

就处于监视端口行

为的无限循环

{bResult=WaitCommEvent

(

m

-

hComm,

&Event,&m

-

ov

)

;

//m

-

ov

OVERLAPPED

类型的成员变量

if

(

!bResult

)

{//

进行出错处理

}

else{Event=WaitForMultipleObjects

(

4,m

-

hEvent,FALSE,INFINITE

)

;

//

无限等待设定的事件发生

switch

(

Event

)

{//

读写事件的响应处理过程

,

在此略

}

}

return0;

}

这样监控主程序就可以使用

AfxBeginThread

()

函数来产生

CommThread

串口监控线程。如果

要实现对所有端口的同时监控

,

可以分别对端口建

立监控线程。

2

1

2

 四种串口通信编程方法的比较

:

单线程

较灵活

只适用于较简单的

系统

多线程

灵活

,

准确

,CPU

利用率高

,

适用

于要求较高的实时监控系统

线程同步较难

编程容易实现

,

简洁

方便

,

不需了解细节

仅在对话框中使用

23

卷第

2

期杨 锋等

:Win32

环境下基于

VC++6.0

串口通信编程方法

73

1

 深海底采矿机器人遥测遥控系统结构图

3

 实例

深海底自动采矿系统如图

1

。在通信方面

,

面遥控站与水下监控站之间的通信采用光纤实现。

而针对深海底工控机与水下光端机之间

,

传输的数

据量

(

传感器数据

)

较多

,

不宜采用并口。我们采用

简单易用的

MSComm

通信控件来进行深海底工控

机与水下光端机之间的串口通信。

通信协议数据包的格式为

:

xxxx%ssss%

%ssss

3

hh

(

串头为$

,

串尾为3

;xxxx

为传输数

据变量的个数

,

共有

4

,

如果数据位不够

,

前面的

数据补零标识

;ssss

为传输数据变量

,

中间以

%

,

最后是

hh

校验

)

编程环境为

:VisualC++6.0,Windows2000

(

源程序略

)

本串口通信程序在

VC++6.0

下编译通过

,

经调试运行

,

效果良好。

4

 结论

VC++

是一个非常优秀的用户平台

,

采用

MSComm

控件进行串口通信编程非常简便实用

,

在深海底自动采矿系统中得到了充分应用。在具

体实践中要结合功能需要

,

综合考虑复杂程度、灵

活性等因素

,

选择合适的方法

,

实现串口通信。

参考文献

:

[1]

 王颖

.

VC6.0

实现串行通信的三种方法

[J].VC

知识库在

线帮助期刊第

9

.

[2]

 吴凤化

.WIN95

界面下的

VC++

串口通信程序

[J].

南京石

油物探研究所

.

[3]

 李现勇

.VisualC++

串口通信技术与工程实践

[M].

北京

:

民邮电出版社

.

[4]

 陆尔东

,

邓利平

.

多线程技术在

VC++

串口通信程序中的应

用研究

[J].

啸峰工作室串口通信

VC

编程

.

[5]

 陈峰

,

桂卫华

,

王随平

,

沈德耀

,

唐朝晖

,

深海底采矿机器人遥

测遥控系统

[J].

中南大学学报

,2003

34

期增刊

2.