这是微软官方的一个例子,这个例子中,如果不做修改,那么他是可以异步运行的,会出现一个错误:官方也说了一下,但是不太好懂,我拷贝过来放在这里,作为参考。
如果无法立即完成重叠的操作,则函数返回 FALSE , GetLastError 函数返回 ERROR_IO_PENDING,指示操作正在后台执行。 发生这种情况时,系统会在 WaitCommEvent 返回之前将 OVERLAPPED 结构的 hEvent 成员设置为非信号状态,然后在发生指定事件或错误之一时将其设置为信号状态。 调用过程可以使用其中一个 等待函数 来确定事件对象的状态,然后使用 GetOverlappedResult 函数来确定 WaitCommEvent 操作的结果。 GetOverlappedResult 报告操作的成功或失败,并将 lpEvtMask 参数指向的变量设置为指示发生的事件。
总之异步在后台运行的那种,目前是出错,我把它修改为不是异步的方式,修改一下CreateFile()函数就可以了。修改后,这个程序就是同步的模式了,就是会一直处于等待状态,虽然不实用,但是好歹是能用了。下面说说是怎么修改的,具体的一看源代码就懂了。
首先,需要修改一下事件的类型:
// fSuccess = SetCommMask(hCom, EV_CTS | EV_DSR); //MS code
fSuccess = SetCommMask(hCom, EV_RXCHAR);//改为 EV_RXCHAR事件
改为比较好懂的:EV_RXCHAR,表示接收到了一个字符并将其放入了输入缓冲区。
其次,就是修改了CreatFile()函数:
hCom = CreateFile(TEXT("\\\\.\\COM1"),
GENERIC_READ | GENERIC_WRITE,
0, // exclusive access
NULL, // default security attributes
OPEN_EXISTING,
0,//FILE_FLAG_OVERLAPPED,此处修改过,改为了0,具体看文档吧,这个太多内容了。0就是同步的方式了。
NULL
);
再次,添加了一些cout 输出字符串的语句。
事件代码的具体含义如下:
值 含义 EV_BREAK 在输入上检测到一个中断。 EV_CTS CTS (明送) 信号更改状态。 EV_DSR DSR (数据集就绪) 信号更改状态。 EV_ERR 发生行状态错误。 行状态错误 CE_FRAME、 CE_OVERRUN和 CE_RXPARITY。 EV_RING 检测到振铃指示。 EV_RLSD RLSD (接收线信号检测) 信号更改状态。 EV_RXCHAR 接收到了一个字符并将其放入了输入缓冲区。 EV_RXFLAG 已接收事件字符并将其放置在输入缓冲区中。 事件字符在设备的 DCB 结构中指定,该结构使用 SetCommState 函数应用于串行端口。 EV_TXEMPTY 输出缓冲区中的最后一个字符已发送。
完整的源代码如下:
// WatchCommunicationEventTest.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
#include <windows.h>
#include <tchar.h>
#include <assert.h>
#include <stdio.h>
int main()
{
// std::cout << "Hello World!\n";
HANDLE hCom;
OVERLAPPED o;
BOOL fSuccess;
DWORD dwEvtMask;
hCom = CreateFile(TEXT("\\\\.\\COM1"),
GENERIC_READ | GENERIC_WRITE,
0, // exclusive access
NULL, // default security attributes
OPEN_EXISTING,
0,//FILE_FLAG_OVERLAPPED,此处修改过,改为了0,具体看文档吧,这个太多内容了。0就是同步的方式了。
NULL
);
if (hCom == INVALID_HANDLE_VALUE)
{
// Handle the error.
printf("CreateFile failed with error %d.\n", GetLastError());
return 2;
}
// Set the event mask.
//此处修改过
// fSuccess = SetCommMask(hCom, EV_CTS | EV_DSR); //MS code
fSuccess = SetCommMask(hCom, EV_RXCHAR);//改为 EV_RXCHAR事件
if (!fSuccess)
{
// Handle the error.
printf("SetCommMask failed with error %d.\n", GetLastError());
return 1;
}
// Create an event object for use by WaitCommEvent.
o.hEvent = CreateEvent(
NULL, // default security attributes
TRUE, // manual-reset event
FALSE, // not signaled
NULL // no name
);
// Initialize the rest of the OVERLAPPED structure to zero.
o.Internal = 0;
o.InternalHigh = 0;
o.Offset = 0;
o.OffsetHigh = 0;
assert(o.hEvent);
//下面的cout 也是博主自己加的,看到输出字符就是成功了
if (WaitCommEvent(hCom, &dwEvtMask, &o))
{
if (dwEvtMask & EV_DSR)
{
std::cout << "EV_DSR event is happening";
}
if (dwEvtMask & EV_CTS)
{
std::cout << "EV_CTS event is happening";
}
if(dwEvtMask & EV_RXCHAR)
{
std::cout << "EV_RXCHAR event is happening";
}
}
else
{
DWORD dwRet = GetLastError();
if (ERROR_IO_PENDING == dwRet)
{
printf("I/O is pending...\n");
// To do.
}
else
printf("Wait failed with error %d.\n", GetLastError());
}
return 0;
}
运行程序:首先是出现一个命令行窗口,啥也没有
用VSPD 和 XCOM V2.6 创建虚拟的COM串口后,可以用XCOM 创建一个 从COM2 发送文本到COM1的操作,之后就有输出了,这个EV_RXCHAR事件发生了。
后续还可以多研究研究,作为一个最权威,最基本的例子,这个作为入门我觉得很不错,推荐给大家。