#include "stdafx.h"
#include "Serial.h"
using namespace std;
CSerial::CSerial()
{
memset( &m_OverlappedRead, 0, sizeof( OVERLAPPED ) );
memset( &m_OverlappedWrite, 0, sizeof( OVERLAPPED ) );
m_hIDComDev = NULL;
m_bOpened = FALSE;
}
CSerial::~CSerial()
{
Close();
}
BOOL CSerial::Open( int nPort, int nBaud, int nDataBit, int nStopBit )
{
m_strLastError = "";
if( m_bOpened ) return( TRUE );
char szPort[15];
char szComParams[50];
DCB dcb;
////wsprintf( szPort, "COM%d", nPort );
//wsprintf( szPort, "\\\\.\\COM%d", nPort );
//m_hIDComDev = CreateFile( szPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL );
//if( m_hIDComDev == INVALID_HANDLE_VALUE ) return( FALSE );
wsprintf( szPort, "//./COM%d", nPort );//modify by lujuan 051222
m_hIDComDev = CreateFile( szPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL );
if( m_hIDComDev == INVALID_HANDLE_VALUE ) return( FALSE );
memset( &m_OverlappedRead, 0, sizeof( OVERLAPPED ) );
memset( &m_OverlappedWrite, 0, sizeof( OVERLAPPED ) );
COMMTIMEOUTS CommTimeOuts;
CommTimeOuts.ReadIntervalTimeout = -1;
CommTimeOuts.ReadTotalTimeoutMultiplier = -1;
CommTimeOuts.ReadTotalTimeoutConstant = 30000;
CommTimeOuts.WriteTotalTimeoutMultiplier = 0;
CommTimeOuts.WriteTotalTimeoutConstant = 30000;
wsprintf( szComParams, "COM%d: %d, n, %d, %d", nPort, nBaud, nDataBit, nStopBit);
m_OverlappedRead.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
m_OverlappedWrite.hEvent = CreateEvent( NULL, TRUE, FALSE, NULL );
dcb.DCBlength = sizeof( DCB );
GetCommState( m_hIDComDev, &dcb );
BuildCommDCB( szComParams, &dcb );
if( !SetCommState( m_hIDComDev, &dcb ) ||
!SetupComm( m_hIDComDev, 0x20000, 0x20000 ) ||
!SetCommMask( m_hIDComDev, EV_BREAK|EV_CTS|EV_DSR|EV_RLSD ) ||
!SetCommTimeouts( m_hIDComDev, &CommTimeOuts ) ||
m_OverlappedRead.hEvent == NULL ||
m_OverlappedWrite.hEvent == NULL ){
DWORD dwError = GetLastError();
if( m_OverlappedRead.hEvent != NULL ) CloseHandle( m_OverlappedRead.hEvent );
if( m_OverlappedWrite.hEvent != NULL ) CloseHandle( m_OverlappedWrite.hEvent );
CloseHandle( m_hIDComDev );
return( FALSE );
}
m_bOpened = TRUE;
PurgeComm( m_hIDComDev, PURGE_TXABORT | PURGE_RXABORT |
PURGE_TXCLEAR | PURGE_RXCLEAR ) ;
///////打印日志
char buffer[64]={0};
wsprintf( buffer, "USB Serial Port: %d 连接成功!", nPort );
cout<<buffer<<endl;
m_strLastError = buffer;
//////// 手动初始化成员变量
char ch1[4]={'A','B','C','D'};
for(int i=0;i<4;++i)
{
m_pinfo.in_port[i]=ch1[i];
}
string ch2[16]={"01","02","03","04","05","06","07","08","09","10","11","12","13","14","15","16"};
for(int i=0;i<16;++i)
{
m_pinfo.out_port[i]=ch2[i];
}
m_pinfo.port_connect.insert(make_pair('A',"01"));
m_pinfo.port_connect.insert(make_pair('B',"02"));
m_pinfo.port_connect.insert(make_pair('C',"03"));
m_pinfo.port_connect.insert(make_pair('D',"04"));
m_pinfo.dis_out_port="16";
/*********将('A',"01"),('B',"02"),('C',"03"),('D',"04")对应关系执行,然后点亮对应图标**********/
this->DoPortA2B("PORT A 01\n");
this->DoPortA2B("PORT B 02\n");
this->DoPortA2B("PORT C 03\n");
this->DoPortA2B("PORT D 04\n");
return( m_bOpened );
}
BOOL CSerial::Close( void )
{
if( !m_bOpened || m_hIDComDev == NULL ) return( TRUE );
PurgeComm( m_hIDComDev, PURGE_TXABORT | PURGE_RXABORT |
PURGE_TXCLEAR | PURGE_RXCLEAR ) ;
if( m_OverlappedRead.hEvent != NULL ) CloseHandle( m_OverlappedRead.hEvent );
if( m_OverlappedWrite.hEvent != NULL ) CloseHandle( m_OverlappedWrite.hEvent );
CloseHandle( m_hIDComDev );
m_bOpened = FALSE;
m_hIDComDev = NULL;
return( TRUE );
}
BOOL CSerial::WriteCommByte( char ucByte )
{
BOOL bWriteStat;
DWORD dwBytesWritten;
PurgeComm(m_hIDComDev, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
bWriteStat = WriteFile( m_hIDComDev, (LPSTR) &ucByte, 1, &dwBytesWritten, &m_OverlappedWrite );
if( !bWriteStat && ( GetLastError() == ERROR_IO_PENDING ) )
{
if( WaitForSingleObject( m_OverlappedWrite.hEvent, 1000 ) )
dwBytesWritten = 0;
else
{
GetOverlappedResult( m_hIDComDev, &m_OverlappedWrite, &dwBytesWritten, FALSE );
m_OverlappedWrite.Offset += dwBytesWritten;
}
}
return( TRUE );
}
int CSerial::WriteCommBytes(const char * ucBytes, int length )
{
BOOL bWriteStat;
DWORD dwBytesWritten;
PurgeComm(m_hIDComDev, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABORT | PURGE_TXABORT);
bWriteStat = WriteFile( m_hIDComDev, (LPSTR) ucBytes, length, &dwBytesWritten, &m_OverlappedWrite );
if( !bWriteStat && ( GetLastError() == ERROR_IO_PENDING ) )
{
if( WaitForSingleObject( m_OverlappedWrite.hEvent, 1000 ) )
dwBytesWritten = 0;
else
{
GetOverlappedResult( m_hIDComDev, &m_OverlappedWrite, &dwBytesWritten, FALSE );
m_OverlappedWrite.Offset += dwBytesWritten;
}
}
///////打印日志
cout<<"send:"<<ucBytes;
return( dwBytesWritten );
}
int CSerial::SendData( const char *buffer, int size )
{
if( !m_bOpened || m_hIDComDev == NULL ) return( 0 );
DWORD dwBytesWritten = 0;
for( int i=0; i<size; i++ )
{
WriteCommByte( buffer[i] );
dwBytesWritten++;
}
return( (int) dwBytesWritten );
}
int CSerial::ReadDataWaiting( void )
{
if( !m_bOpened || m_hIDComDev == NULL ) return( 0 );
DWORD dwErrorFlags;
COMSTAT ComStat;
ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat );
return( (int) ComStat.cbInQue );
}
int CSerial::ReadData(int limit, string& strBuffer )
{
char buffer[64]={0};
if( !m_bOpened || m_hIDComDev == NULL ) return( 0 );
BOOL bReadStatus;
DWORD dwBytesRead, dwErrorFlags;
COMSTAT ComStat;
ClearCommError( m_hIDComDev, &dwErrorFlags, &ComStat );
if( !ComStat.cbInQue ) return( 0 );
dwBytesRead = (DWORD) ComStat.cbInQue;
if( limit < (int) dwBytesRead ) dwBytesRead = (DWORD) limit;
bReadStatus = ReadFile( m_hIDComDev, buffer, 64, &dwBytesRead, &m_OverlappedRead );
if( !bReadStatus )
{
if( GetLastError() == ERROR_IO_PENDING )
{
WaitForSingleObject( m_OverlappedRead.hEvent, 2000 );
return( (int) dwBytesRead );
}
return( 0 );
}
strBuffer = buffer;
///////打印日志
cout<<"recv:"<<buffer;
return( (int) dwBytesRead );
}
//////////
string extractPortNumber(const string& deviceInfoStr) {
size_t startPos = deviceInfoStr.find("(COM");
if (startPos != string::npos) {
startPos += 4; // 跳过 "(COM" 这四个字符
size_t endPos = deviceInfoStr.find(")", startPos);
if (endPos != string::npos) {
return deviceInfoStr.substr(startPos, endPos - startPos);
}
}
return "";
}
bool CSerial::FindUSBPort() {
HDEVINFO deviceInfoSet = SetupDiGetClassDevs(&GUID_DEVCLASS_PORTS, NULL, NULL, DIGCF_PRESENT);
if (deviceInfoSet == INVALID_HANDLE_VALUE) {
std::cerr << "Failed to get device information set." << std::endl;
return EXIT_FAILURE;
}
SP_DEVINFO_DATA deviceInfoData;
ZeroMemory(&deviceInfoData, sizeof(SP_DEVINFO_DATA));
deviceInfoData.cbSize = sizeof(SP_DEVINFO_DATA);
// 遍历设备
DWORD index = 0;
while (SetupDiEnumDeviceInfo(deviceInfoSet, index, &deviceInfoData)) {
index++;
// 获取设备路径
char devicePath[MAX_PATH];
if (!SetupDiGetDeviceInstanceId(deviceInfoSet, &deviceInfoData, devicePath, sizeof(devicePath), NULL)) {
std::cerr << "Failed to get device path." << std::endl;
continue;
}
//std::cout<<devicePath<<std::endl;
// 从设备路径中提取 COM 口号
// 获取设备注册表属性
CHAR portName[MAX_PATH];
DWORD size = 0;
if (!SetupDiGetDeviceRegistryPropertyA(deviceInfoSet, &deviceInfoData, SPDRP_FRIENDLYNAME, NULL, (PBYTE)portName, sizeof(portName), &size)) {
std::cerr << "Failed to get device registry property." << std::endl;
continue;
}
// 显示 COM 口�