再请教大侠
我在百度上找了个串口发送和接受的例子:
for(;;)
{
bResult = ::ClearCommError(hComm,&dwError,&comstat);
if(comstat.cbInQue == 0)
continue;
//if(!::SetCommMask(hComm,EV_RXCHAR))
//continue;
if(bRead)
{
bResult = ::ReadFile(hComm,
&RXBuff,
1,
&BytesRead,
&m_ov);
可是当使用ClearCommError函数时,得到的cbInque总是为0,导致死循环。
然而使用SetCommMask函数可以得到缓冲区已经接收到数据 了,只是用下面的ReadFile函数读出的数据不正确,这个又是咋回事呢。。。。求解
[解决办法]
剛才我大概看一下...因為其一是以永久循環迴路來做例子...其二是使用 Communicate 的 Overlapped 模式...所以在調試檢測通訊狀態或讀寫時並不會等待完成函數就直接離開...當然會導致死循環囉~ 實際的作法必須以計時器或多線程方式來輪詢......
SetCommMask 與 WaitCommMask 應該是匹配使用的...你所列出的例子其敘述並不是那麼完整...建議你把完整的例子給列出必較容易看出問題喔......
[解决办法]
我给你一个串口程序你参照下 前不久刚写的 没问题
void __fastcall TMainForm::CreatComm()
{
Comm.hCom = CreateFile( g_strCommPort.c_str(),GENERIC_READ
[解决办法]
GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_FLAG_OVERLAPPED,
NULL);
if ( Comm.hCom == INVALID_HANDLE_VALUE )
{
//ShowMessage("串口打开错误!");
Application->MessageBoxA("没有找到设备!", "错误!", MB_OK
[解决办法]
MB_ICONERROR);
exit(3);
}
if(Comm.hRecvEvent != NULL)
{
ResetEvent(Comm.hRecvEvent);
}
if(!SetCommMask(Comm.hCom,EV_RXCHAR))
{
ShowMessage("通信事件设置错误!");
CloseHandle(Comm.hCom);
return;
}
if(!InitCom())
{
ShowMessage("串口初始化错误!");
CloseHandle(Comm.hCom);
return;
}
// if(!InitTimeCom())
// {
// ShowMessage("串口超时设置错误!");
// CloseHandle(Comm.hCom);
// return;
// }
// Comm.hRecvEvent = CreateEvent(NULL,true,false,NULL);
if(!SetupComm(Comm.hCom, 128, 128))
{
ShowMessage("串口缓冲区设置错误!");
CloseHandle(Comm.hCom);
}
//清空输入输出缓冲区
if(!PurgeComm(Comm.hCom, PURGE_RXABORT
[解决办法]
PURGE_TXABORT
[解决办法]
PURGE_TXCLEAR
[解决办法]
PURGE_RXCLEAR ))
{
ShowMessage("串口缓冲区清理错误!");
CloseHandle(Comm.hCom);
}
m_hThread = CreateThread(NULL,NULL,(LPTHREAD_START_ROUTINE)ThreadProc,0,0,NULL);//创建监听串口数据线程
}
bool __fastcall TMainForm::InitCom()
{
//串口初始化
DCB dcb;
GetCommState(Comm.hCom,&dcb);
dcb.BaudRate = StrToInt(g_strBaud);
dcb.ByteSize = 8;
dcb.Parity = NOPARITY;
dcb.StopBits = ONESTOPBIT ;
return (SetCommState(Comm.hCom,&dcb));
}
bool __fastcall TMainForm::InitTimeCom() //超时设置
{
COMMTIMEOUTS TimeOuts;
GetCommTimeouts(Comm.hCom, &TimeOuts);
TimeOuts.ReadIntervalTimeout = 0;
TimeOuts.ReadTotalTimeoutMultiplier = 0;
TimeOuts.ReadTotalTimeoutConstant = 0;
TimeOuts.WriteTotalTimeoutMultiplier = 50;
TimeOuts.WriteTotalTimeoutConstant = 2000;
return (SetCommTimeouts(Comm.hCom, &TimeOuts)) ;
}
写数据
void __fastcall TMainForm::suiButton1Click(TObject *Sender)
{
DWORD dwBytesWriten;
DWORD dwBytesSend;
OVERLAPPED osWrite;
Byte btWrite[64];
memset(&osWrite, 0 ,sizeof(OVERLAPPED));
Byte btTitle[] = {0x7E,0x81,0x00,0x40,0x86,0x00,0x00,0x00, //0x40 总字节数
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,
0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x03,
0x00,0x00,0x00,0x10 // 0x10写32个字节 16个字
};
Byte btEnd[] = {0x0D, 0x0A};
memset(btWrite, 0 ,64);
for(int i = 0; i<28; i++)
{
btWrite[i] = btTitle[i];
}
for(int i = 0; i<32; i++)
{
btWrite[i+28] = m_btData[i];
}
Byte btCRC = GetCRC(btWrite,64);
btWrite[60] = 0x00;
btWrite[61] = btCRC;
btWrite[62] = btEnd[0];
btWrite[63] = btEnd[1];
WriteFile(Comm.hCom, btWrite, sizeof(btWrite), &dwBytesWriten, &osWrite);
if(ERROR_IO_PENDING== GetLastError())
{
GetOverlappedResult(Comm.hCom, &osWrite, &dwBytesWriten, true );
}
}
读数据
DWORD dwRead, dwEvMask, dwTransfer, dwErrorFlags;
memset(&Comm.osRead, 0, sizeof(OVERLAPPED));
Comm.osRead.hEvent = CreateEvent(NULL,true,false,NULL);
while(1)
{
if(!WaitCommEvent(Comm.hCom, &dwEvMask, &Comm.osRead))
{
//ERROR_IO_PENDING错误:重叠I/O返回的标志。表示现在等待I/O,稍后就会返回
if(ERROR_IO_PENDING == GetLastError())
GetOverlappedResult(Comm.hCom,&Comm.osRead,&dwTransfer,true);
}
if((dwEvMask & EV_RXCHAR)==EV_RXCHAR)
{
ClearCommError(Comm.hCom,&dwErrorFlags,&Comm.ComStat);
if(Comm.ComStat.cbInQue > 0)
{
SendMessage(g_hForm,WM_COMDATA,NULL,NULL);
}
}
}