为了节省时间,我就贴出来吧
头文件 SerialPort.h
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 /*************************************************************************************************** 2 * SerialPort.h 3 * 4 * 功 能:串口通讯类 5 * 类 名:CSerialPort 6 * 7 * Ver 变更日期 负责人 变更内容 8 * ───────────────────────────────────────────────────── 9 * V1.0.0.0 2015年8月27日 金胖胖 新建10 *11 *****************************************************************************************************/12 13 #pragma once14 #include "StdAfx.h"15 16 #define FC_DTRDSR 0x0117 #define FC_RTSCTS 0x0218 #define FC_XONXOFF 0x0419 #define ASCII_BEL 0x0720 #define ASCII_BS 0x0821 #define ASCII_LF 0x0A22 #define ASCII_CR 0x0D23 #define ASCII_XON 0x1124 #define ASCII_XOFF 0x1325 26 class CSerial27 {28 public: 29 CSerial();30 ~CSerial();31 32 // 打开串口 33 BOOL Open( int nPort = 2, int nBaud = 9600 ); 34 35 // 关闭串口36 BOOL Close( void ); 37 38 // 读取数据39 int ReadData( void *, int ); 40 41 //发送数据42 int SendData( const char *, int );43 44 // 45 int ReadDataWaiting( void ); 46 47 // 是否打开串口48 BOOL IsOpened( void ); 49 50 // 清空缓冲区51 void ClearBuffer(void); 52 53 // 获取计算机中的所有串口号54 vectorGetPortNames(); 55 56 // 十六进制数据 转换到 字符串57 CString HexToStr(unsigned char *lpDataBuffer,int Total);58 protected:59 60 BOOL WriteCommByte( unsigned char );61 HANDLE m_hIDComDev; // 串口文件句柄62 OVERLAPPED m_OverlappedRead;63 OVERLAPPED m_OverlappedWrite;64 BOOL m_bOpened; // 是否打开标识65 };
实现文件 SerialPort.cpp
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 /*************************************************************************************************** 2 * Serial.cpp 3 * 4 * 功 能:串口通讯类 5 * 类 名:CSerial 6 * 参考文献:http://blog.csdn.net/zw0558/article/details/4465835 7 * 参考文献:http://blog.csdn.net/cp1300/article/details/40591699 8 * 参考文献:http://dev.21tx.com/2001/08/01/10054.shtml 9 * Ver 变更日期 负责人 变更内容 10 * ───────────────────────────────────────────────────── 11 * V1.0.0.0 2015年8月27日 金胖胖 新建 12 * 13 *****************************************************************************************************/ 14 #pragma region Include 15 16 #include "stdafx.h" 17 #include "Serial.h" 18 CRITICAL_SECTION sec; 19 20 #pragma endregion Include 21 22 #pragma region 构造 析构函数 23 24 CSerial::CSerial() 25 { 26 27 memset( &this->m_OverlappedRead, 0, sizeof( OVERLAPPED ) ); 28 memset( &this->m_OverlappedWrite, 0, sizeof( OVERLAPPED ) ); 29 this->m_hIDComDev = NULL; 30 this->m_bOpened = FALSE; 31 32 } 33 34 35 CSerial::~CSerial() 36 { 37 this->Close(); 38 } 39 40 #pragma endregion 构造 析构函数 41 42 /***************************************************/ 43 /* 函数: 获取计算机中的所有串口号 44 /* 返回: vector45 /* 创建人: 日期 内容 46 /* 金胖胖 2015年8月27日 新建 47 /***************************************************/ 48 vector CSerial::GetPortNames() 49 { 50 vector vecArr; 51 52 int i = 0; 53 CHAR Name[25]; 54 UCHAR szPortName[25]; 55 LONG Status; 56 DWORD dwIndex = 0; 57 DWORD dwName; 58 DWORD dwSizeofPortName; 59 DWORD Type; 60 HKEY hKey; 61 CString strSerialList[256]; // 临时定义 256 个字符串组,因为系统最多也就 256 个 62 LPCTSTR data_Set="HARDWARE\\DEVICEMAP\\SERIALCOMM\\"; 63 dwName = sizeof(Name); 64 dwSizeofPortName = sizeof(szPortName); 65 long ret0 = RegOpenKeyEx(HKEY_LOCAL_MACHINE, data_Set, 0, KEY_READ, &hKey); //打开一个制定的注册表键,成功返回ERROR_SUCCESS即“0”值 66 if(ret0 == ERROR_SUCCESS) 67 { 68 do 69 { 70 Status = RegEnumValue(hKey, dwIndex++, Name, &dwName, NULL, &Type, szPortName, &dwSizeofPortName);//读取键值 71 if((Status == ERROR_SUCCESS)||(Status == ERROR_MORE_DATA)) 72 { 73 strSerialList[i] = CString(szPortName); // 串口字符串保存 74 vecArr.push_back(strSerialList[i].GetBuffer(0)); 75 i++;// 串口计数 76 } 77 //每读取一次dwName和dwSizeofPortName都会被修改 78 //注意一定要重置,否则会出现很离奇的错误,本人就试过因没有重置,出现先插入串口号大的(如COM4),再插入串口号小的(如COM3),此时虽能发现两个串口,但都是同一串口号(COM4)的问题,同时也读不了COM大于10以上的串口 79 dwName = sizeof(Name); 80 dwSizeofPortName = sizeof(szPortName); 81 } while((Status == ERROR_SUCCESS)||(Status == ERROR_MORE_DATA)); 82 RegCloseKey(hKey); 83 } 84 return vecArr ; 85 } 86 87 /***************************************************/ 88 /* 函数: 打开串口 89 /* 参数: int 串口号 90 /* 参数: int 波特率 91 /* 返回: BOOL 是否成功 92 /* 创建人: 日期 内容 93 /* 金胖胖 2015年8月31日 新建 94 /***************************************************/ 95 BOOL CSerial::Open( int nPort, int nBaud ) 96 { 97 98 DWORD dwErrorFlags; 99 COMSTAT ComStat;100 101 ::ClearCommError( this->m_hIDComDev, &dwErrorFlags, &ComStat );102 103 if( this->m_bOpened ) return( TRUE );104 105 char szPort[15];106 char szComParams[50];107 DCB dcb;108 109 wsprintf( szPort, "COM%d", nPort );110 this->m_hIDComDev = ::CreateFile( szPort, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL );111 if( this->m_hIDComDev == NULL ) return( FALSE );112 113 memset( &this->m_OverlappedRead, 0, sizeof( OVERLAPPED ) );114 memset( &this->m_OverlappedWrite, 0, sizeof( OVERLAPPED ) );115 116 COMMTIMEOUTS CommTimeOuts;117 CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;118 CommTimeOuts.ReadTotalTimeoutMultiplier = 0;119 CommTimeOuts.ReadTotalTimeoutConstant = 0;120 CommTimeOuts.WriteTotalTimeoutMultiplier = 0;121 CommTimeOuts.WriteTotalTimeoutConstant = 5000;122 ::SetCommTimeouts( this->m_hIDComDev, &CommTimeOuts );123 124 wsprintf( szComParams, "COM%d:%d,n,8,1", nPort, nBaud );125 126 this->m_OverlappedRead.hEvent = ::CreateEvent( NULL, TRUE, FALSE, NULL );127 this->m_OverlappedWrite.hEvent = ::CreateEvent( NULL, TRUE, FALSE, NULL );128 129 dcb.DCBlength = sizeof( DCB );130 ::GetCommState( m_hIDComDev, &dcb );131 dcb.BaudRate = nBaud;132 dcb.ByteSize = 8;133 unsigned char ucSet;134 ucSet = (unsigned char) ( ( FC_RTSCTS & FC_DTRDSR ) != 0 );135 ucSet = (unsigned char) ( ( FC_RTSCTS & FC_RTSCTS ) != 0 );136 ucSet = (unsigned char) ( ( FC_RTSCTS & FC_XONXOFF ) != 0 );137 if( !::SetCommState( this->m_hIDComDev, &dcb ) ||!::SetupComm( this->m_hIDComDev, 10000, 10000 ) ||this->m_OverlappedRead.hEvent == NULL ||this->m_OverlappedWrite.hEvent == NULL )138 {139 DWORD dwError = GetLastError();140 if( this->m_OverlappedRead.hEvent != NULL ) ::CloseHandle( this->m_OverlappedRead.hEvent );141 if( this->m_OverlappedWrite.hEvent != NULL ) ::CloseHandle( this->m_OverlappedWrite.hEvent );142 ::CloseHandle( this->m_hIDComDev );143 return( FALSE );144 }145 146 this->m_bOpened = TRUE;147 return( this->m_bOpened );148 149 }150 151 /***************************************************/152 /* 函数: 关闭函数153 /* 返回: BOOL 是否成功154 /* 创建人: 日期 内容155 /* 金胖胖 2015年8月31日 新建156 /***************************************************/157 BOOL CSerial::Close( void )158 {159 160 if( !this->m_bOpened || this->m_hIDComDev == NULL ) return( TRUE );161 162 if( this->m_OverlappedRead.hEvent != NULL ) ::CloseHandle( this->m_OverlappedRead.hEvent );163 if( this->m_OverlappedWrite.hEvent != NULL ) ::CloseHandle( this->m_OverlappedWrite.hEvent );164 ::CloseHandle( this->m_hIDComDev );165 this->m_bOpened = FALSE;166 this->m_hIDComDev = NULL;167 return( TRUE );168 169 }170 171 /***************************************************/172 /* 函数: 写串口数据 字节173 /* 参数: unsigned char 字节174 /* 返回: BOOL 是否成功175 /* 创建人: 日期 内容176 /* 金胖胖 2015年8月31日 新建177 /***************************************************/178 BOOL CSerial::WriteCommByte( unsigned char ucByte )179 {180 BOOL bWriteStat;181 DWORD dwBytesWritten;182 183 bWriteStat = ::WriteFile( this->m_hIDComDev, (LPSTR) &ucByte, 1, &dwBytesWritten, &m_OverlappedWrite );184 if( !bWriteStat && ( GetLastError() == ERROR_IO_PENDING ) ){185 if( ::WaitForSingleObject( this->m_OverlappedWrite.hEvent, 1000 ) ) dwBytesWritten = 0;186 else{187 ::GetOverlappedResult( this->m_hIDComDev, &this->m_OverlappedWrite, &dwBytesWritten, FALSE );188 this->m_OverlappedWrite.Offset += dwBytesWritten;189 }190 }191 192 return( TRUE );193 194 }195 196 /***************************************************/197 /* 函数: 发送数据198 /* 参数: const char 缓冲区199 /* 参数: int 长度200 /* 返回: int 发送的成功的长度201 /* 创建人: 日期 内容202 /* 金胖胖 2015年8月31日 新建203 /***************************************************/204 int CSerial::SendData( const char *buffer, int size )205 {206 207 if( !this->m_bOpened || this->m_hIDComDev == NULL ) return( 0 );208 209 DWORD dwBytesWritten = 0;210 int i;211 for( i=0; i WriteCommByte( buffer[i] );213 dwBytesWritten++;214 }215 return( (int) dwBytesWritten );216 }217 218 /***************************************************/219 /* 函数: 清除错误信息 获取通讯状态220 /* 返回: int 通讯状态221 /* 创建人: 日期 内容222 /* 金胖胖 2015年8月31日 新建223 /***************************************************/224 int CSerial::ReadDataWaiting( void )225 {226 227 if( !this->m_bOpened || this->m_hIDComDev == NULL ) return( 0 );228 229 DWORD dwErrorFlags;230 COMSTAT ComStat;231 232 ::ClearCommError( this->m_hIDComDev, &dwErrorFlags, &ComStat );233 234 return( (int) ComStat.cbInQue );235 236 }237 238 /***************************************************/239 /* 函数: 读取数据240 /* 参数: void * 缓冲区241 /* 参数: int 缓冲区长度242 /* 返回: int 读到的字节数243 /* 创建人: 日期 内容244 /* 金胖胖 2015年8月31日 新建245 /***************************************************/246 int CSerial::ReadData( void *buffer, int limit )247 {248 249 if( !this->m_bOpened || this->m_hIDComDev == NULL ) 250 return( 0 );251 252 BOOL bReadStatus;253 DWORD dwBytesRead, dwErrorFlags;254 COMSTAT ComStat;255 256 ::ClearCommError( this->m_hIDComDev, &dwErrorFlags, &ComStat );//清空错误信息257 if( !ComStat.cbInQue ) 258 return( 0 );259 260 dwBytesRead = (DWORD) ComStat.cbInQue;261 if( limit < (int) dwBytesRead ) 262 dwBytesRead = (DWORD) limit;263 264 bReadStatus = ::ReadFile( this->m_hIDComDev, buffer, dwBytesRead, &dwBytesRead, &m_OverlappedRead );265 if( !bReadStatus )266 {267 if( GetLastError() == ERROR_IO_PENDING )268 {269 ::WaitForSingleObject( this->m_OverlappedRead.hEvent, 2000 );270 return( (int) dwBytesRead );271 }272 return( 0 );273 }274 275 return( (int) dwBytesRead );276 }277 278 /***************************************************/279 /* 函数: 清空缓冲区 280 /* 返回: void 281 /* 创建人: 日期 内容282 /* 金胖胖 2015年8月31日 新建283 /***************************************************/284 void CSerial::ClearBuffer()285 {286 ::PurgeComm(this->m_hIDComDev,PURGE_RXABORT | PURGE_RXCLEAR );//| PURGE_TXABORT | PURGE_TXCLEAR287 }288 289 /***************************************************/290 /* 函数: 串口是否打开291 /* 返回: BOOL 是否打开292 /* 创建人: 日期 内容293 /* 金胖胖 2015年8月31日 新建294 /***************************************************/295 BOOL CSerial::IsOpened( void )296 {297 return( this->m_bOpened ); 298 }299 300 /***************************************************/301 /* 函数: 十六进制数据 转换到 字符串302 /* 参数: unsigned char * 缓冲区303 /* 参数: int 长度304 /* 返回: CString 转换成功的字符串305 /* 创建人: 日期 内容306 /* 金胖胖 2015年8月31日 新建307 /***************************************************/308 CString CSerial::HexToStr(unsigned char *lpDataBuffer,int Total)309 {310 CString ReturnStr;311 char OneNumber[5];312 313 ReturnStr.Empty();314 memset(OneNumber,0,5);315 316 for(int i=0;i