|
@@ -0,0 +1,305 @@
|
|
|
+#include "StdAfx.h"
|
|
|
+#include "SynSerial.h"
|
|
|
+
|
|
|
+CSynSerial::CSynSerial(void) :m_hSerialPort(NULL)
|
|
|
+, m_dwInQueue(1024)
|
|
|
+, m_dwOutQueue(1024)
|
|
|
+{
|
|
|
+ memset(&m_dcb, 0, sizeof(DCB));
|
|
|
+ memset(&m_cts, 0, sizeof(COMMTIMEOUTS));
|
|
|
+ memset(&m_szSerialPort, 0, sizeof(TCHAR)*MAX_PORT_LEN);
|
|
|
+}
|
|
|
+
|
|
|
+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)
|
|
|
+{
|
|
|
+ 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)
|
|
|
+ {
|
|
|
+ // 打开串口失败;
|
|
|
+ DWORD dwError = GetLastError();
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ BOOL bResult = FALSE;
|
|
|
+ // SetupComm设置缓冲区大小;
|
|
|
+ bResult = SetupComm(m_hSerialPort, m_dwInQueue, m_dwOutQueue);
|
|
|
+ if (!bResult)
|
|
|
+ {
|
|
|
+ DWORD dwError = GetLastError();
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 在串口读写之前,清除缓冲区;
|
|
|
+ bResult = PurgeComm(m_hSerialPort, PURGE_TXCLEAR | PURGE_RXCLEAR);
|
|
|
+ if (!bResult)
|
|
|
+ {
|
|
|
+ DWORD dwError = GetLastError();
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ // GetCommState获取设备控制块状态;
|
|
|
+ memset(&m_dcb, 0, sizeof(DCB));
|
|
|
+ bResult = GetCommState(m_hSerialPort, &m_dcb);
|
|
|
+ if (!bResult)
|
|
|
+ {
|
|
|
+ DWORD dwError = GetLastError();
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ m_dcb.Parity = byParity;
|
|
|
+ if (m_dcb.Parity == NOPARITY)
|
|
|
+ m_dcb.fParity = FALSE;
|
|
|
+ else
|
|
|
+ m_dcb.fParity = TRUE;
|
|
|
+
|
|
|
+ m_dcb.BaudRate = dwBaudRate;
|
|
|
+ m_dcb.ByteSize = bySize;
|
|
|
+ m_dcb.StopBits = byStopBits;
|
|
|
+ if (m_dcb.ByteSize == 8)
|
|
|
+ m_dcb.StopBits = ONESTOPBIT;
|
|
|
+
|
|
|
+ // SetCommState设置设备的控制块状态;
|
|
|
+ memset(&m_cts, 0, sizeof(COMMTIMEOUTS));
|
|
|
+ bResult = SetCommState(m_hSerialPort, &m_dcb);
|
|
|
+ if (!bResult)
|
|
|
+ {
|
|
|
+ DWORD dwError = GetLastError();
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取设备的超时值;
|
|
|
+ bResult = GetCommTimeouts(m_hSerialPort, &m_cts);
|
|
|
+ if (!bResult)
|
|
|
+ {
|
|
|
+ DWORD dwError = GetLastError();
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 两字符之间最大的延时,设置0表示参数不起作用;
|
|
|
+ m_cts.ReadIntervalTimeout = 50;
|
|
|
+ m_cts.ReadTotalTimeoutMultiplier = 100;
|
|
|
+ m_cts.ReadTotalTimeoutConstant = 8000;
|
|
|
+ m_cts.WriteTotalTimeoutMultiplier = 100;
|
|
|
+ m_cts.WriteTotalTimeoutConstant = 5000;
|
|
|
+
|
|
|
+ // 设置设备的超时值;
|
|
|
+ bResult = SetCommTimeouts(m_hSerialPort, &m_cts);
|
|
|
+ if (!bResult)
|
|
|
+ {
|
|
|
+ DWORD dwError = GetLastError();
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ return TRUE;
|
|
|
+}
|
|
|
+
|
|
|
+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)
|
|
|
+ {
|
|
|
+ // 打开串口失败;
|
|
|
+ DWORD dwError = GetLastError();
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ BOOL bResult = FALSE;
|
|
|
+ // SetupComm设置缓冲区大小;
|
|
|
+ bResult = SetupComm(m_hSerialPort, m_dwInQueue, m_dwOutQueue);
|
|
|
+ if (!bResult)
|
|
|
+ {
|
|
|
+ DWORD dwError = GetLastError();
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 在串口读写之前,清除缓冲区;
|
|
|
+ bResult = PurgeComm(m_hSerialPort, PURGE_TXCLEAR | PURGE_RXCLEAR);
|
|
|
+ if (!bResult)
|
|
|
+ {
|
|
|
+ DWORD dwError = GetLastError();
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ // SetCommState设置设备的控制块状态;
|
|
|
+ memset(&m_cts, 0, sizeof(COMMTIMEOUTS));
|
|
|
+ bResult = SetCommState(m_hSerialPort, &m_dcb);
|
|
|
+ if (!bResult)
|
|
|
+ {
|
|
|
+ DWORD dwError = GetLastError();
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 设置设备的超时值;
|
|
|
+ bResult = SetCommTimeouts(m_hSerialPort, &m_cts);
|
|
|
+ if (!bResult)
|
|
|
+ {
|
|
|
+ DWORD dwError = GetLastError();
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ return TRUE;
|
|
|
+}
|
|
|
+
|
|
|
+void CSynSerial::CloseSerialPort()
|
|
|
+{
|
|
|
+ if (m_hSerialPort != NULL && m_hSerialPort != INVALID_HANDLE_VALUE)
|
|
|
+ CloseHandle(m_hSerialPort);
|
|
|
+ m_hSerialPort = NULL;
|
|
|
+}
|
|
|
+
|
|
|
+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;
|
|
|
+
|
|
|
+ BOOL bResult = FALSE;
|
|
|
+ // GetCommState获取设备控制块状态;
|
|
|
+ memset(&m_dcb, 0, sizeof(DCB));
|
|
|
+ bResult = GetCommState(m_hSerialPort, &m_dcb);
|
|
|
+ if (!bResult)
|
|
|
+ {
|
|
|
+ DWORD dwError = GetLastError();
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ m_dcb.Parity = byParity;
|
|
|
+ if (m_dcb.Parity == NOPARITY)
|
|
|
+ m_dcb.fParity = FALSE;
|
|
|
+ else
|
|
|
+ m_dcb.fParity = TRUE;
|
|
|
+
|
|
|
+ m_dcb.BaudRate = dwBaudRate;
|
|
|
+ m_dcb.ByteSize = byByteSize;
|
|
|
+ m_dcb.StopBits = byStopBits;
|
|
|
+ if (m_dcb.ByteSize == 8)
|
|
|
+ m_dcb.StopBits = ONESTOPBIT;
|
|
|
+
|
|
|
+ // SetCommState设置设备的控制块状态;
|
|
|
+ memset(&m_cts, 0, sizeof(COMMTIMEOUTS));
|
|
|
+ bResult = SetCommState(m_hSerialPort, &m_dcb);
|
|
|
+ if (!bResult)
|
|
|
+ {
|
|
|
+ DWORD dwError = GetLastError();
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 获取设备的超时值;
|
|
|
+ bResult = GetCommTimeouts(m_hSerialPort, &m_cts);
|
|
|
+ if (!bResult)
|
|
|
+ {
|
|
|
+ DWORD dwError = GetLastError();
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ // 两字符之间最大的延时,设置0表示参数不起作用;
|
|
|
+ m_cts.ReadIntervalTimeout = 50;
|
|
|
+ m_cts.ReadTotalTimeoutMultiplier = 100;
|
|
|
+ m_cts.ReadTotalTimeoutConstant = 8000;
|
|
|
+ m_cts.WriteTotalTimeoutMultiplier = 100;
|
|
|
+ m_cts.WriteTotalTimeoutConstant = 3000;
|
|
|
+
|
|
|
+ // 设置设备的超时值;
|
|
|
+ bResult = SetCommTimeouts(m_hSerialPort, &m_cts);
|
|
|
+ if (!bResult)
|
|
|
+ {
|
|
|
+ DWORD dwError = GetLastError();
|
|
|
+ return FALSE;
|
|
|
+ }
|
|
|
+
|
|
|
+ return TRUE;
|
|
|
+}
|
|
|
+
|
|
|
+void CSynSerial::SetSerialDCB(IN CONST DCB & dcb)
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+void CSynSerial::SetSerialCommTimeouts(IN CONST COMMTIMEOUTS & commTimeouts)
|
|
|
+{
|
|
|
+}
|
|
|
+
|
|
|
+DWORD CSynSerial::WriteComm(IN BYTE * pWirteBuf, IN CONST INT32 nWriteSize)
|
|
|
+{
|
|
|
+ if (!IsOpen())
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ if (pWirteBuf == NULL || !::AfxIsValidAddress(pWirteBuf, nWriteSize, FALSE))
|
|
|
+ {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ DWORD dwErrorFlags;
|
|
|
+ DWORD dwBytesWritten = 0; // 实际写入的字节数;
|
|
|
+ // 写前, 清除错误;
|
|
|
+ COMSTAT 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) )
|
|
|
+ {
|
|
|
+ DWORD dwError = GetLastError();
|
|
|
+ }
|
|
|
+
|
|
|
+ // 返回写入字节数;
|
|
|
+ return dwBytesWritten;
|
|
|
+}
|
|
|
+
|
|
|
+DWORD CSynSerial::ReadComm(IN BYTE * pReadBuf, IN CONST DWORD & dwReadSize)
|
|
|
+{
|
|
|
+ if (!IsOpen())
|
|
|
+ return 0;
|
|
|
+
|
|
|
+ if (pReadBuf == NULL || !::AfxIsValidAddress(pReadBuf, dwReadSize, FALSE))
|
|
|
+ {
|
|
|
+ return 0;
|
|
|
+ }
|
|
|
+
|
|
|
+ DWORD dwBytesRead = 0;
|
|
|
+ DWORD dwErrorFlags = 0;
|
|
|
+ // ReadFile前,使用ClearCommError清除错误;
|
|
|
+ COMSTAT ComStat = {0};
|
|
|
+ DWORD dwLastLen = 0;
|
|
|
+ ULONGLONG ulTick = GetTickCount64();
|
|
|
+ // 直到有数据为止,超时3秒;
|
|
|
+ while (true)
|
|
|
+ {// cbInQue表示输入缓冲区的字节数;
|
|
|
+ Sleep(150);
|
|
|
+ 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;
|
|
|
+ }
|
|
|
+
|
|
|
+ dwBytesRead = ComStat.cbInQue;
|
|
|
+ if (dwReadSize < dwBytesRead)
|
|
|
+ {
|
|
|
+ dwBytesRead = dwReadSize;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (ReadFile(m_hSerialPort, pReadBuf, dwBytesRead, &dwBytesRead, NULL))
|
|
|
+ {
|
|
|
+ return (INT)dwBytesRead;
|
|
|
+ }
|
|
|
+
|
|
|
+ return dwBytesRead;
|
|
|
+}
|