?? yscomm.cpp
字號:
dcb.StopBits = ONESTOPBIT; // one stop bit
dcb.fAbortOnError=FALSE;
//dcb.EofChar=1;
//dcb.fRtsControl=DTR_CONTROL_DISABLE;
if(m_bSemiduplex)
dcb.fRtsControl=RTS_CONTROL_TOGGLE;//半雙工
else dcb.fRtsControl=RTS_CONTROL_ENABLE;//用來控制modem
SetupComm(m_hFileHandle,2048,2048);//setup comm buffer size
/* COMMTIMEOUTS TimeOuts;
//Setup timeout
TimeOuts.ReadIntervalTimeout=MAXDWORD;
TimeOuts.ReadTotalTimeoutMultiplier=0;
TimeOuts.ReadTotalTimeoutConstant=0;
TimeOuts.WriteTotalTimeoutMultiplier=100;
TimeOuts.WriteTotalTimeoutConstant=1000;
SetCommTimeouts(m_hFileHandle, &TimeOuts);
*/
Purge(PURGE_ALL);
fSuccess = SetCommState(m_hFileHandle, &dcb);
if (!fSuccess)
{
// Handle the error.
TRACE(_TEXT("SetCommState failed with error %d.\n"), GetLastError());
return FALSE;
}
// EscapeCommFunction(m_hFileHandle,CLRRTS);//半雙工
return TRUE;
}
/*************************2001.10.31 ycat *********************************************
FUNCTION: BOOL CYsComm::SetEvent(DWORD dwEvent)
PURPOSE: 設置要等待的串口事件
PARAMETERS:
dwEvent:要等待的事件
EV_BREAK | EV_CTS | EV_DSR | EV_ERR | EV_RING |\
EV_RLSD | EV_RXCHAR | EV_RXFLAG | EV_TXEMPTY
RETURN VALUE:
TRUE表示操做成功,FALSE表示操作失敗
COMMENTS: 目前只支持一種狀態,說明見下一WaitEvent()
*********************************************************************************/
BOOL CYsComm::SetEvent(DWORD dwEvent)
{
return SetCommMask(m_hFileHandle,dwEvent);
}
/*************************2001.10.31 ycat *********************************************
FUNCTION: int CYsComm::WaitEvent(DWORD* pwdEvent,DWORD dwTimeOut)
PURPOSE: 等待收到某個串口事件
PARAMETERS:
pwdEvent:所等到的事件
dwTimeOut:超時設置
RETURN VALUE:
-1: 除timeout外其它錯誤
1:等待成功
-2: 表示timeout
COMMENTS:
Note The Microsoft Win32 SDK Knowledge Base documents
a problem with Windows 95 and the EV_RING flag.
The above code never returns in Windows 95 because
the EV_RING event is not detected by the system;
Windows NT properly reports the EV_RING event.
Please see the Win32 SDK Knowledge Base for more
information on this bug.
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.
如果用重疊IO,則SetCommMask使正在等待的WaitCommEvent馬上返回,
而且返回的事件為NULL
出錯時返回負數,但DWORD為無符號數,會不會出問題?
目前只支持等待一個事件
**********************************************************************/
int CYsComm::WaitEvent(DWORD* pwdEvent,DWORD dwTimeOut)
{
if(m_hFileHandle==NULL) return -1;
DWORD nRet;
DWORD dwRes;
DWORD dwOvRes;
int i;
// if(!SetCommMask(m_hFileHandle,EV_RXCHAR))
// return -1;//清除以前事件
// WaitCommEvent(m_hFileHandle,pwdEvent,NULL);
// Issue a status event check if one hasn't been issued already.
if (WaitCommEvent(m_hFileHandle,pwdEvent,&m_overlappedEvent))
{
// WaitCommEvent returned immediately.
// Deal with status event as appropriate.
DoStateEvent(*pwdEvent);
nRet=1;
goto Exit;
}
i=GetLastError();
// error in WaitCommEvent; abort
if (i!= ERROR_IO_PENDING)
{
nRet=-1;
TRACE(_TEXT("GetlastError %d\n"),i);
goto Exit;
}
// Check on overlapped operation.
// Wait a little while for an event to occur.
dwRes = WaitForSingleObject(m_overlappedEvent.hEvent, dwTimeOut);
switch(dwRes)
{
// Event occurred.
case WAIT_OBJECT_0:
if (GetOverlappedResult(m_hFileHandle,&m_overlappedEvent,&dwOvRes,FALSE))
{
// Status event is stored in the event flag
// specified in the original WaitCommEvent call.
// Deal with the status event as appropriate.
DoStateEvent(*pwdEvent);
nRet=1;
goto Exit;
}
else
{
// An error occurred in the overlapped operation;
// call GetLastError to find out what it was
// and abort if it is fatal.
TRACE(_TEXT("An error occurred in the overlapped operation\nGetLastError is %d\n "),
GetLastError());
nRet=-1;
goto Exit;
}
break;
case WAIT_TIMEOUT:
nRet=-2;
goto Exit;
break;
default:
nRet=-1;
goto Exit;
}
Exit:
return nRet;
}
/*
對串口事件進行處理,還要修改
返回值無意義
*/
BOOL CYsComm::DoStateEvent(DWORD dwEvtMask)
{
if(dwEvtMask==NULL) return TRUE;
//dwEvtMask可能會為NULL
if (dwEvtMask & EV_BREAK) //檢測到轉入的中止
{
if(m_hWnd)PostMessage(m_hWnd,WM_YSCOMM_MESSAGE,WM_EV_BREAK,m_nPort);
}
if (dwEvtMask & EV_CTS) //CTS (清除發送)信號改變狀態
{
if(m_hWnd)PostMessage(m_hWnd,WM_YSCOMM_MESSAGE,WM_EV_CTS,m_nPort);
}
if (dwEvtMask & EV_DSR) //DSR (數據設置就緒) 信號改變狀態
{
if(m_hWnd)PostMessage(m_hWnd,WM_YSCOMM_MESSAGE,WM_EV_DSR,m_nPort);
}
if (dwEvtMask & EV_ERR) //發生線路狀態錯誤
{
if(m_hWnd)PostMessage(m_hWnd,WM_YSCOMM_MESSAGE,WM_EV_ERR,m_nPort);
}
if (dwEvtMask & EV_RING)//檢測到振鈴
{
if(m_hWnd)PostMessage(m_hWnd,WM_YSCOMM_MESSAGE,WM_EV_RING,m_nPort);
}
if (dwEvtMask & EV_RLSD)//RLSD(接收線路信號檢測)信號改變狀態
{
if(m_hWnd)PostMessage(m_hWnd,WM_YSCOMM_MESSAGE,WM_EV_RLSD,m_nPort);
}
if (dwEvtMask & EV_RXCHAR)//收到一個字符,并放入輸入緩沖區
{
if(m_hWnd)PostMessage(m_hWnd,WM_YSCOMM_MESSAGE,WM_EV_RXCHAR,m_nPort);
}
if (dwEvtMask & EV_RXFLAG) //收到事件字符(DCB結構的EvtChar成員),并放入輸入緩沖區
{
if(m_hWnd)PostMessage(m_hWnd,WM_YSCOMM_MESSAGE,WM_EV_RXFLAG,m_nPort);
}
if (dwEvtMask & EV_TXEMPTY)//輸出緩沖區最后一個字符發送出去
{
if(m_hWnd)PostMessage(m_hWnd,WM_YSCOMM_MESSAGE,WM_EV_TXEMPTY,m_nPort);
}
return TRUE;
}
//一個例子,供參考
/*************************2001.10.30 ycat *********************************************
FUNCTION: UINT CATModem::ReadCommThread(LPVOID pParam)
PURPOSE: 線程函數,把串口讀入緩沖區的字符,寫到自己維護的緩沖區中,并判斷斷線
PARAMETERS:
pParam:指向CATModem類
RETURN VALUE:
COMMENTS: 斷線的處理,也許還要改進
**********************************************************************/
/*************************2001.11.06 ycat *********************************************
FUNCTION: int CYsComm::ReadComm(
PBYTE pByteRead,
DWORD dwCount,
DWORD* dwHaveReaded,
DWORD nTimeOut)
PURPOSE: 在dwReadTimeOut里讀到dwCount個字符,既使超時,
在緩沖區里也有在超時之前讀出來的數據
PARAMETERS:
pByteRead: 存放返回數據的字符串緩沖區
dwCount: 希望要讀到的字符個數
dwHaveReaded: 已經讀到的數據
dwReadTimeOut: 超時的時間
RETURN VALUE:
-1: 除-2,-3之外的其它錯誤
1:表示寫com口成功
-2:表示超時
-3: 表示讀操作被停止
COMMENTS:
不能支持多線程
即使沒有讀夠dwCount個數,緩沖區里的字符仍然有效
注意和ReadIn()的區別
**********************************************************************/
/*int CYsComm::ReadComm(PBYTE pByteRead,DWORD dwCount,
DWORD* dwHaveReaded,DWORD nTimeOut)
{
int nRet;
DWORD dwTimeAfter;
DWORD dwTimeUsed;
DWORD dwTimeBefore;
for(DWORD i=0;i<dwCount;i++)
{
dwTimeBefore=GetTickCount();
nRet=ReadIn(pByteRead+i,1,nTimeOut);
if(nRet==-2)//超時
{
// TRACE(_TEXT("ReadComm Timeout %ld \n"),nTimeOut);
goto Exit;
}
else if(nRet!=1) //出錯
{
TRACE(_TEXT("ReadComm Error %ld \n"),nRet);
goto Exit;
}
dwTimeAfter=GetTickCount();
dwTimeUsed=dwTimeAfter-dwTimeBefore;
if(dwTimeUsed>nTimeOut)
{
if(i<dwCount)
{
nRet=-2;//TimeOut
goto Exit;
}
else
{
nRet=1;
goto Exit;
}
}
//計算剩下的時間
nTimeOut-=dwTimeUsed;
}
nRet=1;
Exit:
*dwHaveReaded=i;
return nRet;
}
*/
/*************************2001.10.31 ycat *********************************************
FUNCTION: int CYsComm::ReadComm(PBYTE buffer,
DWORD dwRead,
LPDWORD pdwReaded,
DWORD dwStartTimeOut,
DWORD dwInterTimeOut)
PURPOSE: 讀從dwStartTimeOut時間開始,以dwInterTimeOut為時間間隔,
的字符
PARAMETERS:
buffer: 緩沖區
dwRead: 希望讀到的長度
pdwReaded: 實際讀到的長度
dwStartTimeOut: 最大的開始讀數等待時間
dwInterTimeOut: 讀每個字符之間的等待時間
RETURN VALUE:
-1: 除-2,-3之外的其它錯誤
1:表示寫com口成功
-2:表示超時
-3: 表示讀操作被停止
COMMENTS:
有兩種超時可能
即使超時,緩沖區里的字符串仍然有效
讀出緩沖區里的數據,時間處理有問題? 有待測試
希望讀到的長度讀到時,是否正常? 有待測試
**********************************************************************/
int CYsComm::ReadComm(PBYTE pByteRead,
DWORD dwCount,
LPDWORD dwHaveReaded,
DWORD dwStartTimeOut,
DWORD dwInterTimeOut)
{
int nRet;
DWORD dwTimeAfter;
DWORD dwTimeUsed;
DWORD dwTimeBefore;
DWORD i=0;
nRet=ReadIn(pByteRead+i,1,dwStartTimeOut);
if(nRet!=1)
{
TRACE(_TEXT("ReadComm Error %ld \n"),nRet);
goto Exit;
}
for(i=1;i<dwCount;i++)
{
dwTimeBefore=GetTickCount();
nRet=ReadIn(pByteRead+i,1,dwInterTimeOut);
if(nRet!=1)
{
TRACE(_TEXT("ReadComm Error %ld \n"),nRet);
goto Exit;
}
dwTimeAfter=GetTickCount();
dwTimeUsed=dwTimeAfter-dwTimeBefore;
if(dwTimeUsed>dwInterTimeOut)
{
if(i<dwCount)
{
nRet=-2;//TimeOut
goto Exit;
}
else
{
nRet=1;
goto Exit;
}
}
//計算剩下的時間
dwInterTimeOut-=dwTimeUsed;
}
nRet=1;
Exit:
*dwHaveReaded=i;
return nRet;
}
BOOL CYsComm::StopRead()
{
return PulseEvent(m_hStopReadEvent);
}
BOOL CYsComm::StopWrite()
{
return PulseEvent(m_hStopWriteEvent);
}
int CYsComm::ReadComm(PBYTE lpszInputBuffer,DWORD dwCountoByte,
DWORD* dwHaveReaded,DWORD dwReadTimeOut)
{
if ( m_hFileHandle == NULL)
{
TRACE(_TEXT("m_hFileHandle error.\n"));
return -1;
}
int nRet;
DWORD dwLastError;
DWORD dwHandleSignaled;
HANDLE HandlesToWaitFor[2];
int iWait=2;
// HandlesToWaitFor[0] = g_hCloseEvent;//為了支持多線程
//OVERLAPPED o={0};
//o.hEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
HandlesToWaitFor[0] = m_overlappedRead.hEvent;
HandlesToWaitFor[1] = m_hStopReadEvent;
if (ReadFile((HANDLE)m_hFileHandle,
(LPVOID)lpszInputBuffer,
(DWORD)dwCountoByte,
(LPDWORD)dwHaveReaded,
(LPOVERLAPPED)&m_overlappedRead))
{ // This would only happen if there was data waiting to be read.
// TRACE(_TEXT("there waw data waiting to be read.\n");
nRet=1;
goto Exit;
}
// ReadFile failed. Expected because of overlapped I/O.
dwLastError = GetLastError();
// Its possible for this error to occur if the
// service provider has closed the port. Time to end.
if (GetLastError()!= ERROR_IO_PENDING)
{
TRACE(_TEXT("Error to reading to CommFile %x\n"),dwLastError);
nRet=-1;
goto Exit;
}
// This is the expected ERROR_IO_PENDING case.
// Wait for either overlapped I/O completion,
// or for the CloseEvent to get signaled.
dwHandleSignaled =
WaitForMultipleObjects(iWait,HandlesToWaitFor,
FALSE,dwReadTimeOut);
switch(dwHandleSignaled)
{
case WAIT_OBJECT_0 : // Wait finished.
{
// Time to get the results of the WriteFile
break;
}
case WAIT_OBJECT_0+1 : // Wait finished.
{
TRACE(_TEXT("stop read event set\n"));
nRet=-3;
goto Exit;
}
case WAIT_TIMEOUT :
{
// TRACE(_TEXT("read time out\n"));
nRet=-2;
goto Exit;
}
case WAIT_FAILED: // Wait failed. Shouldn't happen.
{
TRACE(_TEXT("read WAIT_FAILED: \n "));
nRet=-1;
goto Exit;
}
default: // This case should never occur.
{
TRACE(_TEXT("Unexpected Wait return value '%x'"),dwHandleSignaled);
nRet=-1;
goto Exit;
}
}
if (GetOverlappedResult(m_hFileHandle,
&m_overlappedRead,dwHaveReaded, FALSE))
{
nRet=1;
goto Exit;
}
else
{
//cause by Purge(PURGE_RXABORT)
TRACE(_TEXT("read operation error \n "));
nRet=-1;
}
Exit:
/* if(nRet==1)
{
for(UINT i=0;i<*dwHaveReaded;i++)
TRACE("@@@ %x %c @@@\n",lpszInputBuffer[i],lpszInputBuffer[i]);
}//test*/
if(nRet!=1) Purge(PURGE_RXABORT);//取消讀操作
return nRet;
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -