|
@@ -7,7 +7,14 @@ CSynSerial::CSynSerial(void) :m_hSerialPort(NULL)
|
|
|
{
|
|
|
memset(&m_dcb, 0, sizeof(DCB));
|
|
|
memset(&m_cts, 0, sizeof(COMMTIMEOUTS));
|
|
|
- memset(&m_szSerialPort, 0, sizeof(TCHAR)*MAX_PORT_LEN);
|
|
|
+ memset(&m_szSerialPort, 0, sizeof(TCHAR) * MAX_PORT_LEN);
|
|
|
+
|
|
|
+ // 初始化重叠对象;
|
|
|
+ ZeroMemory(&m_wrOverlapped, sizeof(m_wrOverlapped));
|
|
|
+ if (m_wrOverlapped.hEvent != NULL) {
|
|
|
+ ResetEvent(m_wrOverlapped.hEvent);
|
|
|
+ m_wrOverlapped.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
CSynSerial::~CSynSerial(void)
|
|
@@ -15,15 +22,14 @@ CSynSerial::~CSynSerial(void)
|
|
|
CloseSerialPort();
|
|
|
}
|
|
|
|
|
|
-BOOL CSynSerial::OpenSerialPort(IN CONST BYTE & byCommPort, IN CONST DWORD & dwBaudRate, IN CONST BYTE & bySize, IN CONST BYTE & byParity, IN CONST BYTE & byStopBits, IN CONST BYTE & byStartAddr, IN CONST INT & nInterval)
|
|
|
+BOOL CSynSerial::OpenSerialPort(IN CONST BYTE& byCommPort, IN CONST DWORD& dwBaudRate, IN CONST BYTE& bySize, IN CONST BYTE& byParity, IN CONST BYTE& byStopBits, IN CONST BYTE& byStartAddr, IN CONST INT& nInterval)
|
|
|
{
|
|
|
ASSERT(byCommPort);
|
|
|
CloseSerialPort();
|
|
|
|
|
|
_stprintf_s(m_szSerialPort, _T("\\\\.\\com%d"), (int)byCommPort);
|
|
|
- m_hSerialPort = CreateFile(m_szSerialPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, NULL, NULL);
|
|
|
- if (m_hSerialPort == INVALID_HANDLE_VALUE)
|
|
|
- {
|
|
|
+ m_hSerialPort = CreateFile(m_szSerialPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
|
|
|
+ if (m_hSerialPort == INVALID_HANDLE_VALUE) {
|
|
|
// 打开串口失败;
|
|
|
DWORD dwError = GetLastError();
|
|
|
return FALSE;
|
|
@@ -32,16 +38,18 @@ BOOL CSynSerial::OpenSerialPort(IN CONST BYTE & byCommPort, IN CONST DWORD & dwB
|
|
|
BOOL bResult = FALSE;
|
|
|
// SetupComm设置缓冲区大小;
|
|
|
bResult = SetupComm(m_hSerialPort, m_dwInQueue, m_dwOutQueue);
|
|
|
- if (!bResult)
|
|
|
- {
|
|
|
+ if (!bResult) {
|
|
|
+ CloseHandle(m_hSerialPort);
|
|
|
+ m_hSerialPort = INVALID_HANDLE_VALUE;
|
|
|
DWORD dwError = GetLastError();
|
|
|
return FALSE;
|
|
|
}
|
|
|
|
|
|
// 在串口读写之前,清除缓冲区;
|
|
|
bResult = PurgeComm(m_hSerialPort, PURGE_TXCLEAR | PURGE_RXCLEAR);
|
|
|
- if (!bResult)
|
|
|
- {
|
|
|
+ if (!bResult) {
|
|
|
+ CloseHandle(m_hSerialPort);
|
|
|
+ m_hSerialPort = INVALID_HANDLE_VALUE;
|
|
|
DWORD dwError = GetLastError();
|
|
|
return FALSE;
|
|
|
}
|
|
@@ -49,8 +57,9 @@ BOOL CSynSerial::OpenSerialPort(IN CONST BYTE & byCommPort, IN CONST DWORD & dwB
|
|
|
// GetCommState获取设备控制块状态;
|
|
|
memset(&m_dcb, 0, sizeof(DCB));
|
|
|
bResult = GetCommState(m_hSerialPort, &m_dcb);
|
|
|
- if (!bResult)
|
|
|
- {
|
|
|
+ if (!bResult) {
|
|
|
+ CloseHandle(m_hSerialPort);
|
|
|
+ m_hSerialPort = INVALID_HANDLE_VALUE;
|
|
|
DWORD dwError = GetLastError();
|
|
|
return FALSE;
|
|
|
}
|
|
@@ -70,16 +79,18 @@ BOOL CSynSerial::OpenSerialPort(IN CONST BYTE & byCommPort, IN CONST DWORD & dwB
|
|
|
// SetCommState设置设备的控制块状态;
|
|
|
memset(&m_cts, 0, sizeof(COMMTIMEOUTS));
|
|
|
bResult = SetCommState(m_hSerialPort, &m_dcb);
|
|
|
- if (!bResult)
|
|
|
- {
|
|
|
+ if (!bResult) {
|
|
|
+ CloseHandle(m_hSerialPort);
|
|
|
+ m_hSerialPort = INVALID_HANDLE_VALUE;
|
|
|
DWORD dwError = GetLastError();
|
|
|
return FALSE;
|
|
|
}
|
|
|
|
|
|
// 获取设备的超时值;
|
|
|
bResult = GetCommTimeouts(m_hSerialPort, &m_cts);
|
|
|
- if (!bResult)
|
|
|
- {
|
|
|
+ if (!bResult) {
|
|
|
+ CloseHandle(m_hSerialPort);
|
|
|
+ m_hSerialPort = INVALID_HANDLE_VALUE;
|
|
|
DWORD dwError = GetLastError();
|
|
|
return FALSE;
|
|
|
}
|
|
@@ -93,8 +104,9 @@ BOOL CSynSerial::OpenSerialPort(IN CONST BYTE & byCommPort, IN CONST DWORD & dwB
|
|
|
|
|
|
// 设置设备的超时值;
|
|
|
bResult = SetCommTimeouts(m_hSerialPort, &m_cts);
|
|
|
- if (!bResult)
|
|
|
- {
|
|
|
+ if (!bResult) {
|
|
|
+ CloseHandle(m_hSerialPort);
|
|
|
+ m_hSerialPort = INVALID_HANDLE_VALUE;
|
|
|
DWORD dwError = GetLastError();
|
|
|
return FALSE;
|
|
|
}
|
|
@@ -107,9 +119,8 @@ BOOL CSynSerial::ReOpenSerialPort()
|
|
|
ASSERT(_tcslen(m_szSerialPort));
|
|
|
CloseSerialPort();
|
|
|
|
|
|
- m_hSerialPort = CreateFile(m_szSerialPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, NULL, NULL);
|
|
|
- if (m_hSerialPort == INVALID_HANDLE_VALUE)
|
|
|
- {
|
|
|
+ m_hSerialPort = CreateFile(m_szSerialPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
|
|
|
+ if (m_hSerialPort == INVALID_HANDLE_VALUE) {
|
|
|
// 打开串口失败;
|
|
|
DWORD dwError = GetLastError();
|
|
|
return FALSE;
|
|
@@ -118,16 +129,18 @@ BOOL CSynSerial::ReOpenSerialPort()
|
|
|
BOOL bResult = FALSE;
|
|
|
// SetupComm设置缓冲区大小;
|
|
|
bResult = SetupComm(m_hSerialPort, m_dwInQueue, m_dwOutQueue);
|
|
|
- if (!bResult)
|
|
|
- {
|
|
|
+ if (!bResult) {
|
|
|
+ CloseHandle(m_hSerialPort);
|
|
|
+ m_hSerialPort = INVALID_HANDLE_VALUE;
|
|
|
DWORD dwError = GetLastError();
|
|
|
return FALSE;
|
|
|
}
|
|
|
|
|
|
// 在串口读写之前,清除缓冲区;
|
|
|
bResult = PurgeComm(m_hSerialPort, PURGE_TXCLEAR | PURGE_RXCLEAR);
|
|
|
- if (!bResult)
|
|
|
- {
|
|
|
+ if (!bResult) {
|
|
|
+ CloseHandle(m_hSerialPort);
|
|
|
+ m_hSerialPort = INVALID_HANDLE_VALUE;
|
|
|
DWORD dwError = GetLastError();
|
|
|
return FALSE;
|
|
|
}
|
|
@@ -135,16 +148,18 @@ BOOL CSynSerial::ReOpenSerialPort()
|
|
|
// SetCommState设置设备的控制块状态;
|
|
|
memset(&m_cts, 0, sizeof(COMMTIMEOUTS));
|
|
|
bResult = SetCommState(m_hSerialPort, &m_dcb);
|
|
|
- if (!bResult)
|
|
|
- {
|
|
|
+ if (!bResult) {
|
|
|
+ CloseHandle(m_hSerialPort);
|
|
|
+ m_hSerialPort = INVALID_HANDLE_VALUE;
|
|
|
DWORD dwError = GetLastError();
|
|
|
return FALSE;
|
|
|
}
|
|
|
|
|
|
// 设置设备的超时值;
|
|
|
bResult = SetCommTimeouts(m_hSerialPort, &m_cts);
|
|
|
- if (!bResult)
|
|
|
- {
|
|
|
+ if (!bResult) {
|
|
|
+ CloseHandle(m_hSerialPort);
|
|
|
+ m_hSerialPort = INVALID_HANDLE_VALUE;
|
|
|
DWORD dwError = GetLastError();
|
|
|
return FALSE;
|
|
|
}
|
|
@@ -156,10 +171,10 @@ void CSynSerial::CloseSerialPort()
|
|
|
{
|
|
|
if (m_hSerialPort != NULL && m_hSerialPort != INVALID_HANDLE_VALUE)
|
|
|
CloseHandle(m_hSerialPort);
|
|
|
- m_hSerialPort = NULL;
|
|
|
+ m_hSerialPort = INVALID_HANDLE_VALUE;
|
|
|
}
|
|
|
|
|
|
-BOOL CSynSerial::SetSerialPort(IN CONST DWORD & dwBaudRate, IN CONST BYTE & byByteSize, IN CONST BYTE & byParity, IN CONST BYTE & byStopBits, IN CONST BYTE & byStartAddr, IN CONST DWORD & dwInQueue, IN CONST DWORD & dwOutQueue)
|
|
|
+BOOL CSynSerial::SetSerialPort(IN CONST DWORD& dwBaudRate, IN CONST BYTE& byByteSize, IN CONST BYTE& byParity, IN CONST BYTE& byStopBits, IN CONST BYTE& byStartAddr, IN CONST DWORD& dwInQueue, IN CONST DWORD& dwOutQueue)
|
|
|
{
|
|
|
if (!IsOpen())
|
|
|
return FALSE;
|
|
@@ -168,8 +183,7 @@ BOOL CSynSerial::SetSerialPort(IN CONST DWORD & dwBaudRate, IN CONST BYTE & byBy
|
|
|
// GetCommState获取设备控制块状态;
|
|
|
memset(&m_dcb, 0, sizeof(DCB));
|
|
|
bResult = GetCommState(m_hSerialPort, &m_dcb);
|
|
|
- if (!bResult)
|
|
|
- {
|
|
|
+ if (!bResult) {
|
|
|
DWORD dwError = GetLastError();
|
|
|
return FALSE;
|
|
|
}
|
|
@@ -189,16 +203,14 @@ BOOL CSynSerial::SetSerialPort(IN CONST DWORD & dwBaudRate, IN CONST BYTE & byBy
|
|
|
// SetCommState设置设备的控制块状态;
|
|
|
memset(&m_cts, 0, sizeof(COMMTIMEOUTS));
|
|
|
bResult = SetCommState(m_hSerialPort, &m_dcb);
|
|
|
- if (!bResult)
|
|
|
- {
|
|
|
+ if (!bResult) {
|
|
|
DWORD dwError = GetLastError();
|
|
|
return FALSE;
|
|
|
}
|
|
|
|
|
|
// 获取设备的超时值;
|
|
|
bResult = GetCommTimeouts(m_hSerialPort, &m_cts);
|
|
|
- if (!bResult)
|
|
|
- {
|
|
|
+ if (!bResult) {
|
|
|
DWORD dwError = GetLastError();
|
|
|
return FALSE;
|
|
|
}
|
|
@@ -212,8 +224,7 @@ BOOL CSynSerial::SetSerialPort(IN CONST DWORD & dwBaudRate, IN CONST BYTE & byBy
|
|
|
|
|
|
// 设置设备的超时值;
|
|
|
bResult = SetCommTimeouts(m_hSerialPort, &m_cts);
|
|
|
- if (!bResult)
|
|
|
- {
|
|
|
+ if (!bResult) {
|
|
|
DWORD dwError = GetLastError();
|
|
|
return FALSE;
|
|
|
}
|
|
@@ -221,15 +232,15 @@ BOOL CSynSerial::SetSerialPort(IN CONST DWORD & dwBaudRate, IN CONST BYTE & byBy
|
|
|
return TRUE;
|
|
|
}
|
|
|
|
|
|
-void CSynSerial::SetSerialDCB(IN CONST DCB & dcb)
|
|
|
+void CSynSerial::SetSerialDCB(IN CONST DCB& dcb)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
-void CSynSerial::SetSerialCommTimeouts(IN CONST COMMTIMEOUTS & commTimeouts)
|
|
|
+void CSynSerial::SetSerialCommTimeouts(IN CONST COMMTIMEOUTS& commTimeouts)
|
|
|
{
|
|
|
}
|
|
|
|
|
|
-DWORD CSynSerial::WriteComm(IN BYTE * pWirteBuf, IN CONST INT32 nWriteSize)
|
|
|
+DWORD CSynSerial::WriteComm(IN BYTE* pWirteBuf, IN CONST INT32 nWriteSize)
|
|
|
{
|
|
|
if (!IsOpen())
|
|
|
return 0;
|
|
@@ -238,24 +249,35 @@ DWORD CSynSerial::WriteComm(IN BYTE * pWirteBuf, IN CONST INT32 nWriteSize)
|
|
|
{
|
|
|
return 0;
|
|
|
}
|
|
|
-
|
|
|
+
|
|
|
DWORD dwErrorFlags;
|
|
|
DWORD dwBytesWritten = 0; // 实际写入的字节数;
|
|
|
// 写前, 清除错误;
|
|
|
COMSTAT ComStat;
|
|
|
- ClearCommError(m_hSerialPort, &dwErrorFlags, &ComStat);
|
|
|
+ ClearCommError(m_hSerialPort, &dwErrorFlags, &ComStat);
|
|
|
// 写前,清空缓存区;
|
|
|
PurgeComm(m_hSerialPort, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
|
|
|
- if ( !WriteFile(m_hSerialPort, pWirteBuf, nWriteSize, &dwBytesWritten, NULL) )
|
|
|
- {
|
|
|
+ if (!WriteFile(m_hSerialPort, pWirteBuf, nWriteSize, &dwBytesWritten, &m_wrOverlapped)) {
|
|
|
DWORD dwError = GetLastError();
|
|
|
- }
|
|
|
+ if (ERROR_IO_PENDING == GetLastError()) {
|
|
|
+ while (!GetOverlappedResult(m_hSerialPort, &m_wrOverlapped, &dwBytesWritten, FALSE)) {
|
|
|
+ dwError = GetLastError();
|
|
|
+ if (ERROR_IO_PENDING == dwError || dwError == ERROR_IO_INCOMPLETE) {
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+ else {
|
|
|
+ ClearCommError(m_hSerialPort, &dwError, NULL);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
|
|
|
// 返回写入字节数;
|
|
|
return dwBytesWritten;
|
|
|
}
|
|
|
|
|
|
-DWORD CSynSerial::ReadComm(IN BYTE *pReadBuf, IN CONST DWORD& dwReadSize, WORD timeout /* = 300 */)
|
|
|
+DWORD CSynSerial::ReadComm(IN BYTE* pReadBuf, IN CONST DWORD& dwReadSize, WORD timeout /* = 300 */)
|
|
|
{
|
|
|
if (!IsOpen())
|
|
|
return 0;
|
|
@@ -265,41 +287,20 @@ DWORD CSynSerial::ReadComm(IN BYTE *pReadBuf, IN CONST DWORD& dwReadSize, WORD t
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
- DWORD dwBytesRead = 0;
|
|
|
- DWORD dwErrorFlags = 0;
|
|
|
- // ReadFile前,使用ClearCommError清除错误;
|
|
|
- COMSTAT ComStat = {0};
|
|
|
- DWORD dwLastLen = 0;
|
|
|
- ULONGLONG ulTick = GetTickCount64();
|
|
|
- // 直到有数据为止,超时3秒;
|
|
|
- while (true)
|
|
|
- {// cbInQue表示输入缓冲区的字节数;
|
|
|
- Sleep(timeout);
|
|
|
- if (GetTickCount64() - ulTick > 3000)
|
|
|
- break;
|
|
|
- ClearCommError(m_hSerialPort, &dwErrorFlags, &ComStat);
|
|
|
- // 防止读一次没读完,再读一次;二次长度一样表示读完;
|
|
|
- if (ComStat.cbInQue != 0 && dwLastLen == ComStat.cbInQue)
|
|
|
- break;
|
|
|
- dwLastLen = ComStat.cbInQue;
|
|
|
- }
|
|
|
-
|
|
|
- if (ComStat.cbInQue == 0)
|
|
|
- {
|
|
|
- // 串口超时,无数据返回;
|
|
|
- return 0;
|
|
|
+ DWORD dwError = 0;
|
|
|
+ DWORD dwRealRead;
|
|
|
+ if (!ClearCommError(m_hSerialPort, &dwError, NULL)) {
|
|
|
+ PurgeComm(m_hSerialPort, PURGE_TXABORT | PURGE_TXCLEAR);
|
|
|
}
|
|
|
|
|
|
- dwBytesRead = ComStat.cbInQue;
|
|
|
- if (dwReadSize < dwBytesRead)
|
|
|
- {
|
|
|
- dwBytesRead = dwReadSize;
|
|
|
- }
|
|
|
-
|
|
|
- if (ReadFile(m_hSerialPort, pReadBuf, dwBytesRead, &dwBytesRead, NULL))
|
|
|
- {
|
|
|
- return (INT)dwBytesRead;
|
|
|
+ if (!ReadFile(m_hSerialPort, pReadBuf, dwReadSize, &dwRealRead, &m_wrOverlapped)) {
|
|
|
+ if (GetLastError() == ERROR_IO_PENDING) {
|
|
|
+ while (!GetOverlappedResult(m_hSerialPort, &m_wrOverlapped, &dwRealRead, FALSE)) {
|
|
|
+ dwError = GetLastError();
|
|
|
+ printf("\t 码值=%d, 长度=%d, 内容=%s \n\n", dwError, dwRealRead, pReadBuf);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
- return dwBytesRead;
|
|
|
+ return dwRealRead;
|
|
|
}
|