win32 api 串口通信

来源:互联网 发布:天津福禄克数据测试 编辑:程序博客网 时间:2024/05/18 11:49

一些普遍的东西,在这里就不再重述。

 

1. 通信原理的理解--重叠IO的本质

 

      在用ReadFile和WriteFile读写串行口时,既可以同步执行,也可以重叠(异步)执行。在同步执行时,函数直到操作完成后才返回。这意味着在同步执行时线程会被阻塞,从而导致效率下降。在重叠执行时,即使操作还未完成,调用的函数也会立即返回。费时的I/O操作在后台进行,这样线程就可以干别的事情。例如,线程可以在不同的句柄上同时执行I/O操作,甚至可以在同一句柄上同时进行读写操作。“重叠”一词的含义就在于此。

      ReadFile函数只要在串行口输入缓冲区中读入指定数量的字符,就算完成操作。而WriteFile函数不但要把指定数量的字符拷入到输出缓冲中,而且要等这些字符从串行口送出去后才算完成操作。

  ReadFile和WriteFile函数是否为执行重叠操作是由CreateFile函数决定的。如果在调用CreateFile创建句柄时指定了FILE_FLAG_OVERLAPPED标志,那么调用ReadFile和WriteFile对该句柄进行的读写操作就是重叠的,如果未指定重叠标志,则读写操作是同步的。

      在同步的情况下,READFILE/WIRTEFILE函数的返回值(TRUE OR FALSE)表示了消息的接收或发送的成功或失败。但在异步的情况下,TRUE表示成功,但FALSE不能够表示失败。此时,应该调用GetLastError函数分析返回的结果。例如,在重叠操作时如果操作还未完成函数就返回,那么函数就返回FALSE,而且GetLastError函数返回ERROR_IO_PENDING,这表示操作由后台继续进行,并未失败。

在使用重叠I/O时,线程需要创建OVERLAPPED结构以供读写函数使用。OVERLAPPED结构最重要的成员是hEvent,hEvent是一个事件对象句柄,线程应该用CreateEvent函数为hEvent成员创建一个手工重置事件,hEvent成员将作为线程的同步对象使用。如果读写函数未完成操作就返回,就那么把hEvent成员设置成无信号的。操作完成后(包括超时),hEvent会变成有信号的。

  如果GetLastError函数返回ERROR_IO_PENDING,则说明重叠操作还为完成,线程可以等待操作完成。有两种等待办法:一种办法是用象WaitForSingleObject这样的等待函数来等待OVERLAPPED结构的hEvent成员,可以规定等待的时间,在等待函数返回后,调用GetOverlappedResult。另一种办法是调用GetOverlappedResult函数等待,如果指定该函数的bWait参数为TRUE,那么该函数将等待OVERLAPPED结构的hEvent 事件。GetOverlappedResult可以返回一个OVERLAPPED结构来报告包括实际传输字节在内的重叠操作结果。

  如果规定了读/写操作的超时,那么当超过规定时间后,hEvent成员会变成有信号的。因此,在超时发生后,WaitForSingleObject和GetOverlappedResult都会结束等待。WaitForSingleObject的dwMilliseconds参数会规定一个等待超时,该函数实际等待的时间是两个超时的最小值。注意GetOverlappedResult不能设置等待的时限,因此如果hEvent成员无信号,则该函数将一直等待下去。

  在调用ReadFile和WriteFile之前,线程应该调用ClearCommError函数清除错误标志。该函数负责报告指定的错误和设备的当前状态。

  调用PurgeComm函数可以终止正在进行的读写操作,该函数还会清除输入或输出缓冲区中的内容。

 

小结:

       从上述可见,重叠IO的本质是操作系统为应用程序提供了一个后台线程,负责IO操作。此时,传统的WRITEFILE、READFILE函数把相关的参数传给后台线程,并等待后台线程的返回值, 当等待一定时间后, 后台线程还没有返回值, WRITEFILE/READFILE则自行返回。但,通信的成功与失败应用程序总是要知道的,因此,读写线程通过事件来与后台通信,从而知道通信的结果。

 

2. 常见错误及解决方法

 

2.1 在打开串口,并且对串口的普通参数(波特率、校验)等进行设置后, WRITEFLIE返回总是0, 后来发现是OVERLAPPED结构没有设置的问题。OVERLAPPED结构的定义及其成员的意义如下。

 

 

小技巧:

1. Debug模式 在下边监视name填入 @err,hr 可以看到GETLASTERROR()错误信息

 

2.VC6.0 报错,没发现mfc42ud.dll or mfc42u.dll 的原因:

The default installation options of Visual C++ v6.0 don't install the Unicode libraries of MFC, so you might get an error that mfc42ud.dll or mfc42u.dll cannot be found.

 

原创粉丝点击