各位大侠,这是一个关于串口读操作的问题,望不啬赐教!(有一位大侠曾经指点过我,但是还有点不明白,故发贴请教)

kmilong 2002-05-11 03:12:32

在下述代码中如何使串口未读完的操作完成呢?

fReadStat = ReadFile(m_hCom, lpszBlock,
dwLength, &dwLength, &( m_rdos) ) ;//读串口
if (!fReadStat)
{
if (GetLastError() == ERROR_IO_PENDING)
{
while(!GetOverlappedResult(m_hCom ,
&( m_rdos), &dwLength, TRUE ))
//各位大侠,小弟不明白的是这句,readfile已经执行完了,还能再回去执行吗?如
//果不能,这句岂不是死循环了吗?
//即使循环了也不能循环到readfile呀?如何读完的呢?
{
dwError = GetLastError();
if(dwError == ERROR_IO_INCOMPLETE)
continue;
else
{
wsprintf( szError, "<CE-%u>", dwError ) ;
ClearCommError(m_hCom , &dwErrorFlags, &ComStat ) ;
break;
}
}
………..
...全文
152 10 打赏 收藏 转发到动态 举报
AI 作业
写回复
用AI写文章
10 条回复
切换为时间正序
请发表友善的回复…
发表回复
qiuanhong 2002-05-11
  • 打赏
  • 举报
回复
下面两点我觉得不是很好:(对了,只是我个人的理解)
2。GetOverlappedResult只是一个等待的线程,起延时作用。
GetOverlappedResult()是等待直到信号状态变为有产,而ReadFile()操作没有完成时,信号是无效的(上面第2点),当ReadFile()操作完成后,系统把它(前面无效信号)设置为有信号状态。当信号为有效后,GetOverlappedResult()函数才执行成功(返回非0,退出while()循环).所以它并不是起延时作用,而是等待读操作完成来获取实际读得的字符数。

3。readfile在这段延时的时间内,又重新读串口,是这样的吗?这个没有任何东西触发它呀,难道它有一个自身定时的循环,只要有时间,就能多次读数据?
这一点,相信看了刚才第2个问题你会理解的了---------ReadFile()是一直在读取数据的,直到读成功。而GetoverlappedResult()只是对这一次Readfile()(注意是只这一次)获取该次的结果,或许只1个字符(你在ReadFile里指定每次读取的字符数)在这里,你可能没读懂,ReadFile()外面应该还有个大的While()循环)。
也就是说,当GetoverlappedResult()成功后,将继续读取输入缓冲区中的下一比数据,因而会继续重复你上面的代码的动作。


kmilong 2002-05-11
  • 打赏
  • 举报
回复
谢谢大侠!!
qsfsea 2002-05-11
  • 打赏
  • 举报
回复
这是另一种方法,看不懂的最好去查msdn,这样才能真正掌握!
有点乱,但肯定好用

UINT ReadCommThread(LPVOID pParam)
{
char szReadBuf[300]; //读缓冲
int n,k,j,x; //记数
DWORD dwEvent,dwError; //
COMSTAT cs;
OVERLAPPED OLwait; //重叠结构
CString cstrCount,cstrTemp; //暂存
MSG msg; //消息体
OLwait.hEvent=CreateEvent(NULL, FALSE, FALSE, NULL);
CMyCommDlg * pMyDlg =(CMyCommDlg *)pParam;
if(OLwait.hEvent==NULL||!SetCommMask(pMyDlg->m_myComm.m_hCom,EV_RXCHAR|EV_RING))
{
pMyDlg->PostMessage(WM_MSG,1,1);
return 0;
}
k=0;
j=0;
for(;;)
{
while(PeekMessage(&msg,NULL,0,0,PM_REMOVE)) //消息泵
{
if(msg.message==WM_STOP) //收到退出消息
return 0;
}
if(!WaitCommEvent(pMyDlg->m_myComm.m_hCom,&dwEvent,&OLwait))
{
// k++;
// cstrCount.Format("WaitCommEvent %d\n",k);
// OutputDebugString(cstrCount);
if(x=GetLastError()==ERROR_IO_PENDING)
{

if(WaitForSingleObject(OLwait.hEvent,INFINITE)==WAIT_OBJECT_0) //等500ms
{
ClearCommError(pMyDlg->m_myComm.m_hCom,&dwError,&cs);
if(dwEvent&EV_RING)
OutputDebugString("Found a Ring\n");
if(cs.cbInQue>0 && dwEvent&EV_RXCHAR)
{
j++;
cstrTemp=pMyDlg->m_cstrReceive;
n=pMyDlg->m_myComm.ReadCommBlock(&pMyDlg->m_myComm,(char *)szReadBuf,cs.cbInQue);
pMyDlg->m_cstrReceive.Format ("%s",szReadBuf);
pMyDlg->m_cstrReceive=pMyDlg->m_cstrReceive.Left(n); //取实际读到的字节数的串
pMyDlg->m_cstrReceive=cstrTemp+pMyDlg->m_cstrReceive;
pMyDlg->PostMessage(WM_MSG,0,0);
// cstrCount.Format("ReadCommBlock %d\n",j);
// OutputDebugString(cstrCount);
}
} // WaitForSingleObject()
} // GetLastError()
else
{
cstrCount.Format("WriteEorro %d\n",x);
OutputDebugString(cstrCount);

Sleep(1);
pMyDlg->PostMessage(WM_MSG,1,1);
return 1; //可能是串口错误

}
} // WaitCommEvents()
else
{
Sleep(1);
}
}
return 0;
}
kmilong 2002-05-11
  • 打赏
  • 举报
回复
感觉你真的很好,衷心谢谢你!

我看了您的解释后收获很大,

我是这样理解的,
1。readfile执行之后,它开了一个线程,如果读完了,线程也就结束了,如果没有读完,IO线程挂起。
2。GetOverlappedResult只是一个等待的线程,起延时作用。
3。readfile在这段延时的时间内,又重新读串口,是这样的吗?这个没有任何东西触发它呀,难道它有一个自身定时的循环,只要有时间,就能多次读数据?


初学,没人指导真是痛苦。
非常感谢您,我的信箱kmilong@sohu.com,到时候发信给您!!
qsfsea 2002-05-11
  • 打赏
  • 举报
回复
说得不错,不过GetOverlappedResult()在98、2k下的运行结果可能有些出入。


to qiuanhong(练从难处练,用从易处用) :
帮我看看!
http://www.csdn.net/expert/topic/712/712759.xml?temp=.4088709
qiuanhong 2002-05-11
  • 打赏
  • 举报
回复
"大侠,我始终不明白的一点是,明明readfile已经执行完了,到了GetOverlappedResult,即使它再等也无法再读到未读完的串口数据呀,我的猜想是readfile一直在某一个线程里等待,而GetOverlappedResult触发了它,让它执行,它读完之后,也触发GetOverlappedResult的完成。
"

ReadFile()函数调用成功,则返回值不为0,否则,为0.请看上面第1、2点.
fReadStat = ReadFile(m_hCom, lpszBlock,dwLength, &dwLength, &( m_rdos) ) ;//读串口
if (!fReadStat)
{
//执行到这里,表示读数据还没有完成(不管你读多少数据,当然是由你的dwLength指定),因为你用异步(指定的OVERLAPPED结构)操作读取数据,而异步操作是不等待函数执行完成的。此时系统把OVERLAPPED中的信号事件设为无信号状态,在调用GetOverlappedResult(m_hCom ,&( m_rdos), &dwLength, TRUE )来获取结果时,必须等待到有信号状态。当IO操作完成时,系统把它设置为有信号状态。所以调用GetOverlappedResult(m_hCom ,&( m_rdos), &dwLength, TRUE )才能获得真正读到的结果。

感觉怎样?我也是在学习!!呵呵~~~~~~


qiuanhong 2002-05-11
  • 打赏
  • 举报
回复
仔细体会一下下面的意思:
在设置了异步IO操作后,IO操作和函数返回有以下两种情况:
1.函数返回时IO操作已完成:此时结果好像是同步执行的,但实际上这是异步执行的结果 。
2.函数返回时IO操作还没完成:此时一方面,函数返回值为0,并且GetLastError()函数返回ERROR_IO_PENDING:另一方面,系统把OVERLAPPED中的信号事件设为无信号状态。当IO操作完成时,系统把它设置为有信号状态。
3.异步IO操作可以由GetOverlappedResult()来获取结果,也可以用WINDOWS信号函数来处理。
4.GetOverlappedResult()最后一参数指定函数是否等待挂起的异步操作完成。为1,等待完成后返回,如果为0,同时操作处于挂 起状态,则该函数返回0,并且GetLastError函数返回ERROR_IO_INCOMPLETE.

好了,有什么好的想法,来信告诉我:dnetmaterial@sohu.com

共同学习!
kmilong 2002-05-11
  • 打赏
  • 举报
回复
万分感谢您,分收到了吗?我把我对程序的理解写了一下,请您看对不对?

关于“异步IO事件”的理解不知对不?

fReadStat = ReadFile(m_hCom, lpszBlock,
dwLength, &dwLength, &( m_rdos) ) ;//读串口,假设共有8个子节,我每次读4个,读了一次,没读完,往下走
if (!fReadStat)//pass
{
if (GetLastError() == ERROR_IO_PENDING) //没有读完,pass
{
while(!GetOverlappedResult(m_hCom ,
&( m_rdos), &dwLength, TRUE ))

{
dwError = GetLastError();//这时
//readfile的msdn中又这么一段
//The event specified in the OVERLAPPED structure is set to the
//signaled
//state upon completion of the read operation.这就是“异步IO事
//件”吗?
//我认为这时是无信号状态
if(dwError == ERROR_IO_INCOMPLETE) // 所以pass
continue;// 到了这儿好象还是不能回到ReadFile呀,对了,我这个程序是在一个Timer定时处理函数中的一段代码,但好像形成死循环了呀?请恕我愚笨!
else
{
wsprintf( szError, "<CE-%u>", dwError ) ;
ClearCommError(m_hCom , &dwErrorFlags, &ComStat ) ;
break;
}
}
………..


qiuanhong 2002-05-11
  • 打赏
  • 举报
回复
请看:
http://www.csdn.net/expert/topic/713/713616.xml?temp=.6165277
qiuanhong 2002-05-11
  • 打赏
  • 举报
回复
while(!GetOverlappedResult(m_hCom ,&(m_rdos), &dwLength, TRUE ))
{
dwError = GetLastError();
if(dwError == ERROR_IO_INCOMPLETE)
continue;
else
{
wsprintf( szError, "<CE-%u>", dwError ) ;
ClearCommError(m_hCom , &dwErrorFlags, &ComStat ) ;
break;
}
}
请注意 ERROR_IO_INCOMPLETE 、ERROR_IO_PENDING 的意义:(MSDN里的)
996 Overlapped I/O event is not in a signaled state. ERROR_IO_INCOMPLETE
997 Overlapped I/O operation is in progress. ERROR_IO_PENDING

通过上面对ERROR_IO_INCOMPLETE的意思可知,在这个while()循环中,调用GetOverlappedResult()函数来获取实际的读取的字符数时,直到异步IO事件有效时才break;否则(无效时:即为ERROR_IO_INCOMPLETE时)继续等待。

上午没有看清你的层次结构,误解了,不好意思。
一句话,就是等待异步IO信号有效,以通过GetOverlappedResult()函数获取实际的读取的字符数。。。。

16,548

社区成员

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

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

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