这是微软官方的一个例子,这个例子中,如果不做修改,那么他是可以异步运行的,会出现一个错误:官方也说了一下,但是不太好懂,我拷贝过来放在这里,作为参考。
如果无法立即完成重叠的操作,则函数返回 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事件发生了。
后续还可以多研究研究,作为一个最权威,最基本的例子,这个作为入门我觉得很不错,推荐给大家。