?? serialport.cpp
字號:
if(!::SetCommMask(m_hComm, dwEvtMask)) {
TRACE(_T("Failed in call to SetCommMask"));
CSerialException::ThrowSerialException();
}
}
void CSerialPort::GetMask(DWORD& dwEvtMask)
{
ASSERT(IsOpen());
if(!::GetCommMask(m_hComm, &dwEvtMask)) {
TRACE(_T("Failed in call to GetCommMask\n"));
CSerialException::ThrowSerialException();
}
}
BOOL CSerialPort::WaitEvent(DWORD& dwEvtmask, OVERLAPPED& overlapped)
{
ASSERT(IsOpen());
BOOL bResult = ::WaitCommEvent(m_hComm, &dwEvtmask, &overlapped);
if (!bResult) {
if (::GetLastError() != ERROR_IO_PENDING) {
TRACE(_T("Failed in call to WaitCommEvent\n"));
CSerialException::ThrowSerialException();
}
}
return bResult;
}
void CSerialPort::GetOverlappedResult(OVERLAPPED& overlapped, DWORD& dwBytesTransfered, BOOL bWait)
{
ASSERT(m_hComm);
ASSERT(overlapped.hEvent != NULL);
if (!::GetOverlappedResult(m_hComm, &overlapped, &dwBytesTransfered, bWait)) {
if (::GetLastError() != ERROR_IO_PENDING) {
TRACE(_T("Failed in call to GetOverlappedResult\n"));
CSerialException::ThrowSerialException();
}
}
}
void CSerialPort::Escape(const DWORD& dwFunc)
{
ASSERT(IsOpen());
if (!::EscapeCommFunction(m_hComm, dwFunc)) {
TRACE(_T("Failed in call to EscapeCommFunction\n"));
CSerialException::ThrowSerialException();
}
}
void CSerialPort::ClearDTR(void)
{
Escape(CLRDTR);
}
void CSerialPort::ClearRTS(void)
{
Escape(CLRRTS);
}
void CSerialPort::SetDTR(void)
{
Escape(SETDTR);
}
void CSerialPort::SetRTS(void)
{
Escape(SETRTS);
}
void CSerialPort::SetXOFF(void)
{
Escape(SETXOFF);
}
void CSerialPort::SetXON(void)
{
Escape(SETXON);
}
void CSerialPort::GetModemStatus(DWORD& dwModemStatus)
{
ASSERT(IsOpen());
if (!GetCommModemStatus(m_hComm, &dwModemStatus)) {
TRACE(_T("Failed in call to GetCommModemStatus\n"));
CSerialException::ThrowSerialException();
}
}
void CSerialPort::SetBreak(void)
{
ASSERT(IsOpen());
if(!::SetCommBreak(m_hComm)) {
TRACE(_T("Failed in call to SetCommBreak\n"));
CSerialException::ThrowSerialException();
}
}
void CSerialPort::ClearBreak(void)
{
ASSERT(IsOpen());
if(!::ClearCommBreak(m_hComm)) {
TRACE(_T("Failed in call to ClearCommBreak"));
CSerialException::ThrowSerialException();
}
}
void CSerialPort::GetConfig(COMMCONFIG& config)
{
ASSERT(IsOpen());
DWORD dwSize = sizeof(COMMCONFIG);
if (!::GetCommConfig(m_hComm, &config, &dwSize)) {
TRACE(_T("Failed in call to GetCommConfig\n"));
CSerialException::ThrowSerialException();
}
}
void CSerialPort::SetConfig(COMMCONFIG& config)
{
ASSERT(IsOpen());
DWORD dwSize = sizeof(COMMCONFIG);
if (!::SetCommConfig(m_hComm, &config, dwSize)) {
TRACE(_T("Failed in call to SetCommConfig\n"));
CSerialException::ThrowSerialException();
}
}
void CSerialPort::GetDefaultConfig(UINT nPortNr, COMMCONFIG& config)
{
//Validate our parameters
ASSERT(nPortNr > 0 && nPortNr < 256);
//Create the device name as a string
CString strPort;
strPort.Format(_T("COM%d"), nPortNr);
DWORD dwSize = sizeof(COMMCONFIG);
if (!::GetDefaultCommConfig(strPort, &config, &dwSize)) {
TRACE(_T("Failed in call to GetDefaultCommConfig\n"));
CSerialException::ThrowSerialException();
}
}
void CSerialPort::SetDefaultConfig(UINT nPortNr, COMMCONFIG& config)
{
//Validate our parameters
ASSERT(nPortNr > 0 && nPortNr < 256);
//Create the device name as a string
CString strPort;
strPort.Format(_T("COM%d"), nPortNr);
DWORD dwSize = sizeof(COMMCONFIG);
if (!::SetDefaultCommConfig(strPort, &config, dwSize)) {
TRACE(_T("Failed in call to GetDefaultCommConfig\n"));
CSerialException::ThrowSerialException();
}
}
void CSerialPort::ClearError(DWORD& dwErrors)
{
ASSERT(IsOpen());
if(!::ClearCommError(m_hComm, &dwErrors, NULL)) {
TRACE(_T("Failed in call to ClearCommError\n"));
CSerialException::ThrowSerialException();
}
}
void CSerialPort::GetStatus(COMSTAT& comstat)
{
ASSERT(IsOpen());
DWORD dwErrors;
if (!::ClearCommError(m_hComm, &dwErrors, &comstat)) {
TRACE(_T("Failed in call to ClearCommError\n"));
CSerialException::ThrowSerialException();
}
}
void CSerialPort::InitPort(CWnd* pPortOwner, // the owner (CWnd) of the port (receives message)
UINT nPortNr, // portnumber (1..255)
UINT baud, // baudrate
char parity, // parity
UINT databits, // databits
UINT stopsbits , // stopbits
DWORD dwCommEvents, // EV_CTS,EV_DSR etc
UINT nBufferSize) // number of input buffer
{
ASSERT(pPortOwner != NULL);
ASSERT(nPortNr > 0 && nPortNr < 256);
if (m_bThreadAlive/*==TRUE*/) {
do {
::SetEvent(m_hShutdownEvent);
} while (m_bThreadAlive);
TRACE("Thread ended\n");
}
// create events
if (m_ReadOverlapped.hEvent/*!=NULL*/)
::ResetEvent(m_ReadOverlapped.hEvent);
else
m_ReadOverlapped.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
if (m_WriteOverlapped.hEvent/*!=NULL*/)
::ResetEvent(m_WriteOverlapped.hEvent);
else
m_WriteOverlapped.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
if (m_BreakOverlapped.hEvent/*!= NULL*/)
::ResetEvent(m_BreakOverlapped.hEvent);
else
m_BreakOverlapped.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
if (m_hWriteEvent/*!= NULL*/)
::ResetEvent(m_hWriteEvent);
else
m_hWriteEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
if (m_hShutdownEvent/*!= NULL*/)
::ResetEvent(m_hShutdownEvent);
else
m_hShutdownEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
// initialize the event objects
m_hEventArray[0] = m_hShutdownEvent; // highest priority
m_hEventArray[1] = m_ReadOverlapped.hEvent;
m_hEventArray[2] = m_BreakOverlapped.hEvent;
m_hEventArray[3] = m_hWriteEvent;
// initialize critical section
::InitializeCriticalSection(&m_csCommunicationSync);
// set buffersize for writing and save the owner
m_pOwner = pPortOwner;
if (m_lpInputBuffer/*!=NULL*/)
delete[] m_lpInputBuffer;
m_lpInputBuffer = new BYTE[nBufferSize];
m_nPortNr = nPortNr;
m_nBufferSize = nBufferSize;
m_dwCommEvents = dwCommEvents;
CString strPort;
CString strDef;
// now it critical!
::EnterCriticalSection(&m_csCommunicationSync);
if (IsOpen()){
::CloseHandle(m_hComm);
m_hComm = NULL;
}
strPort.Format(_T("\\\\.\\COM%d"), nPortNr);
strDef.Format(_T("baud=%d parity=%c data=%d stop=%d"), baud, parity, databits, stopsbits);
m_hComm = ::CreateFile((LPCTSTR)strPort, // 串口號 (COMX)
GENERIC_READ | GENERIC_WRITE, // 可以同時讀寫
0, // 以獨占方式打開串口
NULL, // 無安全屬性
OPEN_EXISTING, // 串口設備必須用OPEN_EXISTING,因為它肯定存在
FILE_FLAG_OVERLAPPED, // (重疊)異步I/O操作方式
0); // 對串設備,模板文件句柄必須為0(NULL)
if (m_hComm == INVALID_HANDLE_VALUE) {
::LeaveCriticalSection(&m_csCommunicationSync);
TRACE(_T("Failed to open up the comms port\n"));
CSerialException::ThrowSerialException();
}
// set the timeout values
m_CommTimeouts.ReadIntervalTimeout = 100;
m_CommTimeouts.ReadTotalTimeoutMultiplier = 0;
m_CommTimeouts.ReadTotalTimeoutConstant = 0;
m_CommTimeouts.WriteTotalTimeoutMultiplier = 0;
m_CommTimeouts.WriteTotalTimeoutConstant = 0;
try {
SetTimeouts(m_CommTimeouts);
SetMask(dwCommEvents);
GetState(m_dcb);
m_dcb.fRtsControl = RTS_CONTROL_ENABLE; // set RTS bit high!
BuildDCB(strDef, m_dcb);
SetState(m_dcb);
Purge(PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
} catch(CSerialException* pEx) {
::MessageBox(m_pOwner->m_hWnd, (LPCTSTR)pEx->GetErrorMessage(), _T("應用程序錯誤"), MB_ICONSTOP);
pEx->Delete();
}
::LeaveCriticalSection(&m_csCommunicationSync);
TRACE("Initialisation for communicationport %d completed.\nUse Startmonitor to communicate.\n", nPortNr);
}
// 開始監視工作線程
BOOL CSerialPort::StartMonitoring(void)
{
m_Thread = AfxBeginThread(CommThread, this);
if (!m_Thread)
return FALSE;
TRACE(_T("Thread started\n"));
return TRUE;
}
// 停止監視工作線程
BOOL CSerialPort::StopMonitoring(void)
{
ASSERT(m_Thread);
TRACE(_T("Thread suspended\n"));
m_Thread->SuspendThread();
return TRUE;
}
BOOL CSerialPort::RestartMonitoring(void)
{
ASSERT(m_Thread);
TRACE(_T("Thread Resume\n"));
m_Thread->ResumeThread();
return TRUE;
}
BOOL CSerialPort::SetBreakEvent(DWORD& dwCommEvents)
{
ASSERT(m_BreakOverlapped.hEvent != NULL);
try {
for(;;) {
if (WaitEvent(dwCommEvents, m_BreakOverlapped)) {
if (!HandleBreakEvent(dwCommEvents))
return FALSE;
} else {
break;
}
}
} catch(CSerialException* pEx) {
::MessageBox(m_pOwner->m_hWnd, (LPCTSTR)pEx->GetErrorMessage(), _T("應用程序錯誤"), MB_ICONSTOP);
pEx->Delete();
return FALSE;
}
return TRUE;
}
BOOL CSerialPort::SetReadEvent(void)
{
ASSERT(m_lpInputBuffer != NULL);
ASSERT(m_ReadOverlapped.hEvent != NULL);
DWORD dwReadByte;
try {
for (;;) {
::memset((void*)m_lpInputBuffer, 0, m_nBufferSize);
if (Read((LPVOID*)m_lpInputBuffer, m_nBufferSize, m_ReadOverlapped, &dwReadByte)) {
if (!HandleReadedEvent(m_lpInputBuffer, dwReadByte))
return FALSE;
::ResetEvent(m_ReadOverlapped.hEvent);
} else {
break;
}
}
} catch(CSerialException* pEx) {
::MessageBox(m_pOwner->m_hWnd, (LPCTSTR)pEx->GetErrorMessage(), _T("應用程序錯誤"), MB_ICONSTOP);
pEx->Delete();
return FALSE;
}
return TRUE;
}
BOOL CSerialPort::HandleReadedEvent(LPVOID pParam, const DWORD& dwReadCount)
{
COMMDATA CommData;
CommData.pParam = pParam;
CommData.dwParamCount = dwReadCount;
//發送輸入緩沖中的串口數據
m_pOwner->SendMessage(WM_COMM_READED_DETECTED, (WPARAM)&CommData, (LPARAM)m_nPortNr);
return SetReadEvent();
}
BOOL CSerialPort::HandleBreakEvent(DWORD& dwCommEvent)
{
if (dwCommEvent & EV_CTS)
m_pOwner->SendMessage(WM_COMM_CTS_DETECTED, (WPARAM)0, (LPARAM)m_nPortNr);
if (dwCommEvent & EV_BREAK)
m_pOwner->SendMessage(WM_COMM_BREAK_DETECTED, (WPARAM)0, (LPARAM)m_nPortNr);
if (dwCommEvent & EV_ERR)
m_pOwner->SendMessage(WM_COMM_ERR_DETECTED, (WPARAM)0, (LPARAM)m_nPortNr);
if (dwCommEvent & EV_RING)
m_pOwner->SendMessage(WM_COMM_RING_DETECTED, (WPARAM)0, (LPARAM)m_nPortNr);
if (dwCommEvent & EV_RXFLAG)
m_pOwner->SendMessage(WM_COMM_RXFLAG_DETECTED, (WPARAM)0, (LPARAM)m_nPortNr);
if (dwCommEvent & EV_TXEMPTY)
m_pOwner->SendMessage(WM_COMM_TXEMPTY_DETECTED, (WPARAM)0, (LPARAM)m_nPortNr);
return SetBreakEvent(dwCommEvent);
}
BOOL CSerialPort::HandleWriteEvent(void)
{
return ::ResetEvent(m_hWriteEvent);
}
void CSerialPort::HandleWaitTimeouts(void)
{
m_pOwner->SendMessage(WM_COMM_TIMEOUT_DETECTED, (WPARAM)0, (LPARAM)m_nPortNr);
}
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -