13.5.2 配置串口(2)
(2)串口通信超时设置。在用ReadFile和WriteFile读写串行口时,需要考虑超时问题。超时的作用是在指定的时间内没有读入或发送指定数量的字符,ReadFile或WriteFile的操作仍然会结束。
要查询当前的超时设置,应调用GetCommTimeouts()函数,该函数会填充一个COMMTIMEOUTS结构。调用SetCommTimeouts()函数可以用某一个COMMTIMEOUTS结构的内容来设置超时。
读写串口的超时有两种:间隔超时和总超时。间隔超时是指在接收时两个字符之间的最大时延。总超时是指读写操作总共花费的最大时间。写操作只支持总超时,而读操作两种超时均支持。用COMMTIMEOUTS结构可以规定读写操作的超时。COMMTIMEOUTS结构的定义为:
- Typedef struct _COMMTIMEOUTS
- {
- DWORD ReadIntervalTimeout; //读间隔超时
- DWORD ReadTotalTimeoutMultiplier; //读时间系数
- DWORD ReadTotalTimeoutConstant; //读时间常量
- DWORD WriteTotalTimeoutMultiplier; //写时间系数
- DWORD WriteTotalTimeoutConstant; //写时间常量
- } COMMTIMEOUTS,*LPCOMMTIMEOUTS;
COMMTIMEOUTS结构的成员都以毫秒为单位。总超时的计算公式是:- 总超时=时间系数×要求读/写的字符数+时间常量
例如,要读入50个字符,那么读操作的总超时的计算公式为:- ReadTotalTimeOut =ReadTotalTimeoutMultiplier×50+ReadTotalTimeoutConstant
可以看出:间隔超时和总超时的设置是不相关的,这可以方便通信程序灵活地设置各种超时。
如果所有写超时参数均为0,那么就不使用写超时。如果ReadIntervalTimeout为0,那么就不使用读间隔超时。如果ReadTotalTimeoutMultiplier和ReadTotalTimeoutConstant都为0,则不使用读总超时。如果读间隔超时被设置成MAXDWORD,并且读时间系数和读时间常量都为0,那么在读一次输入缓冲区的内容后读操作就立即返回,而不管是否读入了要求的字符。
注意:在用重叠方式读写串口时,虽然ReadFile和WriteFile在完成操作以前就可能返回,但超时仍然是起作用的。在这种情况下,超时规定的是操作的完成时间,而不是ReadFile和WriteFile的返回时间
(3)申请串口通信缓冲区。除了在DCB中的设置外,程序一般还需要设置I/O缓冲区的大小和超时。Windows用I/O缓冲区来暂存串口输入和输出的数据。如果通信的速率较高,则应该设置较大的缓冲区。调用SetupComm()函数可以设置串行口的输入和输出缓冲区的大小,函数原型如下:
- BOOL SetupComm(
- HANDLE hFile, //通信设备的句柄
- DWORD dwInQueue, //输入缓冲区的大小(字节数)
- DWORD dwOutQueue //输出缓冲区的大小(字节数)
- );
(4)清空串口通信缓冲区。在读写串口之前,还要用PurgeComm()函数清空缓冲区,该函数原型如下: - BOOL PurgeComm(
- HANDLE hFile, //串口句柄
- DWORD dwFlags
- );
参数dwFlags指定要完成的操作,可以是表13.5中值的组合。
表13.5 清空缓冲区的值
|
值< xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" /> |
说 明 |
|
P URGE_RXABORT |
中断所有读操作并立即返回,即使读操作还没有完成 |
|
PURGE_TXABORT |
中断所有写操作并立即返回,即使写操作还没有完成 |
|
PURGE_TXCLEAR |
清除输出缓冲区 |
|
PURGE_RXCL EAR |
清除输入缓冲区 |
配置串口属性的示例代码如下:
- 01 SetCom(HANDLE hCom)
- 02 {
- 03 SetupComm( hCom, 1024, 1024); //输入、输出缓冲区的大小都是1024
- 04 COMMTIMEOUTS TimeOuts;
- 05 //设定读超时
- 06 TimeOuts.ReadIntervalTimeout = 1000;
- 07 TimeOuts.ReadTotalTimeoutMultiplier = 500;
- 08 TimeOuts.ReadTotalTimeoutConstant = 5000;
- 09 //设定写超时
- 10 TimeOuts.WriteTotalTimeoutMultiplier = 500;
- 11 TimeOuts.WriteTotalTimeoutConstant = 2000;
- 12 SetCommTimeouts( hCom, &TimeOuts); //设置超时
- 13 DCB dcb;
- 14 GetCommState( hCom, &dcb );
- 15 dcb.BaudRate = CBR_115200; //波特率为115200
- 16 dcb.ByteSize = 8; //每个字节有8位
- 17 dcb.Parity = NOPARITY; //无奇偶校验位
- 18 dcb.StopBits = TWOSTOPBITS; //两个停止位
- 19 SetCommState( hCom, &dcb );
- 20 PurgeComm(hCom,PURGE_TXCLEAR|PURGE_RXCLEAR);
- 21 }