?? ceserialcomm.cpp
字號:
/*************************************************************************
CeSerialComm.cpp: implementation of the CCeSerialComm class.
作 者: Raymond
創建時間: 2006.04.19
作 用: 封裝串口API
*************************************************************************/
//////////////////////////////////////////////////////////////////////
#include "stdafx.h"
#include "RddDbg.h"
#include "CeSerialComm.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////
CCeSerialComm::CCeSerialComm()
{
m_hComm = NULL;
m_strPort = _T("COM1");
m_strError = _T("");
m_uRate = 9600;
}
CCeSerialComm::~CCeSerialComm()
{
}
BOOL CCeSerialComm::InitComm(LPCTSTR lpszPort, UINT uRate, UINT uTimeOut)
{
if(IsCommOpened()) return TRUE;
if(!OpenComm(lpszPort)) return FALSE;
DCB commParam;
// 得到打開串口的當前屬性參數,修改后再重新設置串口。
// 設置串口的超時特性為立即返回。
if (!GetCommState(m_hComm,&commParam))
{
return FALSE;
}
commParam.fOutxCtsFlow = FALSE;
commParam.fOutxDsrFlow = FALSE;
commParam.fRtsControl = DTR_CONTROL_DISABLE;
commParam.fDtrControl = DTR_CONTROL_DISABLE;
commParam.BaudRate = uRate; // set the baud rate
commParam.ByteSize = 8; // data size, xmit, and rcv
commParam.Parity = NOPARITY; // no parity bit
commParam.StopBits = ONESTOPBIT; // one stop bit
if (!SetCommState(m_hComm, &commParam))
{
AfxMessageBox(_T("設置串口屬性參數失敗!"));
return FALSE;
}
//設置串口讀寫時間
COMMTIMEOUTS CommTimeOuts;
GetCommTimeouts (m_hComm, &CommTimeOuts);
CommTimeOuts.ReadIntervalTimeout = MAXDWORD;
CommTimeOuts.ReadTotalTimeoutMultiplier = 0;
CommTimeOuts.ReadTotalTimeoutConstant = 0;
CommTimeOuts.WriteTotalTimeoutMultiplier = 10;
CommTimeOuts.WriteTotalTimeoutConstant = 1000;
if(!SetCommTimeouts( m_hComm, &CommTimeOuts ))
{
TRACE( _T("SetCommTimeouts 返回錯誤") );
return FALSE;
}
//指定端口監測的事件集
SetCommMask (m_hComm, EV_RXCHAR|EV_TXEMPTY);
//分配設備緩沖區
SetupComm(m_hComm, 2048, 2048);
//初始化緩沖區中的信息
PurgeComm(m_hComm,PURGE_TXCLEAR|PURGE_RXCLEAR);
return TRUE;
}
BOOL CCeSerialComm::OpenComm(LPCTSTR lpszPort)
{
TCHAR szPort[15];
//設置串口名
wsprintf(szPort, L"%s:", lpszPort);
m_hComm = CreateFile(szPort, GENERIC_READ|GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, 0, NULL);
if(m_hComm == INVALID_HANDLE_VALUE)
{
m_strError = GetLastErrorDisc();
AfxMessageBox(m_strError);
return FALSE;
}
return TRUE;
}
BOOL CCeSerialComm::CloseComm()
{
if(m_hComm != NULL && m_hComm != INVALID_HANDLE_VALUE) return FALSE;
return CloseHandle(m_hComm);
}
BOOL CCeSerialComm::ClearCommBreaks()
{
if(m_hComm == NULL || m_hComm == INVALID_HANDLE_VALUE) return FALSE;
return ClearCommBreak(m_hComm);
}
BOOL CCeSerialComm::ClearCommErrors(LPDWORD lpErrors, LPCOMSTAT lpStat)
{
if(m_hComm == NULL || m_hComm == INVALID_HANDLE_VALUE) return FALSE;
return ClearCommError(m_hComm, lpErrors, lpStat);
}
BOOL CCeSerialComm::GetCommMasks(LPDWORD lpEvtMask)
{
if(m_hComm == NULL || m_hComm == INVALID_HANDLE_VALUE) return FALSE;
return GetCommMask(m_hComm, lpEvtMask);
}
BOOL CCeSerialComm::GetCommStates(LPDCB lpDCB)
{
if(m_hComm == NULL || m_hComm == INVALID_HANDLE_VALUE) return FALSE;
return GetCommState(m_hComm, lpDCB);
}
BOOL CCeSerialComm::GetCommTimeOut(LPCOMMTIMEOUTS lpCommTimeouts)
{
if(m_hComm == NULL || m_hComm == INVALID_HANDLE_VALUE) return FALSE;
return GetCommTimeouts(m_hComm, lpCommTimeouts);
}
BOOL CCeSerialComm::SetCommTimeOut(LPCOMMTIMEOUTS lpCommTimeouts)
{
if(m_hComm == NULL || m_hComm == INVALID_HANDLE_VALUE) return FALSE;
return SetCommTimeouts(m_hComm, lpCommTimeouts);
}
BOOL CCeSerialComm::PurgeCeComm(DWORD dwFlags)
{
if(m_hComm == NULL || m_hComm == INVALID_HANDLE_VALUE) return FALSE;
return PurgeComm(m_hComm, dwFlags);
}
BOOL CCeSerialComm::SetCommMasks(DWORD dwEvtMsk)
{
if(m_hComm == NULL || m_hComm == INVALID_HANDLE_VALUE) return FALSE;
return SetCommMask(m_hComm, dwEvtMsk);
}
BOOL CCeSerialComm::SetCommStates(LPDCB lpDCB)
{
if(m_hComm == NULL || m_hComm == INVALID_HANDLE_VALUE) return FALSE;
return SetCommState(m_hComm, lpDCB);
}
BOOL CCeSerialComm::IsCommOpened()
{
if(m_hComm == NULL || m_hComm == INVALID_HANDLE_VALUE) return FALSE;
return TRUE;
}
BOOL CCeSerialComm::ReadNoEvent(BYTE *pByMsg, DWORD dwLen, LPDWORD lpdwReadLen, DWORD dwTimeOut/* =0 */)
{
if(m_hComm == NULL || m_hComm == INVALID_HANDLE_VALUE) return FALSE;
if(dwTimeOut != 0)
{
COMMTIMEOUTS CommTimeouts;
if(!GetCommTimeOut(&CommTimeouts)) return FALSE;
CommTimeouts.ReadTotalTimeoutMultiplier = 10;
CommTimeouts.ReadTotalTimeoutConstant = dwTimeOut;
if(!SetCommTimeOut(&CommTimeouts)) return FALSE;
}
if(!ReadFile(m_hComm, pByMsg, dwLen, lpdwReadLen, NULL))
{
CloseComm();
return FALSE;
}
if(*lpdwReadLen != dwLen) return FALSE;
return TRUE;
}
BOOL CCeSerialComm::ReadComm(BYTE *pByMsg, DWORD dwNumberOfBytesToRead, LPDWORD lpNumOfByRead, DWORD dwTimeOut)
{
if(m_hComm == NULL || m_hComm == INVALID_HANDLE_VALUE) return FALSE;
if(dwTimeOut != 0)
{
COMMTIMEOUTS CommTimeouts;
if(!GetCommTimeOut(&CommTimeouts)) return FALSE;
CommTimeouts.ReadTotalTimeoutMultiplier = 10;
CommTimeouts.ReadTotalTimeoutConstant = dwTimeOut;
if(!SetCommTimeOut(&CommTimeouts)) return FALSE;
}
if(!ReadFile(m_hComm, pByMsg, dwNumberOfBytesToRead, lpNumOfByRead, NULL))
{
CloseComm();
return FALSE;
}
return TRUE;
}
BOOL CCeSerialComm::WriteComm(BYTE *pByMsg, DWORD dwNumOfByToWrite, LPDWORD lpNumOfByWritten, DWORD dwTimeOut)
if(m_hComm == NULL || m_hComm == INVALID_HANDLE_VALUE) return FALSE;
if(dwTimeOut != 0)
{
COMMTIMEOUTS CommTimeouts;
if(!GetCommTimeOut(&CommTimeouts)) return FALSE;
CommTimeouts.WriteTotalTimeoutMultiplier = 10;
CommTimeouts.WriteTotalTimeoutConstant = dwTimeOut;
if(!SetCommTimeOut(&CommTimeouts)) return FALSE;
}
if(!WriteFile(m_hComm, pByMsg, dwNumOfByToWrite, lpNumOfByWritten, NULL))
{
CloseComm();
return FALSE;
}
return TRUE;
}
BOOL CCeSerialComm::WaitCommEvents(LPDWORD lpEvtMask)
{
if(m_hComm == NULL || m_hComm == INVALID_HANDLE_VALUE) return FALSE;
return WaitCommEvent(m_hComm, lpEvtMask, NULL);
}
int CCeSerialComm::ReadAframe(BYTE *pByMsg, LPDWORD lpdwReadLen, DWORD dwTimeOut /* = 0 */)
{
*lpdwReadLen = 0;
DWORD dwIndex = 0;
DWORD dwReadLen;
if(!Read(pByMsg+dwIndex, 1, &dwReadLen, dwTimeOut)) return 0; //讀出錯
if(pByMsg[0] != 0xeb && pByMsg[0] != 0xd7) return -1; //報文頭第一個字節出錯
dwIndex += 1; //讀出一個字節
*lpdwReadLen = dwIndex;
if(!Read(pByMsg+dwIndex, 1, &dwReadLen, dwTimeOut)) return 0; //讀出錯
if(!(pByMsg[0]==0xeb && pByMsg[1]==0x90) && !(pByMsg[0]==0xd7 && pByMsg[1]==0x09)) return -1; //報文頭出錯
dwIndex += 1; //讀出一個字節
*lpdwReadLen = dwIndex;
if(!Read(pByMsg+dwIndex, 2, &dwReadLen, dwTimeOut)) return 0; //讀出錯
int iMsgLen = pByMsg[2] + pByMsg[3]*0x100;
if(iMsgLen > MAX_MSG_LEN) return -1; //長度出錯
dwIndex += 2; //讀出2個字節
*lpdwReadLen = dwIndex;
if(!Read(pByMsg+dwIndex, iMsgLen-4, &dwReadLen, dwTimeOut)) return 0; //讀出錯
dwIndex += iMsgLen-4; //讀出iMsgLen-4個字節
*lpdwReadLen = dwIndex;
return 1; //讀完
}
BOOL CCeSerialComm::Recv(BYTE *pByMsg, DWORD &dwLen, DWORD dwTimeOut)
{
dwLen = 0;
DWORD dwCommStatus;
if(m_hComm == NULL || m_hComm == INVALID_HANDLE_VALUE) return FALSE;
//清空串口
if(!PurgeCeComm(PURGE_RXCLEAR | PURGE_TXCLEAR )) return FALSE;
if(!SetCommMasks(EV_RXCHAR)) return FALSE;
if(!WaitCommEvents(&dwCommStatus)) return FALSE;
if(!SetCommMasks(EV_RXCHAR)) return FALSE;
if(dwCommStatus & EV_RXCHAR)
{
DWORD dwReadLen;
DWORD dwIndex = 0;
do
{
if(!ReadComm(pByMsg+dwIndex, 1, &dwReadLen, dwTimeOut))
{
m_strError = GetLastErrorDisc();
return FALSE;
}
if(dwReadLen == 1)
{
dwIndex++;
dwLen ++;
}
else
{
return FALSE;
}
} while(dwReadLen == 1);
return TRUE;
}
return FALSE;
}
/*****************************************************************************************
設計意圖:從串口中讀取指定長度的數據。如果串口中原來有數據,則直接讀出來,讀到夠長度就
返回,如果不夠,則等待直到讀到所需為止。如果串口中沒有數據,則等待
*****************************************************************************************/
BOOL CCeSerialComm::Read(BYTE *pByMsg, DWORD dwLen, LPDWORD lpdwReadLen, DWORD dwTimeOut)
{
*lpdwReadLen = 0;
if(m_hComm == NULL || m_hComm == INVALID_HANDLE_VALUE) return FALSE;
COMSTAT comStat;
DWORD dwErrors;
DWORD dwCommStatus;
BOOL bIsHasData = TRUE; //原本就有數據
if(!ClearCommErrors(&dwErrors, &comStat)) return FALSE;
DWORD dwInLen = comStat.cbInQue;
if(dwInLen < 1) //沒有數據
{
//清空串口
if(!PurgeCeComm(PURGE_RXCLEAR | PURGE_TXCLEAR )) return FALSE;
if(!SetCommMasks(EV_RXCHAR)) return FALSE;
if(!WaitCommEvents(&dwCommStatus)) return FALSE;
bIsHasData = FALSE;
}
DWORD dwIndex = 0;
DWORD dwReadLen;
//有數據來,或者原本就有數據
if((dwCommStatus & EV_RXCHAR) || bIsHasData)
{
do
{
if(!ReadComm(pByMsg+dwIndex, 1, &dwReadLen, dwTimeOut))
{
*lpdwReadLen = dwReadLen;
m_strError = GetLastErrorDisc();
return FALSE;
}
if(dwReadLen == 1)
{
dwIndex++;
}
if(dwIndex == dwLen) //已經讀完所需
{
*lpdwReadLen = dwLen;
return TRUE;
}
} while(dwIndex < dwInLen);
}
//清空串口
if(!PurgeCeComm(PURGE_RXCLEAR | PURGE_TXCLEAR )) return FALSE;
//長度不夠
if(!SetCommMasks(EV_RXCHAR)) return FALSE;
//讀到所需為止
while(dwIndex < dwLen)
{
if(!WaitCommEvents(&dwCommStatus)) return FALSE;
if(!SetCommMasks(EV_RXCHAR)) return FALSE;
if(dwCommStatus & EV_RXCHAR)
{
do
{
if(!ReadComm(pByMsg+dwIndex, 1, &dwReadLen, dwTimeOut))
{
m_strError = GetLastErrorDisc();
*lpdwReadLen = dwReadLen;
return FALSE;
}
if(dwReadLen == 1) dwIndex++;
if(dwIndex == dwLen) //已經夠所需了
{
*lpdwReadLen = dwLen;
return TRUE;
}
} while(dwReadLen == 1);
}
}
return FALSE;
}
BOOL CCeSerialComm::Write(BYTE *pByMsg, DWORD dwLen, LPDWORD lpdwWriteLen, DWORD dwTimeOut)
{
UINT uIndex = 0;
*lpdwWriteLen = 0;
while(uIndex < dwLen)
{
DWORD dwWrittenLen;
if(!WriteComm(pByMsg+uIndex, 1, &dwWrittenLen))
{
m_strError = GetLastErrorDisc();
return FALSE;
}
if(dwWrittenLen == 1)
{
uIndex++;
(*lpdwWriteLen)++;
}
else
{
return FALSE;
}
}
return TRUE;
}
CString CCeSerialComm::GetLastErrorDisc()
{
int iErCode = GetLastError();
HLOCAL hLocal = NULL;
BOOL fOk = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ALLOCATE_BUFFER,
NULL, iErCode, MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED),
(PTSTR) &hLocal, 0, NULL);
//如果沒有則從網絡模塊查找.
if(!fOk)
{
HMODULE hDLL = LoadLibraryEx(TEXT("netmsg.dll"), NULL,
DONT_RESOLVE_DLL_REFERENCES);
if(hDLL != NULL)
{
FormatMessage(FORMAT_MESSAGE_FROM_HMODULE | FORMAT_MESSAGE_FROM_SYSTEM,
hDLL, iErCode, MAKELANGID(LANG_CHINESE, SUBLANG_CHINESE_SIMPLIFIED),
(PTSTR)&hLocal, 0, NULL);
FreeLibrary(hDLL);
}
}
if(hLocal != NULL)
{
CString strMsg;
strMsg.Format(_T("%s"), (PTSTR)LocalLock(hLocal));
m_strError = strMsg;
LocalFree(hLocal);
return strMsg;
}
return _T("Unknow Error");
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -