100分求助:为什么我的程序停不下来----关于串口通讯

jiju 2002-03-09 08:40:58
我打开一个COM口,WRITEFILE正常,但是,读文件时。。。
我启动一个线程来读COM口收到的字符,
创建COM口如下
m_hCom1 = CreateFile("COM1",GENERIC_READ | GENERIC_WRITE ,
0, NULL, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED , NULL);

并设有事件HANDLE g_Event[3]均已指向创建好的OVERLAPPED 结构的事件
有SetCommMask(m_hCom, EV_RXCHAR);

现在我把如下语句嵌套在CMyThread的RUN函数的循环里
DWORD SE = WaitForMultipleObjects(3,g_Event,false,)
case se of
0 :
COMSTAT ComStat;
DWORD dwErrorFlags;
ClearCommError(m_hCom,&dwErrorFlags,&ComStat);:
writefile(m_hCom1,...);
。。。
但是,程序却在waitForMultipliObjects语句上不停;se 的值一直是一个很大的数,并且不会变,
更怪的是用WaitForSingleObject()会永远停下来,就是不能接受信号
程序作在一个.dll里
望各位高手给予指点:万分感谢
...全文
51 11 打赏 收藏 转发到动态 举报
写回复
用AI写文章
11 条回复
切换为时间正序
请发表友善的回复…
发表回复
jiju 2002-03-13
  • 打赏
  • 举报
回复
解决了,难为各位了,程序因为定义了一个全局的static变量,在主线程和辅线程中会变成两个,主辅线程各操纵一个,所以到WaitForMultipleObjects(3,g_Event,false,INFINITE)时g_Event虽然在主线程中附了值,现在却是NULL
所以停不下来。

感谢各位提供的帮助,分数嘛,只有平均分配了。
HuWenjin 2002-03-11
  • 打赏
  • 举报
回复


// Send the Datas.
// 写数据到串口
BOOL CSaimIO::WriteToCom(unsigned char *lpCommand, DWORD dwBytesToWrite)
{
if (IoInfoData.fConnected == FALSE )
return ( FALSE ) ;

//等到串口已可用
if( m_hComMutex )
::WaitForSingleObject(m_hComMutex,INFINITE);

BOOL fWriteStat ;
DWORD dwBytesWritten ;
DWORD dwErrorFlags;
DWORD dwError;
DWORD dwBytesSent=0;
COMSTAT ComStat;
char szError[ 128 ] ;

fWriteStat = WriteFile( IoInfoData.idComDev , lpCommand, dwBytesToWrite,
&dwBytesWritten,NULL) ; // &IoInfoData.osWrite ) ;

if(dwBytesWritten != dwBytesToWrite)
return FALSE;

if (!fWriteStat)
{
if(GetLastError() == ERROR_IO_PENDING)
{
while(!GetOverlappedResult( IoInfoData.idComDev ,
&IoInfoData.osWrite, &dwBytesWritten, TRUE ))
{
dwError = GetLastError();
if(dwError == ERROR_IO_INCOMPLETE)
{
// normal result if not finished
dwBytesSent += dwBytesWritten;
continue;
}
else
{
// an error occurred, try to recover
wsprintf( szError, "向串口发送数据出错,错误代码: %u", dwError ) ;

MessageBox(NULL,szError,"发送数据出错",MB_ICONEXCLAMATION);

ClearCommError( IoInfoData.idComDev , &dwErrorFlags, &ComStat ) ;

break;
}
}
}
else
{
// some other error occurred
ClearCommError( IoInfoData.idComDev , &dwErrorFlags, &ComStat ) ;

if (dwErrorFlags > 0)
{
wsprintf( szError, "向串口发送数据出错,错误代码: %u", dwErrorFlags ) ;

MessageBox(NULL,szError,"发送数据出错",MB_ICONEXCLAMATION);
}

//完成使用串口,释放串口
::ReleaseMutex(m_hComMutex);
return ( FALSE );
}
}

//完成使用串口,释放串口
if( m_hComMutex )
::ReleaseMutex(m_hComMutex);

return ( TRUE ) ;

}



// Read the Datas.
// 从串口中读出数据,DataBuffer 接收缓冲, DataLength 要接收的数据长度
DWORD CSaimIO::GetData(unsigned char *DataBuffer, DWORD DataLength)
{
if (IoInfoData.fConnected == FALSE)
return ( FALSE ) ;

//等到串口已可用
if( m_hComMutex )
::WaitForSingleObject(m_hComMutex,INFINITE);

BOOL fReadStat ;
COMSTAT ComStat ;
DWORD dwErrorFlags;
DWORD dwLength = DataLength;
DWORD dwError;
char szError[ 128 ] ;

// only try to read number of bytes in queue
ClearCommError( IoInfoData.idComDev, &dwErrorFlags, &ComStat ) ;
//dwLength = min( DataLength, ComStat.cbInQue ) ;
//和下面的 ReadFile( ... dwLength,&dwLength, ...); 对应
//读出串口中已有的数据但不等待还没有收到的数据
//适用于读出不完整的数据到缓冲中,其它部分来完成数据拼合和清空
if( ComStat.cbInQue == 0 )
{
//完成使用串口,释放串口
if( m_hComMutex )
::ReleaseMutex(m_hComMutex);
return 0 ;
}

if (dwLength > 0)
{
//读出串口中的已有的数据
//fReadStat = ReadFile( IoInfoData.idComDev, DataBuffer,
// dwLength, &dwLength, &IoInfoData.osRead );

//读出指定的数据,在指定的溢出时间内如果没有读出则只读出串口中已存在的数据
fReadStat = ReadFile( IoInfoData.idComDev, DataBuffer,
DataLength, &dwLength, &IoInfoData.osRead );
if (!fReadStat)
{
if (GetLastError() == ERROR_IO_PENDING)
{
// We have to wait for read to complete.
// This function will timeout according to the
// CommTimeOuts.ReadTotalTimeoutConstant variable
// Every time it times out, check for port errors
while(!GetOverlappedResult( IoInfoData.idComDev,
&IoInfoData.osRead, &dwLength, TRUE ))
{
dwError = GetLastError();
if(dwError == ERROR_IO_INCOMPLETE)
// normal result if not finished
continue;
else
{
// an error occurred, try to recover
wsprintf( szError, "向串口读出数据出错,错误代码: %u", dwError ) ;

MessageBox(NULL,szError,"读出数据出错",MB_ICONEXCLAMATION);

ClearCommError( IoInfoData.idComDev, &dwErrorFlags, &ComStat ) ;
if (dwErrorFlags > 0)
{
wsprintf( szError, "向串口读出数据出错,错误代码: %u", dwError ) ;

MessageBox(NULL,szError,"读出数据出错",MB_ICONEXCLAMATION);
}
break;
}
}
}
else
{
// some other error occurred
dwLength = 0 ;
ClearCommError( IoInfoData.idComDev, &dwErrorFlags, &ComStat ) ;
if (dwErrorFlags > 0 )
{
wsprintf( szError, "向串口读出数据出错,错误代码: %u", dwErrorFlags ) ;

MessageBox(NULL,szError,"读出数据出错",MB_ICONEXCLAMATION);
}
}
}
}

//完成使用串口,释放串口
if( m_hComMutex )
::ReleaseMutex(m_hComMutex);
return ( dwLength ) ;
}

读出串口的数据长度部分还可以修改一下
老本都给你了不给分就?????
HuWenjin 2002-03-11
  • 打赏
  • 举报
回复
没时间看你的程式用我代码我想应可以解决所有的东西都不要改




// 以默认方式初始化串口
void CSaimIO::InitaiseIO()
{
IoInfoData.idComDev = 0 ;
IoInfoData.bByteSize = 8 ;
IoInfoData.fConnected = FALSE;
IoInfoData.bPort = 1 ;
IoInfoData.dwBaudRate = CBR_9600;
IoInfoData.bFlowCtrl = FALSE; //FC_XONXOFF; // FC_RTSCTS; //FC_XONXOFF;
IoInfoData.fXonXoff = 0 ;
IoInfoData.bParity = NOPARITY; // EVENPARITY ;MARKPARITY ; SPACEPARITY; ODDPARITY;
IoInfoData.bStopBits = ONESTOPBIT; //ONE5STOPBITS; TWOSTOPBITS
IoInfoData.osWrite.Offset = 0;
IoInfoData.osWrite.OffsetHigh = 0;
IoInfoData.osRead.Offset = 0;
IoInfoData.osRead.OffsetHigh = 0;
IoInfoData.osRead.hEvent = NULL;
IoInfoData.osWrite.hEvent = NULL;
}


// Connect IO before use it.
// 打开串开
BOOL CSaimIO::Connect()
{
BOOL fRetVal ;
BYTE bSet ;
DCB dcb ;
char szPort[10];

memset(szPort,0,10);

wsprintf(szPort,"COM%d:",IoInfoData.bPort);


IoInfoData.idComDev = CreateFile(szPort,GENERIC_READ|GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
NULL);

if( !IoInfoData.idComDev )
return FALSE;

if(!SetCommMask(IoInfoData.idComDev,EV_RXFLAG)) // EV_RXCHAR))
return FALSE;

// Alloc the buffer for Read and Write.
if( SetupComm(IoInfoData.idComDev,4096,4096) == 0 )
return FALSE;


//Setup for overlapped I/O
COMMTIMEOUTS CommTimesOuts;

if( IoInfoData.dwBaudRate == CBR_2400 ||
IoInfoData.dwBaudRate == CBR_1200 ||
IoInfoData.dwBaudRate == CBR_300 ||
IoInfoData.dwBaudRate == CBR_110 )
{
// 读取溢出时间 = 要读取的字节 * 放大因子 + 固定时间
// Bin 码每个BIN 间的时间允许为 30 ms , 在此设定为 50 ms , 超过该时间说明读取完成
CommTimesOuts.ReadIntervalTimeout = 50;
// 时间放大因子
CommTimesOuts.ReadTotalTimeoutMultiplier = 10 ;
// 固定时间,
CommTimesOuts.ReadTotalTimeoutConstant = 1000 ;

}
else
{
// 读取溢出时间 = 要读取的字节 * 放大因子 + 固定时间
// Bin 码每个BIN 间的时间允许为 30 ms , 在此设定为 100 ms , 超过该时间说明读取完成
CommTimesOuts.ReadIntervalTimeout = 30;
// 时间放大因子
CommTimesOuts.ReadTotalTimeoutMultiplier = 8 ;
// 固定时间,
CommTimesOuts.ReadTotalTimeoutConstant = 100 ;
}

// 写数据溢出时间 = 要写入的字节 * 放大因子 + 固定时间
CommTimesOuts.WriteTotalTimeoutMultiplier = 2*CBR_9600 / IoInfoData.dwBaudRate ;
CommTimesOuts.WriteTotalTimeoutConstant = 50;

SetCommTimeouts(IoInfoData.idComDev,&CommTimesOuts);


// Initise the com port.
dcb.DCBlength = sizeof( DCB ) ;

GetCommState( IoInfoData.idComDev, &dcb ) ;

dcb.BaudRate = IoInfoData.dwBaudRate ;
dcb.ByteSize = IoInfoData.bByteSize ;
dcb.Parity = IoInfoData.bParity ;
dcb.StopBits = IoInfoData.bStopBits ;

// setup hardware flow control

bSet = (BYTE) ((FC_RTSCTS & FC_DTRDSR) != 0) ;
dcb.fOutxDsrFlow = bSet ;

dcb.fDtrControl = DTR_CONTROL_DISABLE ; //给予提供电源 ,新的 485 就不需要提供
dcb.fRtsControl = RTS_CONTROL_ENABLE ;

bSet = (BYTE) FC_RTSCTS ;
dcb.fOutxCtsFlow = bSet ;


// setup software flow control

bSet = (BYTE) FC_XONXOFF ;

dcb.fInX = dcb.fOutX = bSet ;
dcb.XonChar = ASCII_XON ;
dcb.XoffChar = ASCII_XOFF ;
dcb.XonLim = 100 ;
dcb.XoffLim = 100 ;

// other various settings

dcb.fBinary = TRUE ;
dcb.fParity = 1 ; // Enalble Parity

fRetVal = SetCommState( IoInfoData.idComDev, &dcb ) ;

if( fRetVal != FALSE )
IoInfoData.fConnected = TRUE;
else
return fRetVal;

//Ceate I/O event used for overlapped reads / writes
IoInfoData.osRead.hEvent = CreateEvent( NULL , //no security
TRUE , //explicit reset req
FALSE , //initial event reset
NULL); //no name

if( IoInfoData.osRead.hEvent == NULL )
{
return FALSE;
}

IoInfoData.osWrite.hEvent = CreateEvent( NULL , //no security
TRUE , //explicit reset req
FALSE , //initial event reset
NULL); //no name

if( IoInfoData.osWrite.hEvent == NULL )
{
CloseHandle( IoInfoData.osRead.hEvent );
return FALSE;
}

// Clear Read and Send IO buffer
if(PurgeComm(IoInfoData.idComDev,PURGE_RXCLEAR)== 0)
return FALSE;
if(PurgeComm(IoInfoData.idComDev,PURGE_TXCLEAR)== 0)
return FALSE;

// Set The DataSet is ready TO Get Data
EscapeCommFunction(IoInfoData.idComDev,SETDTR|SETRTS);

// Set Connected flag to TRUE
IoInfoData.fConnected = TRUE ;


if( IoInfoData.dwBaudRate == CBR_4800 ||
IoInfoData.dwBaudRate == CBR_2400 ||
IoInfoData.dwBaudRate == CBR_1200 ||
IoInfoData.dwBaudRate == CBR_300 ||
IoInfoData.dwBaudRate == CBR_110 )
{
m_bHighSpeed = FALSE ;
//BeginComProc();
}
else
{
m_bHighSpeed = TRUE ;
}

//创建串口信号量
if( !m_hComMutex )
m_hComMutex = ::CreateMutex(NULL,FALSE,NULL);

return ( TRUE ) ;
}

delphihero 2002-03-11
  • 打赏
  • 举报
回复
我觉得你应该在
DWORD SE = WaitForMultipleObjects(3,g_Event,false,INFINITE);//INFINITE 如果没有事件一直等待
之前加上
BOOL bResult;
DWORD Event;
bResult=WaitCommEvent(m_hCom,&Event,&m_overlappedRead);//如果有你的SetCommMask(..)设的事件,WaitCommEvent 会把m_overlappedRead 的hEvent 复位为信号状态,否则为非信号状态.
honeycombs 2002-03-11
  • 打赏
  • 举报
回复
这位大哥请到:
http://www.ht.com.cn/download/moxa/pcommpro/pcommpro.htm
jiju 2002-03-10
  • 打赏
  • 举报
回复
To: joyu(佳友) ,我也下过此段程序
但是,我觉得我所有的事都做了,还是不会停,各位没有遇到过吗?
以下是我的部分程序
m_ComHandle = CreateFile(Lpcom,GENERIC_READ|GENERIC_WRITE,
0,0,OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED ,NULL);
if(m_ComHandle==NULL)
{
……
}

SetupComm(m_ComHandle,Rbuf,Wbuf);//Rbuf和Wbuf默认1024

SetTimeOut(ReadIntervalTimeout,ReadTotalTimeoutConstant,ReadTotalTimeoutMultiplier,WriteTotalTimeoutConstant,WriteTotalTimeoutMultiplier);// 自定义函数
SetDCB(););// (1)自定义函数在下面

PurgeComm(m_ComHandle, PURGE_RXABORT|PURGE_RXCLEAR|PURGE_TXABORT|PURGE_TXCLEAR );
SetCommMask(m_ComHandle,m_dwEvtMask);//m_dwEvtMask定义为EV_RXCHAR


//(1):
void CComm::SetDCB()
{
m_dwEvtMask=0;
Init_OVERLAPPEN();
///////////////////////////////
GetCommState(m_ComHandle,&m_Dcb);
m_Dcb.BaudRate=9600;
m_Dcb.ByteSize=8;
m_Dcb.Parity=NOPARITY;
m_Dcb.StopBits=TWOSTOPBITS;
m_Dcb.fRtsControl = RTS_CONTROL_ENABLE;
if (!SetCommState(m_ComHandle,&m_Dcb))
{
DWORD err=GetLastError();
GetError(err);
AfxMessageBox("SetDcb error!");
}
}

bool CComm::Init_OVERLAPPEN()//m_osRead和m_osWrite为类成员,
//g_Event[4]和sum为全局static变量,
{
//memset

m_osRead.Internal=5000;
m_osRead.InternalHigh=1000;
m_osRead.Offset=5000;
m_osRead.OffsetHigh=5000;
if((m_osRead.hEvent = CreateEvent(NULL,false,false,NULL))==NULL)
{
return false;
AfxMessageBox("createeventR error!");
}
event[g_sum]=m_osRead.hEvent;
//ResetEvent(
g_sum++;
m_osWrite.Internal=5000;
m_osWrite.InternalHigh=5000;
m_osWrite.Offset=5000;
m_osWrite.OffsetHigh=5000;
if((m_osWrite.hEvent = CreateEvent(NULL,false,false,NULL))==NULL)
{
return false;
AfxMessageBox("createeventW error!");
}
event[g_sum]=m_osWrite.hEvent;
g_sum++;
return true;

}

////////////////////////////////////////
【不会停】
for(;;){
E=WaitForMultipleObjects(4,event,false,INFINITE);
if(E!=0)
comX.ReadCombuf(p,q);
else
{
……
}//comX.GetError(GetLastError());
}
joyu 2002-03-10
  • 打赏
  • 举报
回复
看看下面这段程序,对你可能有帮助:
BOOL CSerial::Open( int nPort, int nBaud )
{
if( m_bOpened ) return( TRUE );

char szPort[15];
DCB dcb;

wsprintf( szPort, "COM%d", nPort );
m_hComDev = CreateFile( szPort, GENERIC_READ | GENERIC_WRITE, 0, NULL,

OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL );
if( m_hComDev == NULL ) return( FALSE );

memset( &m_OverlappedRead, 0, sizeof( OVERLAPPED ) );
memset( &m_OverlappedWrite, 0, sizeof( OVERLAPPED ) );

COMMTIMEOUTS CommTimeOuts;
CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
CommTimeOuts.ReadTotalTimeoutConstant = 0;
CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
CommTimeOuts.WriteTotalTimeoutConstant = 5000;
SetCommTimeouts( m_hComDev, &CommTimeOuts );

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

dcb.DCBlength = sizeof( DCB );
GetCommState( m_hComDev, &dcb );
dcb.BaudRate = nBaud;
dcb.ByteSize = 8;
if( !SetCommState( m_hComDev, &dcb ) ||
!SetupComm( m_hComDev, 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_hComDev );
return FALSE;
}

m_bOpened = TRUE;

return m_bOpened;

}

int CSerial::InBufferCount( void )
{

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

DWORD dwErrorFlags;
COMSTAT ComStat;

ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat );

return (int)ComStat.cbInQue;

}

DWORD CSerial::ReadData( void *buffer, DWORD dwBytesRead)
{

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

BOOL bReadStatus;
DWORD dwErrorFlags;
COMSTAT ComStat;

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

dwBytesRead = min(dwBytesRead,(DWORD) ComStat.cbInQue);

bReadStatus = ReadFile( m_hComDev, buffer, dwBytesRead, &dwBytesRead,

&m_OverlappedRead );
if( !bReadStatus ){
if( GetLastError() == ERROR_IO_PENDING ){
WaitForSingleObject( m_OverlappedRead.hEvent, 2000 );
return dwBytesRead;
}
return 0;
}

return dwBytesRead;

}

DWORD CSerial::SendData( const char *buffer, DWORD dwBytesWritten)
{

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

BOOL bWriteStat;

bWriteStat = WriteFile( m_hComDev, buffer, dwBytesWritten, &dwBytesWritten,

&m_OverlappedWrite );
if( !bWriteStat){
if ( GetLastError() == ERROR_IO_PENDING ) {
WaitForSingleObject( m_OverlappedWrite.hEvent, 1000 );
return dwBytesWritten;
}
return 0;
}
return dwBytesWritten;

}

MeKing 2002-03-10
  • 打赏
  • 举报
回复
There are two interesting side effects of SetCommMask and WaitCommEvent. First, if the communications port is open for nonoverlapped operation, WaitCommEvent will be blocked until an event occurs. If another thread calls SetCommMask to set a new event mask, that thread will be blocked on the call to SetCommMask. The reason is that the original call to WaitCommEvent in the first thread is still executing. The call to SetCommMask blocks the thread until the WaitCommEvent function returns in the first thread. This side effect is universal for ports open for nonoverlapped I/O. If a thread is blocked on any communications function and another thread calls a communications function, the second thread is blocked until the communications function returns in the first thread. The second interesting note about these functions is their use on a port open for overlapped operation. If SetCommMask sets a new event mask, any pending WaitCommEvent will complete successfully, and the event mask produced by the operation is NULL.
jiju 2002-03-10
  • 打赏
  • 举报
回复
调用getlasterror后,用FormatMessage() 没有返回的东西
g_Event 在查看地址时均有效
cm_w 2002-03-09
  • 打赏
  • 举报
回复
估计你的程序中waitForMultipliObjects返回的值是WAIT_FAILED(0XFFFFFFFF).调用getlasterror可以获得进一步的信息.最大的可能是g_Event中有无效的句柄.
JerryGR 2002-03-09
  • 打赏
  • 举报
回复
关注

16,472

社区成员

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

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

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