#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 BYTE byCommPort, IN DWORD dwBaudRate, IN BYTE bySize, IN BYTE byParity, IN BYTE byStopBits, IN BYTE byStartAddr, IN 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::OpenSerialPort( IN LPCTSTR lpCommPort, IN DWORD dwBaudRate, IN BYTE bySize, IN BYTE byParity, IN BYTE byStopBits, IN BYTE byStartAddr, IN INT nInterval ) { ASSERT(lpCommPort); CloseSerialPort(); _stprintf_s(m_szSerialPort, _T("\\\\.\\%s"), lpCommPort); 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, WORD timeout /* = 300 */) { 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(timeout); //if (GetTickCount64() - ulTick > timeout) // 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; }