串口通讯中,如何判断readfile已经完整的读完了输入缓存区的数据?

glacierful 2008-12-10 05:12:43
通过PC上的串口来接收工控设备上返回的一些字符串,这些返回的字符串根据情况有时是几个字符,有时候会是大段的字符串。使用的是readfile函数。
我打算使用同步方式,把读取过程放到一个线程中来执行。

BOOL ReadFile(
HANDLE hFile,
LPVOID lpBuffer,
DWORD nNumberOfBytesToRead,
LPDWORD lpNumberOfBytesRead,
LPOVERLAPPED lpOverlapped
);

我想知道的是,如何知道工控设备上返回的字符串已经全部放入了输入缓存区,如何判断readfile已经完全读完了缓存区中的数据?
...全文
1179 15 打赏 收藏 转发到动态 举报
写回复
用AI写文章
15 条回复
切换为时间正序
请发表友善的回复…
发表回复
CA_HA_M 2008-12-11
  • 打赏
  • 举报
回复
BOOL bReadStat = ReadFile(m_hCom, buf, lenght, &lenght, &m_osRead);

if(!bReadStat)
{
if(GetLastError()==ERROR_IO_PENDING)
//GetLastError()函数返回ERROR_IO_PENDING,表明串口正在进行读操作
{
WaitForSingleObject(m_osRead.hEvent,m_intWaiteTime);
//使用WaitForSingleObject函数等待,直到读操作完成或延时已达到m_intCharTime
//当串口读操作进行完毕后,m_osRead的hEvent事件会变为有信号
}
}
glacierful 2008-12-11
  • 打赏
  • 举报
回复
我打算使用逐字节读取输入缓存区的方式来取字符串了。
谢谢大家的回答,让我学了不少啊。
glacierful 2008-12-11
  • 打赏
  • 举报
回复
[Quote=引用 9 楼 CA_HA_M 的回复:]
C/C++ codeBOOL bReadStat = ReadFile(m_hCom, buf, lenght, &lenght, &m_osRead);

if(!bReadStat)
{
if(GetLastError()==ERROR_IO_PENDING)
//GetLastError()函数返回ERROR_IO_PENDING,表明串口正在进行读操作
{
WaitForSingleObject(m_osRead.hEvent,m_intWaiteTime);
//使用WaitForSingleObject函数等待,直到读操作完成或延时已达到m_intCharTime

[/Quote]

我计划使用同步的方式来进行数据的收发,不想采用overlapped模式。
一条晚起的虫 2008-12-11
  • 打赏
  • 举报
回复
计算好通讯所需时间,
上位机发送成功 + 下位机响应 + 下位机发送时间 (这个时间也可以实际测试)
延时后,再ClearCommError
此时上位机不发命令,下位机就不会再发数据过来。
glacierful 2008-12-11
  • 打赏
  • 举报
回复
[Quote=引用 8 楼 wocow3 的回复:]
C/C++ code
COMSTAT comstat;
DWORD err = 0;
DWORD num = 0;

if (!ClearCommError(hComDev, &err, &comstat) || err != 0)
{
PurgeComm(hComDev, PURGE_RXABORT | PURGE_RXCLEAR);
return;
}

ReadFile(hComDev, pComReceiveIoEnd, comstat.cbInQue, &num, NULL);


通过ClearCommError确定当前接收缓冲区的数据量
[/Quote]

发送完命令后,马上就使用ClearCommError来获取接收缓存区的数据大小。这种情况下会不会出现,ClearCommError取了大小后,又有数据进来,然后实际的输入缓存区的数据长度大于ClearCommError取到的长度。
一条晚起的虫 2008-12-11
  • 打赏
  • 举报
回复
我看有些示例程序,使用readfile在循环中一个字节一个字节来读,直到第三个参数LPDWORD lpNumberOfBytesRead的返回值不再为1时,就结束读取。不知道这种方式是否可以取到缓存区中的全部字符?
//可以。
//其实可以按照你能收到的数据的最小粒度来读。读到NumberOfBytesRead小于NumberWantToRead就可以了。
glacierful 2008-12-11
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 ilovedrv 的回复:]
这个需要定义协议,比如你用单片机做下位机,pc做上位机

单片机发送数据应该有一定格式,比如 数据长度+ 数据内容

这样在pc端,先读长度,然后readfile指定长度的数据,这时候有两种情况,readfile返回的读取字节数等于你指定的,这样就直接返回,如果读取字符数小于你指定的,那么继续readfile,这次的长度应该是剩余要读取的字符数,以此循环,直到读到的数据为你需要的为止,当然可以加超时判断
[/Quote]

这个设备是先发送命令到工控机,然后设备会返回一串字符,这个字符串没有给出长度,也没有起止结束符号。所以比较头疼。

我看有些示例程序,使用readfile在循环中一个字节一个字节来读,直到第三个参数LPDWORD lpNumberOfBytesRead的返回值不再为1时,就结束读取。不知道这种方式是否可以取到缓存区中的全部字符?
wocow3 2008-12-10
  • 打赏
  • 举报
回复

COMSTAT comstat;
DWORD err = 0;
DWORD num = 0;

if (!ClearCommError(hComDev, &err, &comstat) || err != 0)
{
PurgeComm(hComDev, PURGE_RXABORT | PURGE_RXCLEAR);
return;
}

ReadFile(hComDev, pComReceiveIoEnd, comstat.cbInQue, &num, NULL);

通过ClearCommError确定当前接收缓冲区的数据量
laomig 2008-12-10
  • 打赏
  • 举报
回复
一般协议有定义好数据长度再决定读多少个字符的,也有不定义好长度,而是用固定的起始和结束字符来标示的!
我估计你属于后者,起始Readfile是无法判断是否读完了接收缓冲区的内容,而是需要先通过ClearCommError确定接收缓冲区有多少字符
shaopengcheng_8 2008-12-10
  • 打赏
  • 举报
回复
太复杂,不懂
ilovedrv 2008-12-10
  • 打赏
  • 举报
回复
这个需要定义协议,比如你用单片机做下位机,pc做上位机

单片机发送数据应该有一定格式,比如 数据长度+ 数据内容

这样在pc端,先读长度,然后readfile指定长度的数据,这时候有两种情况,readfile返回的读取字节数等于你指定的,这样就直接返回,如果读取字符数小于你指定的,那么继续readfile,这次的长度应该是剩余要读取的字符数,以此循环,直到读到的数据为你需要的为止,当然可以加超时判断
zaodt 2008-12-10
  • 打赏
  • 举报
回复

下面这篇文章正适合你,先看看,看完有问题再问:


使用Win32创建串口通讯程序

http://www.vckbase.com/document/viewdoc/?id=1114
qinxiaogang 2008-12-10
  • 打赏
  • 举报
回复
这个ReadFile是判断不了的. 只能由自己的程序来判断.
luowin 2008-12-10
  • 打赏
  • 举报
回复
串口数据都是一个一个字节传送的;
glacierful 2008-12-10
  • 打赏
  • 举报
回复
再问一下,工控设备返回的字符串是以一个一个的字符逐步放入缓存区的吗?

16,472

社区成员

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

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

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