对串口通讯中的
COMMTIMEOUTS参数一直很疑惑。到底是怎么起作用的呢?
曾经写一个简单的串口通讯程序,其中的过程是发60个字节数据到设备,然后过一段时间后大概是1到2秒的时间,会返回两次各60字节的数据,结果因为
COMMTIMEOUTS的作用不清楚,试了好久。现总结一下。
写操作时间有两种设置模式:
如下设置,写操作时,不考虑时间限制,直到写完成才返回
CommTimeOuts.WriteTotalTimeoutMultipl ier = 0;
CommTimeOuts.WriteTotalTimeoutConstan
t = 0;
如下设置,即a,b中至少有一个大于0,此时以
b+
a*(发送字节数
nBufLen
) 为时间限制,超时则返回
CommTimeOuts.WriteTotalTimeoutMultipl ier = a;
CommTimeOuts.WriteTotalTimeoutConstan
t = b;
实际试验中,可能由于我的写的数据量太少,才60个字节,所以发送很快,两种模式下都很快返回了,看不出什么区别。而且串口的另一端没有设备连接时也可以写数据,所以写操作设置可以随意一些。
CommTimeOuts.ReadIntervalTimeout 与
(CommTimeOuts.ReadTotalTimeoutMultipli er
、
CommTimeOuts.ReadTotalTimeoutConstant )
分两组
共同起影响。
2.1
CommTimeOuts.ReadIntervalTimeout
管理单个字符的读时限。
CommTimeOuts.ReadIntervalTimeout=0; 表示对单个字符的读不加时限。
CommTimeOuts.ReadIntervalTimeout=a; (a>0) 表示 从读操作(即
ReadFile
)启动开始每a毫秒内能读到下一个字符(包括第一个字符),则OK,否则返回。
2.2
CommTimeOuts.ReadTotalTimeoutMultipli er 和
CommTimeOuts.ReadTotalTimeoutConstant
管理总的读数时限
如下设置时
表示不加限制
CommTimeOuts.ReadTotalTimeoutMultipli er
=0;
CommTimeOuts.ReadTotalTimeoutConstant =0;
如下设置时,
b,c中至少有一个大于0,
c
+
b*(读取字节数
nBufLen
) 为总时限,超过则返回
CommTimeOuts.ReadTotalTimeoutMultipli er
=b;
CommTimeOuts.ReadTotalTimeoutConstant =c;
CommTimeOuts.ReadIntervalTimeout=
MAXDWORD
;
CommTimeOuts.ReadTotalTimeoutMultipli er
=0;
CommTimeOuts.ReadTotalTimeoutConstant =0;
CommTimeOuts.ReadIntervalTimeout=
0
;
CommTimeOuts.ReadTotalTimeoutMultipli er
=0;
CommTimeOuts.ReadTotalTimeoutConstant =0;
CommTimeOuts.ReadIntervalTimeout=
0
; //对单个字符不设限制,无限等待
CommTimeOuts.ReadTotalTimeoutMultipli er
=0;
CommTimeOuts.ReadTotalTimeoutConstant =5000; //限制总的时限不超过5秒, 主要考虑到设备返回数据没那么快, 且防止永久阻塞
CommTimeOuts.WriteTotalTimeoutMultipl ier = 0; //以下两个设置在使用没发现太大效果
CommTimeOuts.WriteTotalTimeoutConstan
t = 1000;
在异步通讯下,时限设置也是有影响的。
试验中,曾串口异步通讯中如下设置
CommTimeOuts.ReadIntervalTimeout = 100;
CommTimeOuts.ReadTotalTimeoutMultipli
er = 0;
CommTimeOuts.ReadTotalTimeoutConstant
= 250;
读串口内容时,如下
if(
ReadFile(m_hComm,
(LPVOID)buf,
bufLen,
&dwReadLen,
&m_hOLP)
)
上面编写的目的是希望
WaitForSingleObject(m_hWRevent,5000) 中
在读到
bufLen 个数据后
m_hWRevent
才变为激活状态,才返回,但实际是很快返回,而
buf 中的内容仍然是初始状态。
由于我当时并没有意识到是时限的问题,我就换了个函数,如下
if(ReadFile(m_hComm, (LPVOID)buf, bufLen, &dwReadLen,&m_hOLP))
因为我看到MSDN说
GetOverlappedResult 函数在第四个参数设置为TRUE后,会产生阻塞效果,直接异步操作完成,但实际运行时,仍然是
GetOverlappedResult很快就返回了,且
buf 中并未读取到所需的值。
最后没办法,在不太了解的情况下,我尝试如下,终于可以得到正确结果了
CommTimeOuts.ReadIntervalTimeout = 0;
CommTimeOuts.ReadTotalTimeoutMultipli
er = 0;
CommTimeOuts.ReadTotalTimeoutConstant
= 0;
在同步通讯中,对ReadFile和WriteFile的何时完成返回产生作用。
在异步
通讯
中
,Read和WriteFile是立即返回的,当返回值时为TRUE时,当然就不提了,但当返回FALSE且
GetLastError()==ERROR_IO_PENDING 时,就对异步操作相关事件的状态起影响。
我认为假设同步通讯时,读写根据时限设置应该返回了,相应的在异步通讯状态下,读写的事件就应该变为激活状态了。
当事件激活后
WaitForSingleObject(m_hWRevent,5000)==WAIT_OBJECT_0 此时就为真了
而
GetOverlappedResult(m_hComm,&m_hOLP,&dwReadLen,TRUE) 的第四个参数为TRUE时,会等待,但当事件状态为激活后,也就会返回。
一、针对同步通讯专门试了一下其效用。
1
WriteFile(m_hComm, cBufSend, nBufLen , &dwNumBytesWritten, 0);
2
ReadFile(m_hComm, cBufSend,
nBufLen ,
&dwNumBytesReaded, 0);
2.3 MSDN中提到如下的时限设置,无论是否读到数据,读操作立即返回,读缓冲区的已有内容需读取返回
2.4
注意:如下设置时,很可能阻塞,建议不使用
3 在以上都清楚的情况下,进行如下设置就很快成功了
二、串口异步通讯时,时限设置的影响
{
return true;
}
else
{
if(GetLastError()==ERROR_IO_PENDING)
{
if(WaitForSingleObject(m_hWRevent,5000)==WAIT_OBJECT_0)
return true;
//此处应该是
}
}
{
return true;
}
else
{
if(GetLastError()==ERROR_IO_PENDING)
{
if(
GetOverlappedResult(m_hComm,&m_hOLP,&dwReadLen,TRUE)
&& dwReadLen==bufLen)
{
return true;
}
return true;
}
}
三、 综上所述,我得出的结果是,
COMMTIMEOUTS
在同步或异步通讯时都是起效果的,只是产生效果的地方不一样。