?? yscomm.cpp
字號(hào):
// YsAT.cpp: implementation of the CYsComm class.
//
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "YsComm.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CYsComm::CYsComm()
{
//ifdef _BALANCE
m_bSemiduplex=FALSE;
//#else
// m_bSemiduplex=TRUE;//半雙工
//#endif
m_hFileHandle = NULL;
//m_overlappedWrite={0, 0, 0, 0, NULL};
memset(&m_overlappedWrite,0,sizeof(OVERLAPPED));
//m_overlappedRead = {0, 0, 0, 0, NULL};
memset(&m_overlappedRead,0,sizeof(OVERLAPPED));
memset(&m_overlappedEvent,0,sizeof(OVERLAPPED));
// Needed for overlapped I/O.
m_overlappedWrite.hEvent = CreateEvent(NULL,TRUE,FALSE, NULL);
if (m_overlappedWrite.hEvent == NULL)
{
TRACE(_TEXT("Unable to CreateEvent:\n "));
}
// Lets put an event in the Read overlapped structure.
m_overlappedRead.hEvent = CreateEvent(NULL,TRUE,FALSE, NULL);
if (m_overlappedRead.hEvent == NULL)
{
TRACE(_TEXT("Unable to CreateEvent: \n"));
}
m_overlappedEvent.hEvent = CreateEvent(NULL,TRUE,FALSE, NULL);
if (m_overlappedEvent.hEvent == NULL)
{
TRACE(_TEXT("Unable to CreateEvent: \n"));
}
m_hStopReadEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
if (m_hStopReadEvent== NULL)
{
TRACE(_TEXT("Unable to CreateEvent: \n"));
}
m_hStopWriteEvent=CreateEvent(NULL,TRUE,FALSE,NULL);
if (m_hStopWriteEvent== NULL)
{
TRACE(_TEXT("Unable to CreateEvent: \n"));
}
m_nPort=0;
m_hWnd=NULL;
}
CYsComm::~CYsComm()
{
StopComm();
CloseHandle(m_overlappedRead.hEvent);
CloseHandle(m_overlappedWrite.hEvent);
CloseHandle(m_overlappedEvent.hEvent);
CloseHandle(m_hStopWriteEvent);
CloseHandle(m_hStopReadEvent);
}
/*************************2001.10.31 ycat *********************************************
FUNCTION: BOOL CYsComm::Create(UINT port,HWND hWnd)
PURPOSE: 創(chuàng)建串口文件句柄
PARAMETERS:
port:串口的串口號(hào)
hWnd:用來(lái)接收消息的窗口句柄
RETURN VALUE:
如果操作成功,返回TRUE,如果失敗返回FALSE
COMMENTS:
**********************************************************************/
BOOL CYsComm::Create(UINT port,BOOL bSemiduplex,HWND hWnd)
{
m_bSemiduplex=bSemiduplex;
CString sBuff;
DWORD dwError = 0;
if(m_hFileHandle!=NULL)
{
StopComm();
}
sBuff.Format(_TEXT("COM%d"),port);
m_hFileHandle = CreateFile(sBuff,
GENERIC_READ|GENERIC_WRITE,
0,//exclusive access
NULL,
OPEN_EXISTING, //必須
FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,
NULL);
if(m_hFileHandle == INVALID_HANDLE_VALUE)
{
dwError = GetLastError();
TRACE(_TEXT("Open COM%d Error code %d,Please check if the port is usable.\n"),port,dwError);
return FALSE;
}
m_hWnd=hWnd;
m_nPort=port;
return TRUE;
}
/*************************2001.10.31 ycat *********************************************
FUNCTION: void CYsComm::StopComm()
PURPOSE: 關(guān)閉串口句柄
PARAMETERS:
RETURN VALUE:
COMMENTS:
**********************************************************************/
void CYsComm::StopComm()
{
// No need to continue if we're not communicating.
if (m_hFileHandle == NULL)
return;
//Purge(PURGE_ALL);
TRACE(_TEXT("Stopping the Comm\n"));
// Now close the comm port handle.
CloseHandle(m_hFileHandle);
m_hFileHandle = NULL;
}
/*************************2001.10.31 ycat *********************************************
/*************************2001.11.06 ycat *********************************************
FUNCTION: int CYsComm::ReadIn(LPTSTR lpszInputBuffer,
DWORD dwCount,
DWORD dwReadTimeOut)
PURPOSE: 在dwReadTimeOut里讀到dwCount個(gè)字符,否則出錯(cuò)
PARAMETERS:
lpszInputBuffer: 存放返回?cái)?shù)據(jù)的字符串緩沖區(qū)
dwCount: 希望要讀到的字符個(gè)數(shù)
dwReadTimeOut: 超時(shí)的時(shí)間
RETURN VALUE:
-1: 除-2,-3之外的其它錯(cuò)誤
1:表示寫(xiě)com口成功
-2: 表示timeout
-3: 表示讀操作被停止
COMMENTS:
不能支持多線程
如果讀出的數(shù)和dwCount不一樣,那么將返回超時(shí)
讀出來(lái)的數(shù)沒(méi)有意義
注意和ReadComm()的區(qū)別
**********************************************************************/
int CYsComm::ReadIn(PBYTE lpszInputBuffer,
DWORD dwCountoByte,
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;
//HandlesToWaitFor[0] = o.hEvent;
DWORD dwHaveReaded=0;
// unsigned char
// WCHAR
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 @@@\n",lpszInputBuffer[i],lpszInputBuffer[i]);
}*/
if(nRet!=1) Purge(PURGE_RXABORT);//取消讀操作
return nRet;
}
/*************************2001.10.31 ycat *********************************************
FUNCTION: int CYsComm::BOOL CYsComm::Purge(DWORD nType)
PURPOSE: 清除串口
PARAMETERS:
nType的值及說(shuō)明,可組合起來(lái)用
PURGE_TXABORT Terminates all outstanding overlapped write
operations and returns immediately,
even if the write operations have not been completed.
PURGE_RXABORT Terminates all outstanding overlapped
read operations and returns immediately,
even if the read operations have not been completed.
PURGE_TXCLEAR Clears the output buffer (if the device driver has one).
PURGE_RXCLEAR Clears the input buffer (if the device driver has one).
RETURN VALUE: 如果操作成功,返回TRUE,如果失敗返回FALSE
COMMENTS:
**********************************************************************/
BOOL CYsComm::Purge(DWORD nType)
{
if(!m_hFileHandle)
{
// SetLastError(_TEXT("comm file handle isn't available"));
return FALSE;
}
if(nType&PURGE_RXABORT)
PulseEvent(m_hStopReadEvent);
if(nType&PURGE_TXABORT)
PulseEvent(m_hStopWriteEvent);
int i=PurgeComm(m_hFileHandle,nType);
if(!i)
{
// SetLastError(_TEXT("Purge com fail"));
return FALSE;
}
// ResetError();
// TRACE(_TEXT("Purge Comm\n");
return i;
}
/*查詢緩沖區(qū)內(nèi)的字符數(shù)
nType=TYPE_READ 表示查讀緩沖區(qū)
nType=TYPE_WRITE表示寫(xiě)緩沖區(qū)*/
BOOL CYsComm::GetBufferCount(int nType,LPDWORD lpNumberInBuffer)
{
DWORD Errors;
COMSTAT State;
if(!ClearCommError(m_hFileHandle,&Errors,&State))
return FALSE;
if(nType==TYPE_READ) *lpNumberInBuffer=State.cbInQue;
else *lpNumberInBuffer=State.cbOutQue;
return TRUE;
}
/*************************2001.10.31 ycat *********************************************
FUNCTION: int CYsComm::WriteComm(LPCTSTR lpszStringToWrite,
DWORD dwCount)
PURPOSE: 向串口發(fā)送數(shù)據(jù)
PARAMETERS:
lpszStringToWrite:要寫(xiě)的字符串
dwCount:字符串的長(zhǎng)度
RETURN VALUE:
-1:除timeout外其它錯(cuò)誤
1:表示寫(xiě)com口成功
-2:表示timeout
-3:表示stop write event set
COMMENTS:
Change the WaitForSingleObject call to include a real
time-out value. This causes more problems because
if the program issues another operation
while an older operation is still pending,
new OVERLAPPED structures and overlapped
events need to be allocated.
This type of recordkeeping is difficult,
particularly when compared to using a “job queue”
design for the operations.
不支持多線程
**********************************************************************/
int CYsComm::WriteComm(PBYTE lpszStringToWrite,
DWORD dwCount)
{
if ( m_hFileHandle == NULL)
{
TRACE(_TEXT("m_hFileHandle error_W.\n"));
return -1;
}
int nRet;
DWORD dwLastError;
DWORD dwHaveWritten = 0;
DWORD dwStartWrite = 0; // Start at the beginning.
DWORD dwNumToWrite = dwCount;
DWORD dwHandleSignaled;
HANDLE HandlesToWaitFor[2];
int iWait=2;
HandlesToWaitFor[0] = m_overlappedWrite.hEvent;
HandlesToWaitFor[1] = m_hStopWriteEvent;
// EscapeCommFunction(m_hFileHandle,SETRTS);//半雙工
// Keep looping until all characters have been written.
do
{
// Start the overlapped I/O.
if (!WriteFile((HANDLE)m_hFileHandle,
(LPCVOID)&(lpszStringToWrite[dwStartWrite]),
(DWORD)dwCount,
(LPDWORD)&dwHaveWritten,
(LPOVERLAPPED)&m_overlappedWrite))
{
// WriteFile failed. Expected; lets handle it.
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 writing to CommFile %x\n"),dwLastError);
nRet=-1;
goto Exit;
}
// Wait for either overlapped I/O completion,
// or for the CloseEvent to get signaled.
dwHandleSignaled =
WaitForMultipleObjects(2, HandlesToWaitFor,
FALSE,5000);
switch(dwHandleSignaled)
{
case WAIT_OBJECT_0 : // Wait finished.
{
// Time to get the results of the WriteFile
break;
}
case WAIT_TIMEOUT :
{
TRACE(_TEXT("write time out\n"));
nRet=-2;
goto Exit;
}
case WAIT_FAILED: // Wait failed. Shouldn't happen.
{
TRACE(_TEXT("Write WAIT_FAILED: \n "));
nRet=-1;
goto Exit;
}
case WAIT_OBJECT_0+1:
{
//stop event set
TRACE(_TEXT("stop event set"));
nRet=-3;
goto Exit;
}
default: // This case should never occur.
{
TRACE(_TEXT("Unexpected Wait return value '%x'"),dwHandleSignaled);
nRet=-1;
goto Exit;
}
}
//判斷是否已經(jīng)結(jié)束
if (!GetOverlappedResult(m_hFileHandle,
&m_overlappedWrite,
&dwHaveWritten,
TRUE))
{
dwLastError = GetLastError();
// Its possible for this error to occur if the
// service provider has closed the port.
if (dwLastError == ERROR_INVALID_HANDLE)
{
TRACE(_TEXT("ERROR_INVALID_HANDLE, Likely that the Service Provider has closed the port.\n"));
nRet=-1;
goto Exit;
}
// No idea what could cause another error.
TRACE(_TEXT("Error writing to CommFile while waiting %x \n"),dwLastError);
nRet=-1;
goto Exit;
}
}
// Some data was written. Make sure it all got written.
//TRACE(_TEXT("Write bytes %ld\n",dwHaveWritten);
dwCount -= dwHaveWritten;
dwStartWrite += dwHaveWritten;
}while(dwCount > 0); // Write the whole thing!
// Wrote the whole string.
// *pdwCountWritten = dwNumToWrite;
nRet=1;
Exit:
// EscapeCommFunction(m_hFileHandle,CLRRTS);//半雙工
if(nRet!=1) Purge(PURGE_TXABORT|PURGE_TXCLEAR);//取消寫(xiě)操作
return nRet;
}
/*
很簡(jiǎn)單的設(shè)置串口的程序,無(wú)參數(shù)接口,還需修改
*/
BOOL CYsComm::SetComm(int iBaud)
{
m_iBaud=iBaud;
DCB dcb;
BOOL fSuccess;
fSuccess = GetCommState(m_hFileHandle, &dcb);
if (!fSuccess)
{
// Handle the error.
TRACE(_TEXT("GetCommState failed with error %d.\n"), GetLastError());
return FALSE;
}
//BuildCommDCB("2400,n,8,1", &dcb)) //another way to set DCB
dcb.fBinary=TRUE;
dcb.BaudRate = iBaud; // set the baud rate
dcb.ByteSize = 8; // data size, xmit, and rcv
dcb.Parity = 0;//EVENPARITY;// Even parity bit
?? 快捷鍵說(shuō)明
復(fù)制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號(hào)
Ctrl + =
減小字號(hào)
Ctrl + -