串行通信与重叠IO

上传人:壹****1 文档编号:508632526 上传时间:2024-02-22 格式:DOC 页数:14 大小:92KB
返回 下载 相关 举报
串行通信与重叠IO_第1页
第1页 / 共14页
串行通信与重叠IO_第2页
第2页 / 共14页
串行通信与重叠IO_第3页
第3页 / 共14页
串行通信与重叠IO_第4页
第4页 / 共14页
串行通信与重叠IO_第5页
第5页 / 共14页
点击查看更多>>
资源描述

《串行通信与重叠IO》由会员分享,可在线阅读,更多相关《串行通信与重叠IO(14页珍藏版)》请在金锄头文库上搜索。

1、串行通信与重叠I/OWin32系统把文件的概念进行了扩展。无论是文件、通信设备、命名管道、邮件槽、磁盘、还是控制台,都是用API函数CreateFile来打开或创建的。该函数的声明为:HANDLECreateFile(LPCTSTRlpFileName,/文件名DWORDdwDesiredAccess,/访问模式DWORDdwShareMode,/共享模式LPSECURITY_ATTRIBUTESlpSecurityAttributes,/通常为NULLDWORDdwCreationDistribution,/创建方式DWORDdwFlagsAndAttributes,/文件属性和标志HAND

2、LEhTemplateFile临时文件的句柄,通常为NULL);如果调用成功,那么该函数返回文件的句柄,如果调用失败,则函数返回INVALID_HANDLE_VALUE。在打开通信设备句柄后,常常需要对串行口进行一些初始化工作。这需要通过一个DCB结构来进行。DCB结构包含了诸如波特率、每个字符的数据位数、奇偶校验和停止位数等信息。在查询或配置置串行口的属性时,都要用DCB结构来作为缓冲区。调用GetCommState函数可以获得串口的配置,该函数把当前配置填充到一个DCB结构中。一般在用CreateFile打开串行口后,可以调用GetCommState函数来获取串行口的初始配置。要修改串行口

3、的配置,应该先修改DCB结构,然后再调用SetCommState函数用指定的DCB结构来设置串行口。除了在DCB中的设置外,程序一般还需要设置I/O缓冲区的大小和超时。Windows用I/O缓冲区来暂存串行口输入和输出的数据,如果通信的速率较高,则应该设置较大的缓冲区。调用SetupComm函数可以设置串行口的输入和输出缓冲区的大小。在用ReadFile和WriteFile读写串行口时,需要考虑超时问题。如果在指定的时间内没有读出或写入指定数量的字符,那么ReadFile或WriteFile的操作就会结束。要查询当前的超时设置应调用GetCommTimeouts函数,该函数会填充一个COMMT

4、IMEOUTS结构。调用SetCommTimeouts可以用某一个COMMTIMEOUTS结构的内容来设置超时。有两种超时:间隔超时和总超时。间隔超时是指在接收时两个字符之间的最大时延,总超时是指读写操作总共花费的最大时间。写操作只支持总超时,而读操作两种超时均支持。用COMMTIMEOUTS结构可以规定读/写操作的超时,该结构的定义为:typedefstruct_COMMTIMEOUTSDWORDReadIntervalTimeout;/读间隔超时DWORDReadTotalTimeoutMultiplier;/读时间系数DWORDReadTotalTimeoutConstant;/读时间常

5、量DWORDWriteTotalTimeoutMultiplier;/写时间系数DWORDWriteTotalTimeoutConstant;/写时间常量COMMTIMEOUTS,*LPCOMMTIMEOUTS;COMMTIMEOUTS结构的成员都以毫秒为单位。总超时的计算公式是:总超时=时间系数x要求读/写的字符数+时间常量例如,如果要读入10个字符,那么读操作的总超时的计算公式为:读总超时=ReadTotalTimeoutMultiplierx10+ReadTotalTimeoutConstant可以看出,间隔超时和总超时的设置是不相关的,这可以方便通信程序灵活地设置各种超时。如果所有写超

6、时参数均为0,那么就不使用写超时。如果ReadIntervalTimeout为0,那么就不使用读间隔超时,如果ReadTotalTimeoutMultiplier和ReadTotalTimeoutConstant都为0,则不使用读总超时。如果读间隔超时被设置成MAXDWORD并且两个读总超时为0,那么在读一次输入缓冲区中的内容后读操作就立即完成,而不管是否读入了要求的字符。在用重叠方式读写串行口时,虽然ReadFile和WriteFile在完成操作以前就可能返回,但超时仍然是起作用的。在这种情况下,超时规定的是操作的完成时间,而不是ReadFile和WriteFile的返回时间。在用ReadF

7、ile和WriteFile读写串行口时,既可以同步执行,也可以重叠(异步)执行。在同步执行时,函数直到操作完成后才返回。这意味着在同步执行时线程会被阻塞,从而导致效率下降。在重叠执行时,即使操作还未完成,调用的函数也会立即返回。费时的I/O操作在后台进行,这样线程就可以干别的事情。例如,线程可以在不同的句柄上同时执行I/O操作,甚至可以在同一句柄上同时进行读写操作。“重叠”一词的含义就在于此。ReadFile函数只要在串行口输入缓冲区中读入指定数量的字符,就算完成操作。而WriteFile函数不但要把指定数量的字符拷入到输出缓冲中,而且要等这些字符从串行口送出去后才算完成操作。ReadFile

8、和WriteFile函数是否为执行重叠操作是由CreateFile函数决定的。如果在调用CreateFile创建句柄时指定了FILE_FLAG_OVERLAPPED标志,那么调用ReadFile和WriteFile对该句柄进行的读写操作就是重叠的,如果未指定重叠标志,则读写操作是同步的。函数ReadFile和WriteFile的参数和返回值很相似。这里仅列出ReadFile函数的声明:BOOLReadFile(HANDLEhFile,/文件句柄LPVOIDlpBuffer,/读缓冲区DWORDnNumberOfBytesToRead,/要求读入的字节数LPDWORDlpNumberOfByte

9、sRead,/实际读入的字节数LPOVERLAPPEDlpOverlapped/指向一个OVERLAPPED结构);若返回TRUE则表明操作成功需要注意的是如果该函数因为超时而返回,那么返回值是TRUE。参数lpOverlapped在重叠操作时应该指向一个OVERLAPPED结构,如果该参数为NULL,那么函数将进行同步操作,而不管句柄是否是由FILE_FLAG_OVERLAPPED标志建立的。当ReadFile和WriteFile返回FALSE时,不一定就是操作失败,线程应该调用GetLastError函数分析返回的结果。例如,在重叠操作时如果操作还未完成函数就返回,那么函数就返回FALSE

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

11、:一种办法是用象WaitForSingleObject这样的等待函数来等待OVERLAPPED结构的hEvent成员,可以规定等待的时间,在等待函数返回后,调用GetOverlappedResult。另一种办法是调用GetOverlappedResult函数等待,如果指定该函数的bWait参数为TRUE,那么该函数将等待OVERLAPPED结构的hEvent事件。GetOverlappedResult可以返回一个OVERLAPPED结构来报告包括实际传输字节在内的重叠操作结果。如果规定了读/写操作的超时,那么当超过规定时间后,hEvent成员会变成有信号的。因此,在超时发生后,WaitForS

12、ingleObject和GetOverlappedResult都会结束等待。WaitForSingleObject的dwMilliseconds参数会规定一个等待超时,该函数实际等待的时间是两个超时的最小值。注意GetOverlappedResult不能设置等待的时限,因此如果hEvent成员无信号,则该函数将一直等待下去。在调用ReadFile和WriteFile之前,线程应该调用ClearCommError函数清除错误标志。该函数负责报告指定的错误和设备的当前状态。调用PurgeComm函数可以终止正在进行的读写操作,该函数还会清除输入或输出缓冲区中的内容。/.2调用Win32API函数实

13、现串行通信编程Windows操作系统对系统底层操作采取了屏蔽的策略,禁止应用程序直接访问计算机I/O端口,而由设备驱动程序统一管理,Windows封装了Windows的通信机制,这种方式称为通信应用程序接口API(ApplicationProgrammingInterfaces)。Windows9x/NT/2000提供的API一般都支持32位的操作,又称为Win32API,程序员可以利用Win32API的通信函数进行编程,不用对硬件直接进行操作,使得应用程序的编制更加方便。2.2.1Win32API常用通信函数在进行串口通信时,经常需要用到下列一些API函数:CreateFile():用于打开

14、一个文件访问串口;GetCommState():获取串口的当前配置,放入设备控制块DCB中;SetCommState():根据DCB重新配置串口参数;SetCommTimeouts():设置串口读写操作的溢出时间;ReadFile():从串口的输入缓冲区读取数据;WriteFile():向串口的输出缓冲区写入数据;SetCommMask():监视指定通信资源上的事件;WaitCommEvent():等待通信事件发生;CloseHandle():关闭由CreateFile函数打开的串口。以上这些函数的原形可在参考文献1中找到。1-在C+Builder6.0下基于api函数编写串口通信程序简介:在

15、dos/win95/win98的年代,操作系统对串口是不保护的,也就是说将串口的的资源完全开放给用户,用户可以用直接操作硬件的函数(比如说TC2.0下的inport()和outport()函数)跟串口直接打交道,这时候用户使用直接操作串口的函数怎样折磨串口都是没有问题的,操作系统根本就不管不问,对串口操作所造成的一切后果都是用户一个人承担的,这时候用户对串口具有高度自由的支配权;但是,这种情况好景不长,从win2000操作系统开始,微软为了照顾好计算机上的硬件,开始实施了对硬件的保护策略,也就是说任何用户在他的操作系统下企图操纵串口时必须经过他的同意方可进行,其实也就是变相的将用户往必须使用他

16、的通信api函数才能操作串口这条”羊肠小路”上赶(当然也有别的方法操作串口,但那些并非我等普通用户能研究明白的),形象一点说就好像你想怎样操作串口的意图必须经过win2000的翻译(其实是win2000的设备驱动程序)才能转达给串口一样,基于这一点我们说(其实是很多资料上说的)win2000下通过api函数操作串口是具有设备无关性的,什么意思呢?就是说你想怎样操作串口就用相应的api函数告诉操作系统你想对串口干什么,然后操作系统就把你的意思转告给串口让其做出相应的动作,相对于dos/win95/win98下来说,据我理解也就相当于你原来写的直接操作串口的函数在win2000下他替你完成了,但是你必须用win2000通信api函数清楚地向操作

展开阅读全文
相关资源
相关搜索

当前位置:首页 > 办公文档 > 解决方案

电脑版 |金锄头文库版权所有
经营许可证:蜀ICP备13022795号 | 川公网安备 51140202000112号