串口超时问题

zhanguo77 2011-08-04 06:14:04
求教,串口超时问题怎么处理。
我如果在read()函数前面设置一个对话框AfxMessageBox("read");,缓冲一下时间,就能读到数据。
如果不设置这个对话框,就读不到数据。
我Write()的字符串长度是10左右,Read()的字符串长度是90左右。

下面是我串口的时间设置简略代码,求教如何设置时间才能有效读取数据。

BOOL CSerial::Open(int PortName)
{
COMMTIMEOUTS CommTimeOuts;
CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
CommTimeOuts.ReadTotalTimeoutConstant = 0;
CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
CommTimeOuts.WriteTotalTimeoutConstant = 5000;
SetCommTimeouts( m_hIDComDev, &CommTimeOuts );
}
int CSerial::ReadDataWaiting( void )
{

if( !m_bOpened || m_hIDComDev == NULL ) return( 0 );

DWORD dwErrorFlags;
COMSTAT ComStat;

ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat );
//AfxMessageBox("wait is ok");

/*CString co;
co.Format("%d",ComStat.cbInQue);
AfxMessageBox(co);*/
return( (int) ComStat.cbInQue );

}
...全文
529 24 打赏 收藏 转发到动态 举报
写回复
用AI写文章
24 条回复
切换为时间正序
请发表友善的回复…
发表回复
一条晚起的虫 2011-08-09
  • 打赏
  • 举报
回复
ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat );
if( !ComStat.cbInQue ) return( 0 );
// 这个,如果当时缓冲区没有数据,不是直接返回了?
// 既然是同步的,直接ReadFile等在那里不行吗?
// CommTimeOuts.ReadIntervalTimeout 这个设置的长些。
// ReadFile之后再去判断 cbInQue,如果还有,再读。
hill8006 2011-08-05
  • 打赏
  • 举报
回复
判断完成:
do
{
bReadStatus = ReadFile( m_hIDComDev, buffer, 1, &dwBytesRead, &m_OverlappedRead );
Sleep(1);
}while( dwBytesRead ==1);

dwBytesRead=0时肯定就没数了~~~~
当然不排除极端情况,比如波特率特低,等待1ms的过程中都不会发一个字节……你可以加大sleep数
hill8006 2011-08-05
  • 打赏
  • 举报
回复
发送是要时间的,返回也要时间,你刚发完肯定收不到数据
你可以发送完成后开启一个定时器,在定时器中完成读取。
或者你直接加个Sleep吧,比较呆板点……
zhanguo77 2011-08-05
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 hezhe1008 的回复:]

读数据时候用个while
里边判断数据缓冲区size
[/Quote]

用什么方法能判断数据已经接受完毕,因为数据是90左右,不是一个定数。
zgl7903 2011-08-05
  • 打赏
  • 举报
回复
看看MSDN帮助
Serial Communications
zhanguo77 2011-08-05
  • 打赏
  • 举报
回复
[Quote=引用 5 楼 hezhe1008 的回复:]

读数据时候用个while
里边判断数据缓冲区size
[/Quote]

用while判断,当数据为90时,结束,否则继续读取??
是这个意思吗?
呔妖怪来嘛 2011-08-05
  • 打赏
  • 举报
回复
读数据时候用个while
里边判断数据缓冲区size
zhanguo77 2011-08-05
  • 打赏
  • 举报
回复
把代码贴全,高手们多多指教啊。

BOOL CSerial::Open(int PortName)
{
if( m_bOpened ) return( TRUE );

char szPort[15];
char szComParams[50];
DCB dcb;

wsprintf( szPort, "COM%d", PortName );
m_hIDComDev = CreateFile( szPort,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL );
if(m_hIDComDev == INVALID_HANDLE_VALUE)
{
return( FALSE );
}
else
{
memset( &m_OverlappedRead, 0, sizeof( OVERLAPPED ) );
memset( &m_OverlappedWrite, 0, sizeof( OVERLAPPED ) );

COMMTIMEOUTS CommTimeOuts;
CommTimeOuts.ReadIntervalTimeout = 10;
CommTimeOuts.ReadTotalTimeoutMultiplier = 1;
CommTimeOuts.ReadTotalTimeoutConstant = 1000;
CommTimeOuts.WriteTotalTimeoutMultiplier = 100;
CommTimeOuts.WriteTotalTimeoutConstant = 5000;
SetCommTimeouts( m_hIDComDev, &CommTimeOuts );

wsprintf( szComParams, "COM%d:%d,2,8,1", PortName, BAUDRATE );

m_OverlappedRead.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
m_OverlappedWrite.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );

dcb.DCBlength = sizeof( DCB );
GetCommState( m_hIDComDev, &dcb );
dcb.BaudRate = BAUDRATE;
dcb.ByteSize = 8;
unsigned char ucSet;
ucSet = (unsigned char) ( ( FC_RTSCTS & FC_DTRDSR ) != 0 );
ucSet = (unsigned char) ( ( FC_RTSCTS & FC_RTSCTS ) != 0 );
ucSet = (unsigned char) ( ( FC_RTSCTS & FC_XONXOFF ) != 0 );

if( !SetCommState( m_hIDComDev, &dcb ) ||
!SetupComm( m_hIDComDev, 10000, 10000 ) ||
m_OverlappedRead.hEvent == NULL ||
m_OverlappedWrite.hEvent == NULL )
{
DWORD dwError = GetLastError();
if( m_OverlappedRead.hEvent != NULL ) CloseHandle( m_OverlappedRead.hEvent );
if( m_OverlappedWrite.hEvent != NULL ) CloseHandle( m_OverlappedWrite.hEvent );
CloseHandle( m_hIDComDev );
AfxMessageBox("close is ok");
return( FALSE );
}
CSerial::PortNo = PortName;
m_bOpened = TRUE;
return( m_bOpened );
}
}

BOOL CSerial::WriteCommByte(char Date[],int wLength)
{
if( !m_bOpened || m_hIDComDev == NULL ) return( 0 );
BOOL bWriteStat;
DWORD dwBytesWritten=0;
bWriteStat = WriteFile( m_hIDComDev,Date, wLength, &dwBytesWritten, &m_OverlappedWrite );
if( !bWriteStat && ( GetLastError() == ERROR_IO_PENDING ) ){
if( WaitForSingleObject( m_OverlappedWrite.hEvent, 1000 ) ) dwBytesWritten = 0;
else{
GetOverlappedResult( m_hIDComDev, &m_OverlappedWrite, &dwBytesWritten, FALSE );
m_OverlappedWrite.Offset += dwBytesWritten;
}
}
//AfxMessageBox("write is ok",MB_OK);
return( TRUE );
}

int CSerial::ReadDataWaiting( void )
{
if( !m_bOpened || m_hIDComDev == NULL ) return( 0 );
DWORD dwErrorFlags;
COMSTAT ComStat;
ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat );
AfxMessageBox("wait is ok");
return( (int) ComStat.cbInQue );
}

int CSerial::ReadData(int limit,int x,int y,int z)
{
if( !m_bOpened || m_hIDComDev == NULL ) return( 0 );

BOOL bReadStatus;
DWORD dwBytesRead;
DWORD dwErrorFlags;
COMSTAT ComStat;

char buffer[100]={0};
int rLength = limit;

ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat );
if( !ComStat.cbInQue ) return( 0 );

dwBytesRead = (DWORD) ComStat.cbInQue;
if( limit < (int) dwBytesRead ) dwBytesRead = (DWORD) limit;

bReadStatus = ReadFile( m_hIDComDev, buffer, rLength, &dwBytesRead, &m_OverlappedRead );
if( !bReadStatus ){
if( GetLastError() == ERROR_IO_PENDING ){
WaitForSingleObject( m_OverlappedRead.hEvent, 2000 );
return( (int) dwBytesRead );
}
return( 0 );
}
}
zhanguo77 2011-08-05
  • 打赏
  • 举报
回复
把代码贴全,高手们多多指教啊。

BOOL CSerial::Open(int PortName)
{
if( m_bOpened ) return( TRUE );

char szPort[15];
char szComParams[50];
DCB dcb;

wsprintf( szPort, "COM%d", PortName );
m_hIDComDev = CreateFile( szPort,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED,
NULL );
if(m_hIDComDev == INVALID_HANDLE_VALUE)
{
return( FALSE );
}
else
{
memset( &m_OverlappedRead, 0, sizeof( OVERLAPPED ) );
memset( &m_OverlappedWrite, 0, sizeof( OVERLAPPED ) );

COMMTIMEOUTS CommTimeOuts;
CommTimeOuts.ReadIntervalTimeout = 10;
CommTimeOuts.ReadTotalTimeoutMultiplier = 1;
CommTimeOuts.ReadTotalTimeoutConstant = 1000;
CommTimeOuts.WriteTotalTimeoutMultiplier = 100;
CommTimeOuts.WriteTotalTimeoutConstant = 5000;
SetCommTimeouts( m_hIDComDev, &CommTimeOuts );

wsprintf( szComParams, "COM%d:%d,2,8,1", PortName, BAUDRATE );

m_OverlappedRead.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
m_OverlappedWrite.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );

dcb.DCBlength = sizeof( DCB );
GetCommState( m_hIDComDev, &dcb );
dcb.BaudRate = BAUDRATE;
dcb.ByteSize = 8;
unsigned char ucSet;
ucSet = (unsigned char) ( ( FC_RTSCTS & FC_DTRDSR ) != 0 );
ucSet = (unsigned char) ( ( FC_RTSCTS & FC_RTSCTS ) != 0 );
ucSet = (unsigned char) ( ( FC_RTSCTS & FC_XONXOFF ) != 0 );

if( !SetCommState( m_hIDComDev, &dcb ) ||
!SetupComm( m_hIDComDev, 10000, 10000 ) ||
m_OverlappedRead.hEvent == NULL ||
m_OverlappedWrite.hEvent == NULL )
{
DWORD dwError = GetLastError();
if( m_OverlappedRead.hEvent != NULL ) CloseHandle( m_OverlappedRead.hEvent );
if( m_OverlappedWrite.hEvent != NULL ) CloseHandle( m_OverlappedWrite.hEvent );
CloseHandle( m_hIDComDev );
AfxMessageBox("close is ok");
return( FALSE );
}
CSerial::PortNo = PortName;
m_bOpened = TRUE;
return( m_bOpened );
}
}

BOOL CSerial::WriteCommByte(char Date[],int wLength)
{
if( !m_bOpened || m_hIDComDev == NULL ) return( 0 );
BOOL bWriteStat;
DWORD dwBytesWritten=0;
bWriteStat = WriteFile( m_hIDComDev,Date, wLength, &dwBytesWritten, &m_OverlappedWrite );
if( !bWriteStat && ( GetLastError() == ERROR_IO_PENDING ) ){
if( WaitForSingleObject( m_OverlappedWrite.hEvent, 1000 ) ) dwBytesWritten = 0;
else{
GetOverlappedResult( m_hIDComDev, &m_OverlappedWrite, &dwBytesWritten, FALSE );
m_OverlappedWrite.Offset += dwBytesWritten;
}
}
//AfxMessageBox("write is ok",MB_OK);
return( TRUE );
}

int CSerial::ReadDataWaiting( void )
{
if( !m_bOpened || m_hIDComDev == NULL ) return( 0 );
DWORD dwErrorFlags;
COMSTAT ComStat;
ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat );
AfxMessageBox("wait is ok");
return( (int) ComStat.cbInQue );
}

int CSerial::ReadData(int limit,int x,int y,int z)
{
if( !m_bOpened || m_hIDComDev == NULL ) return( 0 );

BOOL bReadStatus;
DWORD dwBytesRead;
DWORD dwErrorFlags;
COMSTAT ComStat;

char buffer[100]={0};
int rLength = limit;

ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat );
if( !ComStat.cbInQue ) return( 0 );

dwBytesRead = (DWORD) ComStat.cbInQue;
if( limit < (int) dwBytesRead ) dwBytesRead = (DWORD) limit;

bReadStatus = ReadFile( m_hIDComDev, buffer, rLength, &dwBytesRead, &m_OverlappedRead );
if( !bReadStatus ){
if( GetLastError() == ERROR_IO_PENDING ){
WaitForSingleObject( m_OverlappedRead.hEvent, 2000 );
return( (int) dwBytesRead );
}
return( 0 );
}
}
zhanguo77 2011-08-05
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 vcf_reader 的回复:]

串口读数据是要死读的。并不是你想读的时候就正好有数据。
[/Quote]

什么意思,说的详细点
都需要什么设置,新手请指点
zhanguo77 2011-08-05
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 hill8006 的回复:]

引用 11 楼 zhanguo77 的回复:
引用 9 楼 hill8006 的回复:

判断完成:
do
{
bReadStatus = ReadFile( m_hIDComDev, buffer, 1, &amp;amp;dwBytesRead, &amp;amp;m_OverlappedRead );
Sleep(1);
}while( dwBytesRea……
[/Quote]

我这样做不行,接受丢数据
zhanguo77 2011-08-05
  • 打赏
  • 举报
回复
[Quote=引用 19 楼 hill8006 的回复:]

为了满足Sleep(1)之后肯定能读到数……
当然也可以通过读取缓冲区有多少个字节来判断
相对来说高波特率 后者更省时间
[/Quote]

请指教缓冲器,具体是指哪里?那个变量?还是串口的硬件?
hill8006 2011-08-05
  • 打赏
  • 举报
回复
为了满足Sleep(1)之后肯定能读到数……
当然也可以通过读取缓冲区有多少个字节来判断
相对来说高波特率 后者更省时间
zhanguo77 2011-08-05
  • 打赏
  • 举报
回复
[Quote=引用 15 楼 hill8006 的回复:]

而且
ReadFile( m_hIDComDev, buffer, 1, &amp;amp;amp;dwBytesRead, &amp;amp;amp;m_OverlappedRead
只读取一个字节
肯定为1的!
红色mark的1
[/Quote]
为什么要一次接受一个字节呢,我设定的是rLength=90,一次接受90个自己,你看我的代码
readfile函数就执行一次,这样是不是很不好。
请求详细讲解,新手求教
zhanguo77 2011-08-05
  • 打赏
  • 举报
回复
[Quote=引用 16 楼 yuncjxxc 的回复:]

读数据时候用个while
里边判断数据缓冲区size
[/Quote]

while(数据缓冲区size!=0)
{read()}
是这个意思吗?
数据缓冲区在哪里,我是新手,很多东西不知道,我你看看我的代码里,那个是数据缓冲区,拜托了
YUNCJXXC 2011-08-05
  • 打赏
  • 举报
回复
读数据时候用个while
里边判断数据缓冲区size
hill8006 2011-08-05
  • 打赏
  • 举报
回复
而且
ReadFile( m_hIDComDev, buffer, 1, &amp;amp;dwBytesRead, &amp;amp;m_OverlappedRead
只读取一个字节
肯定为1的!
红色mark的1
hill8006 2011-08-05
  • 打赏
  • 举报
回复
while( dwBytesRead < 1)
zhanguo77 2011-08-05
  • 打赏
  • 举报
回复
[Quote=引用 12 楼 hill8006 的回复:]

引用 11 楼 zhanguo77 的回复:
引用 9 楼 hill8006 的回复:

判断完成:
do
{
bReadStatus = ReadFile( m_hIDComDev, buffer, 1, &amp;amp;dwBytesRead, &amp;amp;m_OverlappedRead );
Sleep(1);
}while( dwBytesRea……
[/Quote]

我没有做循环,只用了一次
bReadStatus = ReadFile( m_hIDComDev, buffer, rLength, &dwBytesRead, &m_OverlappedRead );
是一次接受一个字符串,你那个是一次接受一个字节吗?
那如果我一次接受了2个字节,dwBytesRead !=1
那岂不是也要跳出循环了
hill8006 2011-08-05
  • 打赏
  • 举报
回复
[Quote=引用 11 楼 zhanguo77 的回复:]
引用 9 楼 hill8006 的回复:

判断完成:
do
{
bReadStatus = ReadFile( m_hIDComDev, buffer, 1, &amp;dwBytesRead, &amp;m_OverlappedRead );
Sleep(1);
}while( dwBytesRead ==1);

dwBytesRead=0时肯定就没数了~~……
[/Quote]
当你接收到第一个数据开始,之后的时间间隔就是程序段里面Sleep所需要保证的时间,保证Sleep的这个时间段肯定有数据
还不放心就在接收完后再尝试接收一次
在我的程序中这么用一直运行正常……
加载更多回复(3)

2,641

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 硬件/系统
社区管理员
  • 硬件/系统社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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