深入浅出VC串口编程

深入浅出VC++串口编程之基本概念2006-02-17 09:43作者:宋宝华出处:天极开发责任编辑:方舟

引言

在PC机的主板上,有一种类型的接口可能为我们所忽视,那就是RS-232C串行接口,在微软的Windows系统中称其为COM。我们可以通过设备管理器来查看COM的硬件参数设置,如图1。

图1 在Windows上查看PC串口设置

迄今为止,几乎每一台PC都包含COM。本质而言,COM是PC为和外界通信所提供的一种串行数据传输的接口。作为一种物理通信的途径和设备,它和目前风靡的另一种串行接口――USB所提供的功能是一致的。不过RS-232C显然已经开始被后起之秀USB赶超,因为USB的传输速率已经远远超过了RS-232C。

尽管如此,RS-232C仍然具有非常广泛的应用,在相对长的一段时间里,难以被USB等接口取代。RS-232C接口(又称EIA RS-232C),1970年由美国电子工业协会(EIA)联合贝尔系统、调制解调器厂家及计算机终端生产厂家共同制定,全名是"数据终端设备(DTE)和数据通讯设备(DCE)之间串行二进制数据交换接口技术标准"。

本文将对这一接口进行硬件原理的介绍,随后我们将逐章学习DOS平台的串口编程,及Windows平台下基于API、控件和第三方类的串口编程,最后本文将给出一个综合实例。

在本文的连载过程中,您可以通过如下方式联系作者(热忱欢迎读者朋友对本文的内容提出质疑或给出修改意见):

作者email:21cnbao@https://www.360docs.net/doc/c63584442.html,(可以来信提问,笔者将力求予以回信解答,并摘取其中的典型问题,在本系列文章最后一次连载的《读者反馈》中予以阐述);

硬件原理

众所周知,CPU与存储芯片和I/O芯片的通信是并行的(并行传输的最大位数依赖于CPU的字长、数据总线的宽度),一种叫做UART(通用异步收发器,Universal Asynchronous Receiver/Transmitter)的芯片提供了并行数据传输和RS-232C串行数据传输方式的转换。这样的设备通常有如图2所示的管脚分布,当其向外传输数据时,CPU并行的将数据写入这类芯片的寄存器,UART再将寄存器中的数据一位一位地移动并向外传输;当外界向其传输数据时,UART一位一位地接收数据,并将其移位组合为并行数据,CPU再并行地读取这些数据。实际上,由于UART芯片一般以TTL/CMOS电平工作,在UART连接接口之前,还要经过一个TTL/CMOS和RS-232C电平的转换。RS-232C规定了其标准的电气特性,逻辑1对应的电压必须在-5~-15V之间;逻辑0对应的的电压必须在+5~+15V之间。

图2 UART并/串转换

一个常见的TTL/CMOS和RS-232C电平转换芯片如图3。

图3 常见的TTL/CMOS和RS-232C电平转换芯片

RS-232C通常以两类接插件与外界相连,分别称为DB9和DB25,如图4所示。

图4 DB9和DB25

而接插件中各个针的定义则如表1:

表1 DB9和DB25引脚定义

DB9 DB25

针号功能说明缩写针号功能说明缩写

1 数据载波检测DCD 8 数据载波检测DCD

2 接收数据RXD

3 接收数据RXD

3 发送数据TXD 2 发送数据TXD

4 数据终端准备DTR 20 数据终端准备DTR

5 信号地GND 7 信号地GND

6 数据设备准备好DSR 6 数据准备好DSR

7 请求发送RTS 4 请求发送RTS

8 清除发送CTS 5 清除发送CTS

9 振铃指示DELL 22 振铃指示DELL

RS-232C定义为数据通信设备(DCE)和数据终端设备(DTE)之间的互连,实现上,到现在为止,究竟一个设备属于DCE还是属于DTE已经没有明显的界限,PC即可作为DCE,又可作为DTE。两串口互连,连接方法主要有二:

一种方法是,数据的发送和接收由软件控制,不进行硬件握手,其连接方法如图5(最常用DB9连接示意)和表2(DB9、DB25三线连接表),真正需要互相连接的是RXD、TXD和GND;

图5 无硬件握手时两串口连接

表2 DB9、DB25三线连接

9针-9针5针-25针 2 9针-25针

2 3 3 2 2 2

3 2 2 3 3 3

5 5 7 7 5 7

软件握手又称为XON/XOFF,通常以CTRL-S(0x13)和CTRL-Q(0x11)两个字符来实现流控制。前者用于请求对方暂停发送,后者用于清除暂停传送的请求,继续发送数据。

另一种方法是,数据的发送和接收由硬件控制,进行硬件握手,其连接方法如图6(最常用DB9连接示意),需要连接的信号除RXD、TXD和GND外,还包括DTR、DSR、RTS和CTS。

硬件握手依赖于RTS和CTS信号,当发送设备欲发送数据时,将RTS信号置为有效表示请求发送,接收设备准备好后,置CTS信号有效,接着发送设备通过信号线TXD开始发送串行数据。

这里我们联想开来,RTS/CTS模式在许多领域里都出现过。回忆一下IEEE 802.11无线局域网协议标准,在其MAC协议中就使用了RTS/CTS,RTS/CTS抽象开来就是一种请求/应答。笔者曾经在拙作中多次以实例论证计算机领域里许多知识的相通性,这又是一个明证。

图6 有硬件握手时两串口连接

实际上,目前我们经常使用的是方法一,即只连接RXD、TXD和GND,简单灵活。另外,串口之间互连还有诸多途径,如图7所示。

图7 其它互连方式

调试工具

在MS-DOS下使用的编程环境是TC 2.0;

在Windows 2000下的编程环境是VC++ 6.0;

借助工具:串口调试助手2.1(图8)。

图8 串口调试助手

串口调试助手是由《Visual C++/Turbo C串口通信编程实践》一书作者龚建伟编写的共享软件,可以方便地进行串口上的数据收发、显示(16进制和ASCII码方式)和串口参数的设置,在串口调试领域应用广泛。

"串口调试助手"的开发原理很简单(相信读者看完本文后在相当短的时间之内就能开发出这样的软件),但是作者龚建伟敏锐地抓住了串口调试在业界的需求,使得自身随这一软件而成名。这一事件或多或少会给程序员们一定的启发。优秀的共享软件不一定要技术含量高,只要有需求,哪怕是开发原理再简单,都能拥有广泛的使用者。

为了在一台PC上同时搭建DOS和Windows平台,我们应该在Windows平台上安装虚拟PC的软件VmWare(图9,VMware Inc.版权所有,https://www.360docs.net/doc/c63584442.html,)。VMware的确是天才的作品!在同一PC上,利用VmWare几乎可以安装所有的操作系统,而且操作系统之间的切换不需要重新启动电脑,与传统的LILO等多系统引导方式有本质的不同。VM的意义是Virtual Machine,即虚拟出一个逻辑的电脑。

图9 VmWare虚拟PC

在虚拟PC的MS-DOS操作系统上,我们安装TC 2.0开发环境。

如果您的PC上没有软驱,为了制作MS-DOS启动软盘,请安装RamDiskNT模拟一个软盘,并在其上安装MS-DOS启动程序。RamDiskNT是一个磁盘模拟软件,其界面如图10所示。

图10 磁盘模拟

深入浅出VC++串口编程之DOS的串口编程

2006-02-20 09:52作者:宋宝华出处:天极开发责任编辑:方舟

在DOS平台下,操作串口主要有下列方式:通过BIOS调用、通过串口的硬件中断或通过对串口硬件进行轮询,本章将对以上三种方式进行具体的介绍并给出例子。

1.BIOS中断

在DOS操作系统下,IBM PC及其兼容机提供了一种灵活的串口I/O访问方法,即通过INT 14H调用ROM BIOS串行通讯例行程序。当设置AH为不同的值时,产生不同的功能:

AH 0 初始化端口

AH 1 向串口写字符

AH 2 从串口读字符

AH 3 取通讯口状态

初始化端口时(即当AH=0时),需要在AL寄存器中赋一字节初始化参数,其各项意义如图1;

图1 调用INT 14H时AL寄存器设置

当向串口写字符时(即当AH=1时),AL寄存器中的字符是需要写入的字符;

当向串口写字符时(即当AH=2时),AL寄存器中的字符是需要读取的字符。

看看下面的例程:

#include

#include

#include

#define STR "author:sbh"

union REGS inregs,outregs;

main()

{

//设置串口参数

init_rs232();

//写串口的例子

write_rs232(STR,strlen(STR));

//读串口的例子

read_rs232();

return(0);

}

init_rs232()

{

do{

inregs.h.ah=0; //AH=0表示初始化端口

inregs.h.al=0xe7;

inregs.x.dx=0; //COM1

int86(0x14, &inregs, &outregs);

}while(outregs.h.ah>=0x80);

return(0);

}

write_rs232(char *string, int len)

{

int i;

do{

inregs.h.ah=1;//发送AL寄存器的字符

inregs.h.al= *string;

inregs.x.dx=0;

int86(0x14, &inregs, &outregs);

}while(outregs.h.al>=0x80);

for(i=1;i

{

inregs.h.ah=1;

inregs.h.al=*(string+i);

inregs.x.dx=0;

int86(0x14, &inregs, &outregs);

}

}

read_rs232()

{

do{

inregs.h.ah=2; //读取AL寄存器中的字符

inregs.x.dx=0;

int86(0x14, &inregs, &outregs);

}while(outregs.h.al!=3||outregs.h.ah>=0x80);

return(0);

}

其中使用的int86函数的原型为:

int86()函数可以调用BIOS功能,现在的程序员们已经很少接触这个函数,80%的程序员甚至都未曾见过这个函数。其实,在茹毛饮血的DOS时代,int86()函数几乎是最常用和最核心的函数之一。几乎可以说,在那个时代,不会int86()就等于不会编程。而与int86配合使用的,就是REGS这样一个联合体,定义为:

其中的WORDREGS定义为:

struct WORDREGS {

unsigned int ax, bx, cx, dx, si, di,

cflag /*进位标志*/,

flags /*标志寄存器*/;

};

而BYTEREGS则定义为:

原来WORDREGS和BYTEREGS是16位的8086处理器内部的寄存器啊!因此,当CPU发展到286、386以后,再安装DOS也是建立在利用CPU实模式的基础上的!

另外一个函数与int86()的功能是类似的:

其中的SREGS为段寄存器结构体,定义为:

struct SREGS

{

unsigned int es;

unsigned int cs;

unsigned int ss;

unsigned int ds;

};

int86和int86x这两个函数的功能都是执行一个由参数intno指定的8086软中断。在执行软中断之前,两个函数都把inregs中的内容放置到各寄存器中(int86x还把segregs.x.es和segregs.x.ds的值存到相应的段寄存器中),软中断返回后,这两个函数都把当前寄存器的值存到outregs,并把系统进位标志拷贝到outregs.s.cflag中,把8086标志寄存器值存到outregs.x.flag中(int86x还恢复DS,并设置Segregs.es 和Segregs.ds的值为对应段寄存器的值)。

查阅BIOS中断调用手册,发现绝大多数调用都未用到ES和DS段寄存器,故在程序设计中经常只利用了int86函数。

2.硬件中断

为了给读者一个直观的印象,我们通过在Windows操作系统中查看COM的资源属性获得某COM对应的中断号,如图2(该对话框中设备管理器中开启)。

图2 COM中断号

实际上COM的确直接对应于一个中断,而系统也按照一定的规律为各类硬件分配了一个较固定的中断号,如表1。

表1 中断向量表

INT (Hex) IRQ Common Uses

08 0 System Timer

09 1 Keyboard

0A 2 Redirected

0B 3 Serial Comms. COM2/COM4

0C 4 Serial Comms. COM1/COM3

0D 5 Reserved/Sound Card

0E 6 Floppy Disk Controller

0F 7 Parallel Comms.

70 8 Real Time Clock

71 9 Reserved

72 10 Reserved

73 11 Reserved

74 12 PS/2 Mouse

75 13 Maths Co-Processor

76 14 Hard Disk Drive

77 15 Reserved

通过编写COM对应的中断服务程序,我们也可以操作串口,涉及到的相关函数有:

(1)设置中断向量表

例如,COM3对应的中断号是4,那么对应中断向量表中的地址是0x0C,设置0x0C对应中断程序的函数为:

其中的中断服务程序PORT1INT为:

void interrupt PORT1INT()

{

int c;

do

{

c = inportb(PORT1 + 5);

if (c &1)

{

buffer[bufferin] = inportb(PORT1);

bufferin++;

if (bufferin == 1024)

bufferin = 0;

}

}

while (c &1);

outportb(0x20, 0x20);

}

上述中断服务程序检查是否有字符可接收,其后将其通过inportb(PORT1)语句将其从UART中读出并放入输入buffer。持续的检查UART,以便能在一次中断里读取所有可获得的数据。

最后的"outportb(0x20,0x20);"语句告诉可编程中断控制器(Programmable Interrupt Controller,PIC)中断已经完成。

(2)读取中断向量表

/*dos.h*/

void interrupt (* _Cdecl getvect(int interruptno)) ();

例如:

其中的oldport1isr定义为:

我们融合setvect()函数、中断服务程序和getvect()函数,给出一个由Craig Peacock编写的完备例程:

/* Name : Sample Comm's Program - 1024 Byte Buffer - buff1024.c */

/* Written By : Craig Peacock */

#include

#include

#include

#define PORT1 0x3F8 /* Port Address Goes Here */

#define INTVECT 0x0C /* Com Port's IRQ here (Must also change PIC setting) */

/* Defines Serial Ports Base Address */

/* COM1 0x3F8 */

/* COM2 0x2F8 */

/* COM3 0x3E8 */

/* COM4 0x2E8 */

int bufferin = 0;

int bufferout = 0;

char ch;

char buffer[1025];

void interrupt(*oldport1isr)();

void interrupt PORT1INT() /* Interrupt Service Routine (ISR) for PORT1 */

{

int c;

do

{

c = inportb(PORT1 + 5);

if (c &1)

{

buffer[bufferin] = inportb(PORT1);

bufferin++;

if (bufferin == 1024)

{

bufferin = 0;

}

}

}

while (c &1);

outportb(0x20, 0x20);

}

void main(void)

{

int c;

outportb(PORT1 + 1, 0); /* Turn off interrupts - Port1 */

oldport1isr = getvect(INTVECT); /* Save old Interrupt Vector of later

recovery */

setvect(INTVECT, PORT1INT); /* Set Interrupt Vector Entry */

/* COM1 - 0x0C */

/* COM2 - 0x0B */

/* COM3 - 0x0C */

/* COM4 - 0x0B */

/* PORT 1 - Communication Settings */

outportb(PORT1 + 3, 0x80); /* SET DLAB ON */

outportb(PORT1 + 0, 0x0C); /* Set Baud rate - Divisor Latch Low Byte */

/* Default 0x03 = 38,400 BPS */

/* 0x01 = 115,200 BPS */

/* 0x02 = 57,600 BPS */

/* 0x06 = 19,200 BPS */

/* 0x0C = 9,600 BPS */

/* 0x18 = 4,800 BPS */

/* 0x30 = 2,400 BPS */

outportb(PORT1 + 1, 0x00); /* Set Baud rate - Divisor Latch High Byte */

outportb(PORT1 + 3, 0x03); /* 8 Bits, No Parity, 1 Stop Bit */

outportb(PORT1 + 2, 0xC7); /* FIFO Control Register */

outportb(PORT1 + 4, 0x0B); /* Turn on DTR, RTS, and OUT2 */

outportb(0x21, (inportb(0x21) &0xEF)); /* Set Programmable Interrupt Controller */ /* COM1 (IRQ4) - 0xEF */

/* COM2 (IRQ3) - 0xF7 */

/* COM3 (IRQ4) - 0xEF */

/* COM4 (IRQ3) - 0xF7 */

outportb(PORT1 + 1, 0x01); /* Interrupt when data received */

printf("\nSample Comm's Program. Press ESC to quit \n");

do

{

if (bufferin != bufferout)

{

ch = buffer[bufferout];

bufferout++;

if (bufferout == 1024)

{

bufferout = 0;

}

printf("%c", ch);

}

if (kbhit())

{

c = getch();

outportb(PORT1, c);

}

}

while (c != 27);

outportb(PORT1 + 1, 0);

/* Turn off interrupts - Port1 */

outportb(0x21, (inportb(0x21) | 0x10)); /* MASK IRQ using PIC */

/* COM1 (IRQ4) - 0x10 */

/* COM2 (IRQ3) - 0x08 */

/* COM3 (IRQ4) - 0x10 */

/* COM4 (IRQ3) - 0x08 */

setvect(INTVECT, oldport1isr); /* Restore old interrupt vector */

}

3.硬件查询

通过读取和写入串口UART对应的硬件端口,我们可以控制串口的收发。请看下面的例子:

/* Name : Sample Comm's Program - Polled Version - termpoll.c */

/* Written By : Craig Peacock */

#include

#include

#include

00000000000000000000#define PORT1 0x3F8

/* Defines Serial Ports Base Address */

/* COM1 0x3F8 */

/* COM2 0x2F8 */

/* COM3 0x3E8 */

/* COM4 0x2E8 */

void main(void)

{

int c;

int ch;

outportb(PORT1 + 1, 0); /* Turn off interrupts - Port1 */

/* PORT 1 - Communication Settings */

outportb(PORT1 + 3, 0x80); /* SET DLAB ON */

outportb(PORT1 + 0, 0x03); /* Set Baud rate - Divisor Latch Low Byte */ /* Default 0x03 = 38,400 BPS */

/* 0x01 = 115,200 BPS */

/* 0x02 = 57,600 BPS */

/* 0x06 = 19,200 BPS */

/* 0x0C = 9,600 BPS */

/* 0x18 = 4,800 BPS */

/* 0x30 = 2,400 BPS */

outportb(PORT1 + 1, 0x00); /* Set Baud rate - Divisor Latch High Byte */ outportb(PORT1 + 3, 0x03); /* 8 Bits, No Parity, 1 Stop Bit */

outportb(PORT1 + 2, 0xC7); /* FIFO Control Register */

outportb(PORT1 + 4, 0x0B); /* Turn on DTR, RTS, and OUT2 */

printf("\nSample Comm's Program. Press ESC to quit \n");

do

{

c = inportb(PORT1 + 5); /* Check to see if char has been */

/* received. */

if (c &1)

{

ch = inportb(PORT1); /* If so, then get Char */

printf("%c", ch);

} /* Print Char to Screen */

if (kbhit())

{

ch = getch(); /* If key pressed, get Char */

outportb(PORT1, ch);

} /* Send Char to Serial Port */

}

while (ch != 27); /* Quit when ESC (ASC 27) is pressed */

}

程序中的

检查PORT1 + 5端口地址,通过c&1可以判断是否有数据被UART接收到。关于UART对应的端口范围,从图2中也可以直观地看出。

深入浅出VC++串口编程之基于Win32 API

2006-02-20 15:49作者:宋宝华出处:天极开发责任编辑:方舟

1、API描述

在WIN32 API中,串口使用文件方式进行访问,其操作的API基本上与文件操作的API一致。

打开串口

Win32 中用于打开串口的API 函数为CreateFile,其原型为:

HANDLE CreateFile (

LPCTSTR lpFileName, //将要打开的串口逻辑名,如COM1 或COM2

DWORD dwAccess, //指定串口访问的类型,可以是读取、写入或两者并列

DWORD dwShareMode, //指定共享属性,由于串口不能共享,该参数必须置为0

LPSECURITY_ATTRIBUTES lpsa, //引用安全性属性结构,缺省值为NULL

DWORD dwCreate, //创建标志,对串口操作该参数必须置为OPEN EXISTING

DWORD dwAttrsAndFlags, //属性描述,用于指定该串口是否可进行异步操作,

//FILE_FLAG_OVERLAPPED:可使用异步的I/O

HANDLE hTemplateFile //指向模板文件的句柄,对串口而言该参数必须置为NULL

);

例如,以下程序用于以同步读写方式打开串口COM1:

HANDLE hCom;

DWORD dwError;

hCon = CreateFile("COM1", GENERIC_READ | GENERIC_WRITE, 0, NULL,

OPEN_EXISTING, 0, NULL);

if (hCom == (HANDLE)0xFFFFFFFF)

{

dwError = GetLastError();

MessageBox(dwError);

}

对于dwAttrsAndFlags参数及FILE_FLAG_OVERLAPPED标志的由来,可解释如下:Windows文件操作分为同步I/O和重叠I/O(Overlapped I/ O)两种方式,在同步I/O方式中,API会阻塞直到操作完成以后才能返回(在多线程方式中,虽然不会阻塞主线程,但是仍然会阻塞监听线程);而在重叠I/O方式中,API会立即返回,操作在后台进行,避免线程的阻塞。重叠I/O非常灵活,它也可以实现阻塞(例如我们可以设置一定要读取到一个数据才能进行到下一步操作)。如果进行I/O操作的API 在没有完成操作的情况下返回,我们可以通过调用GetOverLappedResult()函数阻塞到I/O操作完成后返回。

配置串口

配置串口是通过改变设备控制块DCB(Device Control Block) 的成员变量值来实现的,接收缓冲区和发送缓冲区的大小可通过SetupComm函数来设置。

DCB结构体定义为:

typedef struct _DCB { // dcb

DWORD DCBlength; // sizeof(DCB)

DWORD BaudRate; // current baud rate

DWORD fBinary: 1; // binary mode, no EOF check

DWORD fParity: 1; // enable parity checking

DWORD fOutxCtsFlow:1; // CTS output flow control

DWORD fOutxDsrFlow:1; // DSR output flow control

DWORD fDtrControl:2; // DTR flow control type

DWORD fDsrSensitivity:1; // DSR sensitivity

DWORD fTXContinueOnXoff:1; // XOFF continues Tx

DWORD fOutX: 1; // XON/XOFF out flow control

DWORD fInX: 1; // XON/XOFF in flow control

DWORD fErrorChar: 1; // enable error replacement

DWORD fNull: 1; // enable null stripping

DWORD fRtsControl:2; // RTS flow control

DWORD fAbortOnError:1; // abort reads/writes on error

DWORD fDummy2:17; // reserved

WORD wReserved; // not currently used

WORD XonLim; // transmit XON threshold

WORD XoffLim; // transmit XOFF threshold

BYTE ByteSize; // number of bits/byte, 4-8

BYTE Parity; // 0-4=no,odd,even,mark,space

BYTE StopBits; // 0,1,2 = 1, 1.5, 2

char XonChar; // Tx and Rx XON character

char XoffChar; // Tx and Rx XOFF character

char ErrorChar; // error replacement character

char EofChar; // end of input character

char EvtChar; // received event character

WORD wReserved1; // reserved; do not use

} DCB;

而SetupComm函数的原型则为:

BOOL SetupComm(

HANDLE hFile, // handle to communications device

DWORD dwInQueue, // size of input buffer

DWORD dwOutQueue // size of output buffer

);

以下程序将串口设置为:波特率为9600,数据位数为7位,停止位为2 位,偶校验,接收缓冲区和发送缓冲区大小均为1024个字节,最后用PurgeComm函数终止所有的后台读写操作并清空接收缓冲区和发送缓冲区:

DCB dcb;

dcb.BaudRate = 9600; //波特率为9600

dcb.ByteSize = 7; //数据位数为7位

dcb.Parity = EVENPARITY; //偶校验

dcb.StopBits = 2; //两个停止位

dcb.fBinary = TRUE;

dcb.fParity = TRUE;

if (!SetCommState(hCom, &dcb))

{

MessageBox("串口设置出错!");

}

SetupComm(hCom, 1024, 1024);

PurgeComm(hCom, PURCE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR |

PURGE_RXCLEAR);

超时设置

超时设置是通过改变COMMTIMEOUTS结构体的成员变量值来实现的,COMMTIMEOUTS的原型为:

{

DWORD ReadIntervalTimeout; //定义两个字符到达的最大时间间隔,单位:毫秒

//当读取完一个字符后,超过了ReadIntervalTimeout,仍未读取到下一个字符,就会

//发生超时

DWORD ReadTotalTimeoutMultiplier;

DWORD ReadTotalTimeoutConstant;

//其中各时间所满足的关系如下:

//ReadTotalTimeout = ReadTotalTimeOutMultiplier* BytesToRead +

ReadTotalTimeoutConstant

DWORD WriteTotalTimeoutMultiplier;

DWORD WriteTotalTimeoutConstant;

} COMMTIMEOUTS, *LPCOMMTIMEOUTS;

设置超时的函数为SetCommTimeouts,其原型中接收COMMTIMEOUTS的指针为参数:

BOOL SetCommTimeouts(

HANDLE hFile, // handle to communications device

LPCOMMTIMEOUTS lpCommTimeouts // pointer to comm time-out structure

);

以下程序将串口读操作的超时设定为10 毫秒:

COMMTIMEOUTS to;

memset(&to, 0, sizeof(to));

to.ReadIntervalTimeout = 10;

SetCommTimeouts(hCom, &to);

与SetCommTimeouts对应的GetCommTimeouts()函数的原型为:

BOOL GetCommTimeouts(

HANDLE hFile, // handle of communications device

LPCOMMTIMEOUTS lpCommTimeouts // pointer to comm time-out structure

);

事件设置

在读写串口之前,需要用SetCommMask ()函数设置事件掩模来监视指定通信端口上的事件,其原型为:

BOOL SetCommMask(

HANDLE hFile, //标识通信端口的句柄

DWORD dwEvtMask //能够使能的通信事件

);

相关主题
相关文档
最新文档