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

Win32 串口编程(一)(2009-08-16 16:28:13)

分类:Windows

翻译自:

ms-help:///.v80//dnfiles/html/msdn_s

老外写的文章,虽比较全面,但很啰嗦,不如看各个函数的文档来得快。为方便以后查阅,

列出本文涉及的主要函数如下:

CreateFile、ReadFile、WriteFile、GetOverlappedResult、WaitForSingleObject

SetCommMask、WaitCommEvent

ClearCommError、GetCommModemStatus、EscapeCommFunction

GetCommState、BuildCommDCB、SetCommState、SetCommTimeouts

此外,新浪的博客系统限制文章最大长度为40000字节,只好把这篇文章分成几部分了。

0 简介

本文仅关注在Windows NT和95间兼容的API。Windows 95支持Telephony API(TAPI),但

Windows NT 3.x不支持TAPI,所以本文不讨论它。

本文的示例程序MTTTY(Multithreaded TTY)使用了三个线程:一个进行内存管理的界面线

程;控制所有写入操作的写入者线程;读取数据和处理端口状态改变的读取/状态线程。示

例采用了一些不同的堆来进行内存管理;还大量使用了同步方法来进行线程间通信。

1 打开端口

使用CreateFile函数打开端口。打开端口时有两种方法:重叠的和非重叠的。下列代码片段

以重叠方式打开端口:

HANDLE hComm;

hComm = CreateFile( gszPort,

GENERIC_READ | GENERIC_WRITE,

0,

0,

OPEN_EXISTING,

FILE_FLAG_OVERLAPPED,

0);

if (hComm == INVALID_HANDLE_VALUE)

// error opening port; abort

Win32 串口编程(二)(2009-08-16 16:39:32)

分类:Windows

标签:串口 重叠i/o it

3 串口状态

有两种获取通信端口状态的方法。第一种方法是设置事件掩码,当指定事件发生时应用程序

会收到通知。SetCommMask函数用于设置事件掩码,WaitCommEvent用于等待指定的事件

发生。它们与16位Windows中的SetCommEventMask和EnableCommNotification类似,只

是它们不发送WM_COMMNOTIFY消息。第二种方法是不时地调用另一些状态函数来获取

通信端口的状态。当然,轮询是低效的,不建议使用。

3.1 通信事件

通信事件在使用通信端口时可能随时发生。接收通信事件需要两个步骤:

用SetCommMask设定需要接收通知的事件

标签:串口 重叠i/o

用WaitCommEvent提交状态检查请求,请求可以是重叠的或者非重叠的,与读写操作一样。

下面是使用SetCommMask的示例:

DWORD dwStoredFlags;

dwStoredFlags = EV_BREAK | EV_CTS | EV_DSR | EV_ERR | EV_RING |

EV_RLSD | EV_RXCHAR | EV_RXFLAG | EV_TXEMPTY ;

if (!SetCommMask(hComm, dwStoredFlags))

// error setting communications mask

下表描述了每种事件类型。

事件标志

EV_BREAK

EV_CTS

EV_DSR

EV_ERR

EV_RING

EV_RLSD

描述

检测到输入中的break

CTS(Clear To Send)信号状态改变。要取得CTS线路状态,应使用

GetCommModemStatus函数。

DSR(Data Set Ready)信号状态改变。要取得DSR线路状态,应使用

GetCommModemStatus函数。

某线路状态错误发生。线路状态错误包括CE_FRAME、CE_OVERRUN

和CE_RXPARITY。要取得具体错误种类,需调用ClearCommError函数。

检测到振铃指示

RLSD(Receive Line Signal Detect)信号状态改变。要取得RLSD线路状态,

需调用GetCommModemStatus函数。注意,RLSD通常被称作CD(carrier

detect)。

接收到一个字符并且已放入输入缓冲区。请参考下面的“警告”节对此

标志的详细讨论。

接收到一个事件字符并且已放入输入缓冲区。事件字符由下文讨论的

DCB结构EvtChar字段指定。下面的“警告”节也讨论了这个标志。

输出缓冲区中最后一个字符被发送到串口设备了。如果使用硬件缓冲区,

此标志仅表示所有数据已经发送到硬件了。如果不与设备驱动交互,是

无法确定硬件缓冲区空的。

EV_RXCHAR

EV_RXFLAG

EV_TXEMPTY

指定事件掩码后,使用WaitCommEvent函数检测事件发生。如果以非重叠方式打开端口,

则WaitCommEvent不需要OVERLAPPED结构体,函数阻塞调用线程直到某事件发生。如

果没有事件发生,调用线程将无限阻塞。

下面的代码片段展示了如何在以非重叠方式打开的端口上等待EV_RING事件。

DWORD dwCommEvent;

if (!SetCommMask(hComm, EV_RING))

// Error setting communications mask

return FALSE;

if (!WaitCommEvent(hComm, &dwCommEvent, NULL))

// An error occurred waiting for the event.

return FALSE;