200分求教:有没有办法在等待20秒时间之内,直到缓冲区满24个字节为止才调用ReadFile一次?或者将缓冲区的数据读完后仍然保存在缓冲区里面呢?

Alan S1 2009-01-07 09:18:13
现在我在项目中遇到这样的一个问题:用重叠IO方式读取串口的数据:代码如下dwBytesRead = 24;

bReadStatus=ReadFile(hCom,lpInBuffer,dwBytesRead,&dwBytesRead,&m_osRead);
if(!bReadStatus){

if(GetLastError()==ERROR_IO_PENDING){
WaitForSingleObject(m_osRead.hEvent,20000);
......................................................
}

现在项目中要求只有串口的输入缓冲区中满了24个字节之后,才能一起读取出来。那么这段代码就遇到了这么一个缺陷:
如果在执行ReadFile时候串口的输入缓冲区只有10个字节的话,ReadFile会将这10个字节读取出来,以后下位机再送入串口的数据将会乱掉(顺序等等)。
有没有办法在等待20秒时间之内,直到缓冲区满24个字节为止才调用ReadFile一次?或者将缓冲区的数据读完后仍然保存在缓冲区里面呢?
...全文
222 20 打赏 收藏 转发到动态 举报
写回复
用AI写文章
20 条回复
切换为时间正序
请发表友善的回复…
发表回复
ProgrameMan 2009-01-08
  • 打赏
  • 举报
回复
有办法的,其实你要做解决的问题可以缩小为:检查串口接收缓冲区中的数据长度,如果你能在接收之前获得这个长度信息就可以决定是否需要进一步的读取,也就满足了楼主的要求。

利用ClearCommError()API函数可以检测串口的状态。
BOOL ClearCommError(
HANDLE hFile, // handle to communications device
LPDWORD lpErrors, // pointer to variable to receive error codes
LPCOMSTAT lpStat // pointer to buffer for communications status
);

还有结构体COMSTAT ,存放串口设备的信息。ClearCommError()来填充这个结构体。
typedef struct _COMSTAT {
DWORD fCtsHold : 1; // Tx waiting for CTS signal
DWORD fDsrHold : 1; // Tx waiting for DSR signal
DWORD fRlsdHold : 1; // Tx waiting for RLSD signal
DWORD fXoffHold : 1; // Tx waiting, XOFF char received
DWORD fXoffSent : 1; // Tx waiting, XOFF char sent
DWORD fEof : 1; // EOF character sent
DWORD fTxim : 1; // character waiting for Tx
DWORD fReserved : 25; // reserved
DWORD cbInQue; // bytes in input buffer
DWORD cbOutQue; // bytes in output buffer
} COMSTAT, *LPCOMSTAT;


BOOL ReadCom()
{
BOOL result;
DWORD nRead = 0;
BYTE Rece_Buf[BUF_MAX_BYTE];
COMSTAT CommStatus;
DWORD Error_Code;

ClearCommError(hCom,&Error_Code,&CommStatus);

if(CommStatus.cbInQue<30) return FALSE;

result=ReadFile(hCom,&Rece_Buf[0],BUF_MAX_BYTE,&nRead,NULL);

ASSERT(result);
if( (!result)||(nRead<=0)||(nRead>BUF_MAX_BYTE) ) return FALSE;

if(snd_rcv_buf.buf_count+nRead > BUF_MAX_BYTE)
snd_rcv_buf.buf_count = 0;

memcpy(&snd_rcv_buf.ReceBuf[snd_rcv_buf.buf_count],&Rece_Buf[0],nRead);

snd_rcv_buf.buf_count += (int)nRead;
return TRUE;
}
猞猁狲 2009-01-08
  • 打赏
  • 举报
回复
分配一个24字节的缓冲区,一个循环不停的读,不停的向你自己的缓冲区里填充满24了就取出
猞猁狲 2009-01-08
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 Mackz 的回复:]
读取出来之后自己再缓存重新组织好了,怎么会乱掉呢?
[/Quote]

强烈赞成
分配一个24字节的缓冲区,一个循环不停的读,不停的向你自己的缓冲区里填充满24了就取出
Alan S1 2009-01-08
  • 打赏
  • 举报
回复
最后我还是用while循环 + WaitSingleObject做的,
代码:ReadFile(hCom, 24-read_bytes, &dwReadBtyes, &os); read_bytes+=dwReadBtyes


非常感谢大家
yedaoq 2009-01-08
  • 打赏
  • 举报
回复
如果发送方的数据长度不定的话,LZ应当再实现一个缓存区,所有串口缓存都立即读入该缓存区;另外为该缓存实现一个ReadFile接口即可。
一条晚起的虫 2009-01-08
  • 打赏
  • 举报
回复
可以用ClearCommError()获取当前串口缓冲区内的字节数。
不过lz的思路是有问题的。一次读取24个字节,并不能保证这24个字节都是同一帧内的数据。
还是要通过读取数据后,根据通讯协议解析数据,才能得到正确的结果。
野男孩 2009-01-08
  • 打赏
  • 举报
回复
你这需求完全是鬼扯。

24字节这种限制是应用层自己的协议,应用层应该根据自己的需要做拆包连包等情况的缓存。保序也是异步机制所必需的控制,如果控制不好就不要用异步的方式。
ilovedrv 2009-01-07
  • 打赏
  • 举报
回复
不知道为什么一定要读24字节

串口传输是采用流方式,需要自己定义协议完成数据完整性控制
roadblossom 2009-01-07
  • 打赏
  • 举报
回复
up
cnzdgs 2009-01-07
  • 打赏
  • 举报
回复
自己定义24字节的缓冲区,多次ReadFile,每次根据实际读取到的数据调整指针和要读取的长度,读满为止。
菜牛 2009-01-07
  • 打赏
  • 举报
回复
对于流输入设备是没办法判断有多少数据的,自己缓存加上计数完全可以解决你的问题;也有一个办法,就是设置端口的缓冲就为24个字节,然后等待缓冲溢出的错误再去读数据,这个方法对socket是可以的,对串口没有试过,存在丢失数据的风险,还增加了复杂性。
keven1868 2009-01-07
  • 打赏
  • 举报
回复
DeviceIoControl不能获取下当前缓冲区内的字节数么?置Control Code为IOCTL_SERIAL_LSRMST_INSERT或是别的?
Tinary3v0 2009-01-07
  • 打赏
  • 举报
回复
每次读取缓存中的数据 将数据追加到一个全局的char[]里面 检测char[]是否到了24个 也就是
不在读串口的时候来做判断串口缓存是否为24字符 而是每次追加后 检测 定义的char[]是否到了24个字符。
Alan S1 2009-01-07
  • 打赏
  • 举报
回复
除了自己把前10个字节保存在单独的缓存里,还有没有其它的办法了?
Alan S1 2009-01-07
  • 打赏
  • 举报
回复
24个字节是下位机的一组完整的信息,我想等到缓冲区中满了24个字节后再一次新的读取,由于我用的是重叠IO的读取,所以有没有办法用WaitSingleObject?

bReadStatus=ReadFile(hCom,lpInBuffer,dwBytesRead,&dwBytesRead,&m_osRead);
if(!bReadStatus){

if(GetLastError()==ERROR_IO_PENDING){
WaitForSingleObject(m_osRead.hEvent,20000);
......................................................
}

用上面的方式的话,如果在ReadFile时,串口的输入缓冲中没有字符,那么结果是我想要的,但是如果缓冲中有数据10个字节,则一调用ReadFile,
将把缓冲区的数据10个字节取走,接下来,想判断哪个24字节是一组完整的信息就比较麻烦.
僵哥 2009-01-07
  • 打赏
  • 举报
回复
为什么一定要满24个字节再读出来,而不能在读取不足24字节的时候进行缓存并继续接收,当多余24字节时先按每24字节一部分进行处理,把剩余不足24字节的缓存下来,然后继续接收?
keven1868 2009-01-07
  • 打赏
  • 举报
回复
用WaitCommEvent来等待可读事件,再去ReadFile,读出来缓存一下直到读足24字节不可以么?
sys0007 2009-01-07
  • 打赏
  • 举报
回复
你把每次读到的数据放到另一缓冲区中,每次读到的都累加到后面,应该不会乱的啊
Alan S1 2009-01-07
  • 打赏
  • 举报
回复
用程序可以保证不乱掉吧,但是我就是想一次读取24个字节,请教有没有办法呢?
菜牛 2009-01-07
  • 打赏
  • 举报
回复
读取出来之后自己再缓存重新组织好了,怎么会乱掉呢?

16,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧