串口的SetCommTimeouts

对串口通讯中的 COMMTIMEOUTS参数一直很疑惑。到底是怎么起作用的呢?  
      
      曾经写一个简单的串口通讯程序,其中的过程是发60个字节数据到设备,然后过一段时间后大概是1到2秒的时间,会返回两次各60字节的数据,结果因为 COMMTIMEOUTS的作用不清楚,试了好久。现总结一下。

一、针对同步通讯专门试了一下其效用。  

        COMMTIMEOUTS    CommTimeOuts;

1     WriteFile(m_hComm, cBufSend,  nBufLen ,  &dwNumBytesWritten, 0);  

      写操作时间有两种设置模式:
      如下设置,写操作时,不考虑时间限制,直到写完成才返回
        CommTimeOuts.WriteTotalTimeoutMultiplier = 0;  
      CommTimeOuts.WriteTotalTimeoutConstan t = 0;  

      如下设置,即a,b中至少有一个大于0,此时以   b+  a*(发送字节数  nBufLen   )  为时间限制,超时则返回
        CommTimeOuts.WriteTotalTimeoutMultiplier = a;  
      CommTimeOuts.WriteTotalTimeoutConstan t = b;  
     
      实际试验中,可能由于我的写的数据量太少,才60个字节,所以发送很快,两种模式下都很快返回了,看不出什么区别。而且串口的另一端没有设备连接时也可以写数据,所以写操作设置可以随意一些。

2   ReadFile(m_hComm, cBufSend,   nBufLen ,   &dwNumBytesReaded, 0);
       
      CommTimeOuts.ReadIntervalTimeout  与 
       (CommTimeOuts.ReadTotalTimeoutMultiplier   CommTimeOuts.ReadTotalTimeoutConstant)
       分两组 共同起影响。

  2.1     CommTimeOuts.ReadIntervalTimeout  管理单个字符的读时限。
          CommTimeOuts.ReadIntervalTimeout=0;  表示对单个字符的读不加时限。
            CommTimeOuts.ReadIntervalTimeout=a; (a>0)  表示  从读操作(即 ReadFile )启动开始每a毫秒内能读到下一个字符(包括第一个字符),则OK,否则返回。

  2.2    CommTimeOuts.ReadTotalTimeoutMultiplier 和  CommTimeOuts.ReadTotalTimeoutConstant   管理总的读数时限
            如下设置时 表示不加限制
            CommTimeOuts.ReadTotalTimeoutMultiplier =0;
            CommTimeOuts.ReadTotalTimeoutConstant=0; 
             如下设置时,  b,c中至少有一个大于0, c b*(读取字节数 nBufLen   )  为总时限,超过则返回
            CommTimeOuts.ReadTotalTimeoutMultiplier =b; 
             CommTimeOuts.ReadTotalTimeoutConstant=c; 
 
2.3   MSDN中提到如下的时限设置,无论是否读到数据,读操作立即返回,读缓冲区的已有内容需读取返回
          CommTimeOuts.ReadIntervalTimeout=  MAXDWORD  ;
            CommTimeOuts.ReadTotalTimeoutMultiplier =0;
          CommTimeOuts.ReadTotalTimeoutConstant=0; 

2.4   注意:如下设置时,很可能阻塞,建议不使用
         CommTimeOuts.ReadIntervalTimeout= 0 ;
        CommTimeOuts.ReadTotalTimeoutMultiplier =0;
        CommTimeOuts.ReadTotalTimeoutConstant=0; 
       
3    在以上都清楚的情况下,进行如下设置就很快成功了
          CommTimeOuts.ReadIntervalTimeout= 0 ;                          //对单个字符不设限制,无限等待
        CommTimeOuts.ReadTotalTimeoutMultiplier =0;
        CommTimeOuts.ReadTotalTimeoutConstant=5000;         //限制总的时限不超过5秒,  主要考虑到设备返回数据没那么快, 且防止永久阻塞

        CommTimeOuts.WriteTotalTimeoutMultiplier = 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)   )
{
return true;
}
else
{
if(GetLastError()==ERROR_IO_PENDING)
{
if(WaitForSingleObject(m_hWRevent,5000)==WAIT_OBJECT_0)
return true;         //此处应该是
}
}
         
        上面编写的目的是希望   WaitForSingleObject(m_hWRevent,5000) 中  在读到   bufLen 个数据后 m_hWRevent   才变为激活状态,才返回,但实际是很快返回,而  buf 中的内容仍然是初始状态。

        由于我当时并没有意识到是时限的问题,我就换了个函数,如下
          if(ReadFile(m_hComm, (LPVOID)buf, bufLen, &dwReadLen,&m_hOLP))
{
return true;
}
else
{
if(GetLastError()==ERROR_IO_PENDING)
{
if( GetOverlappedResult(m_hComm,&m_hOLP,&dwReadLen,TRUE)
&& dwReadLen==bufLen)
{
return true;
}
return true;
}
}
        因为我看到MSDN说  GetOverlappedResult 函数在第四个参数设置为TRUE后,会产生阻塞效果,直接异步操作完成,但实际运行时,仍然是 GetOverlappedResult很快就返回了,且  buf 中并未读取到所需的值。
        
        最后没办法,在不太了解的情况下,我尝试如下,终于可以得到正确结果了
           CommTimeOuts.ReadIntervalTimeout = 0;  
        CommTimeOuts.ReadTotalTimeoutMultipli er = 0;  
          CommTimeOuts.ReadTotalTimeoutConstant = 0;  


三、 综上所述,我得出的结果是, COMMTIMEOUTS  在同步或异步通讯时都是起效果的,只是产生效果的地方不一样。
        在同步通讯中,对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时,会等待,但当事件状态为激活后,也就会返回。
  • 6
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值