如何使用COMMTIMEOUTS等待字节可用但读取多个字节?

时间:2022-07-07 21:45:00

I have a C++ serial port class that has a none blocking and a blocking mode for read operations. For blocking mode:

我有一个C ++串行端口类,它具有无阻塞和阻塞模式的读操作。对于阻止模式:

COMMTIMEOUTS cto;
GetCommTimeouts(m_hFile,&cto);
// Set the new timeouts
cto.ReadIntervalTimeout = 0;
cto.ReadTotalTimeoutConstant = 0;
cto.ReadTotalTimeoutMultiplier = 0;
SetCommTimeouts(m_hFile,&cto)

For non blocking mode:

对于非阻塞模式:

COMMTIMEOUTS cto;
GetCommTimeouts(m_hFile,&cto);
// Set the new timeouts
cto.ReadIntervalTimeout = MAXDWORD;
cto.ReadTotalTimeoutConstant = 0;
cto.ReadTotalTimeoutMultiplier = 0;
SetCommTimeouts(m_hFile,&cto)

I would like to add another mode that waits for any number of bytes and read them.

我想添加另一种等待任意数量字节并读取它们的模式。

From MSDN COMMTIMEOUTS structure:

从MSDN COMMTIMEOUTS结构:

If an application sets ReadIntervalTimeout and ReadTotalTimeoutMultiplier to MAXDWORD and sets ReadTotalTimeoutConstant to a value greater than zero and less than MAXDWORD, one of the following occurs when the ReadFile function is called:

如果应用程序将ReadIntervalTimeout和ReadTotalTimeoutMultiplier设置为MAXDWORD并将ReadTotalTimeoutConstant设置为大于零且小于MAXDWORD的值,则在调用ReadFile函数时会发生以下情况之一:

  • If there are any bytes in the input buffer, ReadFile returns immediately with the bytes in the buffer.
  • 如果输入缓冲区中有任何字节,则ReadFile会立即返回缓冲区中的字节。

  • If there are no bytes in the input buffer, ReadFile waits until a byte arrives and then returns immediately.
  • 如果输入缓冲区中没有字节,则ReadFile会等待一个字节到达,然后立即返回。

  • If no bytes arrive within the time specified by ReadTotalTimeoutConstant, ReadFile times out.
  • 如果在ReadTotalTimeoutConstant指定的时间内没有字节到达,则ReadFile超时。

This looks in code like this:

这看起来像这样的代码:

COMMTIMEOUTS cto;
GetCommTimeouts(m_hFile,&cto);
// Set the new timeouts
cto.ReadIntervalTimeout = 100;
cto.ReadTotalTimeoutConstant = MAXDWORD;
cto.ReadTotalTimeoutMultiplier = MAXDWORD;
SetCommTimeouts(m_hFile,&cto)

But this returns emidiately on the first byte. This is a problem since I am reading the port in a loop and the handling of a byte is so fast that the next time I read the port, only another byte is available. The end result is that I am reading one byte at a time in a loop and using 100% of the core running that thread.

但是这会在第一个字节上显示返回。这是一个问题,因为我在循环中读取端口并且字节的处理速度太快以至于下次读取端口时,只有另一个字节可用。最终结果是我在循环中一次读取一个字节并使用100%运行该线程的核心。

I would like to use the cto.ReadIntervalTimeout like in the MSDN documentation but still wait until at least one byte is available. Does anyone have an idea?

我想在MSDN文档中使用cto.ReadIntervalTimeout,但仍然要等到至少有一个字节可用。有没有人有想法?

Thanks.

3 个解决方案

#1


3  

The behavior you want will come from:

您想要的行为将来自:

cto.ReadIntervalTimeout = 10;
cto.ReadTotalTimeoutConstant = 0;
cto.ReadTotalTimeoutMultiplier = 0;

It blocks arbitrarily long for the first byte (total timeout is disabled by setting the latter two fields to zero, per the documentation), then reads up to the buffer size as long as data is streaming in. If there's a 10ms gap in the data, it will return with what has been received so far.

它会对第一个字节任意阻塞任意长度(根据文档将后两个字段设置为零来禁用总超时),然后只要数据流入就读取缓冲区大小。如果数据中有10ms的间隙,它将与迄今为止收到的内容一起返回。

#2


1  

If you're using 100% (or even close to it) of the CPU, it sounds like you're doing something wrong elsewhere. As I showed in a previous answer, for years I've used code with the timeouts all set to 1. I initially set it that way just as a wild guess at something that might at least sort of work, with the intent of tuning it later. It's worked well enough that I've never gotten around to tuning it at all. Just for example, it'll read input from my GPS (about the only thing I have that even imitates using a serial port any more) using an almost immeasurably tiny amount of CPU time -- after hours of reading a constant stream of data from the GPS, it still shows 0:00:00 seconds of CPU time used (and I can't see any difference in CPU usage whether it's running or not).

如果您使用100%(甚至接近它)的CPU,听起来你在其他地方做错了。正如我在之前的回答中所表明的那样,多年来我一直使用的代码都设置为1。我最初设置它就像对某些可能至少有点工作的东西一样疯狂猜测,目的是调整它后来。它运作得很好,我根本就没有调整它。例如,它会从我的GPS中读取输入(关于我唯一能够使用串行端口模仿的东西),使用几乎无法估量的微小CPU时间 - 在数小时后从中读取恒定的数据流GPS,它仍然显示0:00:00秒使用的CPU时间(我看不出CPU使用情况是否有任何差异)。

Now, I'll certainly grant that a GPS isn't (even close to) the fastest serial device around, but we're still talking about ~100% vs. ~0%. That's clearly a pretty serious difference.

现在,我肯定会认为GPS不是(甚至接近)最快的串行设备,但我们仍然在谈论~100%对比~0%。这显然是一个非常严重的差异。

#3


0  

if (dwEvtMask == EV_RXCHAR )
{
   Sleep(1);
   if (dwLength > 2)
    {
      Sleep(1);
      Readfile( m_Serial->m_hCom, data,dwLength, &dwBytesRead, &Overlapped);
      pDlg->PostMessage(WM_RECEIVE,0,0);
    }
}

#1


3  

The behavior you want will come from:

您想要的行为将来自:

cto.ReadIntervalTimeout = 10;
cto.ReadTotalTimeoutConstant = 0;
cto.ReadTotalTimeoutMultiplier = 0;

It blocks arbitrarily long for the first byte (total timeout is disabled by setting the latter two fields to zero, per the documentation), then reads up to the buffer size as long as data is streaming in. If there's a 10ms gap in the data, it will return with what has been received so far.

它会对第一个字节任意阻塞任意长度(根据文档将后两个字段设置为零来禁用总超时),然后只要数据流入就读取缓冲区大小。如果数据中有10ms的间隙,它将与迄今为止收到的内容一起返回。

#2


1  

If you're using 100% (or even close to it) of the CPU, it sounds like you're doing something wrong elsewhere. As I showed in a previous answer, for years I've used code with the timeouts all set to 1. I initially set it that way just as a wild guess at something that might at least sort of work, with the intent of tuning it later. It's worked well enough that I've never gotten around to tuning it at all. Just for example, it'll read input from my GPS (about the only thing I have that even imitates using a serial port any more) using an almost immeasurably tiny amount of CPU time -- after hours of reading a constant stream of data from the GPS, it still shows 0:00:00 seconds of CPU time used (and I can't see any difference in CPU usage whether it's running or not).

如果您使用100%(甚至接近它)的CPU,听起来你在其他地方做错了。正如我在之前的回答中所表明的那样,多年来我一直使用的代码都设置为1。我最初设置它就像对某些可能至少有点工作的东西一样疯狂猜测,目的是调整它后来。它运作得很好,我根本就没有调整它。例如,它会从我的GPS中读取输入(关于我唯一能够使用串行端口模仿的东西),使用几乎无法估量的微小CPU时间 - 在数小时后从中读取恒定的数据流GPS,它仍然显示0:00:00秒使用的CPU时间(我看不出CPU使用情况是否有任何差异)。

Now, I'll certainly grant that a GPS isn't (even close to) the fastest serial device around, but we're still talking about ~100% vs. ~0%. That's clearly a pretty serious difference.

现在,我肯定会认为GPS不是(甚至接近)最快的串行设备,但我们仍然在谈论~100%对比~0%。这显然是一个非常严重的差异。

#3


0  

if (dwEvtMask == EV_RXCHAR )
{
   Sleep(1);
   if (dwLength > 2)
    {
      Sleep(1);
      Readfile( m_Serial->m_hCom, data,dwLength, &dwBytesRead, &Overlapped);
      pDlg->PostMessage(WM_RECEIVE,0,0);
    }
}