bool CMySerial::OpenSerialPort(CWnd* pParent, UINT portnr, UINT baud, wchar_t parity, UINT databits, UINT stopbits, DWORD dwCommEvents, UINT writebuffersize)
{
//assert(portnr > 0 && portnr < 5);
assert(pParent != NULL);
// 如果串口監控執行緒活動,則關閉它
if (m_bThreadAlive)
{
do
{
SetEvent(m_hShutdownEvent);
} while (m_bThreadAlive);
TRACE("Thread ended\n");
}
// 創建串口異步通訊事件
if (m_ov.hEvent != NULL)
ResetEvent(m_ov.hEvent);
else
m_ov.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);
// 初始化事件陣列
m_hEventArray[0] = m_hShutdownEvent; // 最高的優先級
m_hEventArray[1] = m_ov.hEvent;
m_hEventArray[2] = m_hWriteEvent;
// 初始化臨界資源
InitializeCriticalSection(&m_csCommunicationSync);
// 保存串口操作視窗指標
m_pParent = pParent;
// 為發送緩沖申請空間
if (m_szWriteBuffer != NULL)
delete [] m_szWriteBuffer;
m_szWriteBuffer = new wchar_t[writebuffersize];
// 保存串口號
m_nPortNr = portnr;
// 將要發送的資料
m_nWriteBufferSize = writebuffersize;
m_dwCommEvents = dwCommEvents;
BOOL bResult = FALSE;
wchar_t *szPort = new wchar_t[100];
//wchar_t *szBaud = new wchar_t[100];
CString szBaud;
// 鎖定臨界變數
EnterCriticalSection(&m_csCommunicationSync);
// 如果串口已經打開,則關閉他
if (m_hComm != NULL)
{
CloseHandle(m_hComm);
m_hComm = NULL;
}
// 狀態資訊
swprintf(szPort,100, _T("COM%d"), portnr);
//swprintf(szBaud,100, _T("baud=%d parity=%c data=https://bbs.csdn.net/topics/%d stop=%d"), baud, parity, databits, stopbits);
szBaud.Format(_T("baud=%d parity=%c data=https://bbs.csdn.net/topics/%d stop=%d"),baud, parity, databits, stopbits);
AfxMessageBox(szBaud);
// 打開串口
m_hComm = CreateFile(szPort, // communication port string (COMX)
GENERIC_READ | GENERIC_WRITE, // read/write types
0, // comm devices must be opened with exclusive access
NULL, // no security attributes
OPEN_EXISTING, // comm devices must use OPEN_EXISTING
FILE_FLAG_OVERLAPPED, // Async I/O
NULL); // template must be 0 for comm devices
if (m_hComm == INVALID_HANDLE_VALUE)
{
// 打開失敗
AfxMessageBox(_T("埠打開失敗"));
delete [] szPort;
//delete [] szBaud;
return FALSE;
}
// 超時引數
m_CommTimeouts.ReadIntervalTimeout = 1000;
m_CommTimeouts.ReadTotalTimeoutMultiplier = 1000;
m_CommTimeouts.ReadTotalTimeoutConstant = 1000;
m_CommTimeouts.WriteTotalTimeoutMultiplier = 1000;
m_CommTimeouts.WriteTotalTimeoutConstant = 1000;
// 設定串口引數
if (SetCommTimeouts(m_hComm, &m_CommTimeouts))
{
if (SetCommMask(m_hComm, dwCommEvents))
{
if (GetCommState(m_hComm, &m_dcb))
{
m_dcb.EvtChar = 'q';
m_dcb.fRtsControl = RTS_CONTROL_ENABLE;
//SetDCB(&m_dcb,baud,parity,databits,stopbits);
//m_dcb.BaudRate=baud;
//m_dcb.Parity=parity;
//m_dcb.ByteSize=databits;
//m_dcb.StopBits=stopbits;
if (BuildCommDCBW(szBaud, &m_dcb))
{
if (!SetCommState(m_hComm, &m_dcb))
ProcessErrorMessage(L"SetCommState()");
}
else
ProcessErrorMessage(L"BuildCommDCBW()");;
}
else
ProcessErrorMessage(L"GetCommState()");
}
else
ProcessErrorMessage(L"SetCommMask()");
}
else
ProcessErrorMessage(L"SetCommTimeouts()");
delete [] szPort;
//delete [] szBaud;
// 清空發送及接受緩沖區
PurgeComm(m_hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
// 解鎖臨界變數
LeaveCriticalSection(&m_csCommunicationSync);
TRACE("Initialisation for communicationport %d completed.\nUse Startmonitor to communicate.\n", portnr);
return TRUE;
}
void CMySerial::ReceiveChar(CMySerial* port, COMSTAT comstat)
{
BOOL bRead = TRUE;
BOOL bResult = TRUE;
DWORD dwError = 0;
DWORD BytesRead = 0;
unsigned char RXBuff;
for (;;)
{
// Gain ownership of the comm port critical section.
// This process guarantees no other part of this program
// is using the port object.
EnterCriticalSection(&port->m_csCommunicationSync);
// ClearCommError() will update the COMSTAT structure and
// clear any other errors.
bResult = ClearCommError(port->m_hComm, &dwError, &comstat);
LeaveCriticalSection(&port->m_csCommunicationSync);
// start forever loop. I use this type of loop because I
// do not know at runtime how many loops this will have to
// run. My solution is to start a forever loop and to
// break out of it when I have processed all of the
// data available. Be careful with this approach and
// be sure your loop will exit.
// My reasons for this are not as clear in this sample
// as it is in my production code, but I have found this
// solutiion to be the most efficient way to do this.
if (comstat.cbInQue == 0)
{
// break out when all bytes have been read
break;
}
EnterCriticalSection(&port->m_csCommunicationSync);
if (bRead)
{
bResult = ReadFile(port->m_hComm, // Handle to COMM port
&RXBuff, // RX Buffer Pointer
1, // Read one byte
&BytesRead, // Stores number of bytes read
&port->m_ov); // pointer to the m_ov structure
// deal with the error code
if (!bResult)
{
switch (dwError = GetLastError())
{
case ERROR_IO_PENDING:
{
// asynchronous i/o is still in progress
// Proceed on to GetOverlappedResults();
bRead = FALSE;
break;
}
default:
{
// Another error has occured. Process this error.
port->ProcessErrorMessage(L"ReadFile()");
break;
}
}
}
else
{
// ReadFile() returned complete. It is not necessary to call GetOverlappedResults()
bRead = TRUE;
}
} // close if (bRead)
if (!bRead)
{
bRead = TRUE;
bResult = GetOverlappedResult(port->m_hComm, // Handle to COMM port
&port->m_ov, // Overlapped structure
&BytesRead, // Stores number of bytes read
TRUE); // Wait flag
// deal with the error code
if (!bResult)
{
port->ProcessErrorMessage(L"GetOverlappedResults() in ReadFile()");
}
} // close if (!bRead)
LeaveCriticalSection(&port->m_csCommunicationSync);
// notify parent that a byte was received
::SendMessage((port->m_pParent)->m_hWnd, WM_COMM_RXCHAR, (WPARAM) RXBuff, (LPARAM) port->m_nPortNr);
} // end forever loop
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/117258.html
