VC 串口通信类

为了节省时间,我就贴出来吧

头文件 SerialPort.h

 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 once
14 #include "StdAfx.h"
15 
16 #define FC_DTRDSR       0x01
17 #define FC_RTSCTS       0x02
18 #define FC_XONXOFF      0x04
19 #define ASCII_BEL       0x07
20 #define ASCII_BS        0x08
21 #define ASCII_LF        0x0A
22 #define ASCII_CR        0x0D
23 #define ASCII_XON       0x11
24 #define ASCII_XOFF      0x13
25 
26 class CSerial
27 {
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     vector<string> GetPortNames(); 
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 };
View Code

 

实现文件 SerialPort.cpp

  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 /*    返回: vector<string>  
 45 /*  创建人:            日期                内容
 46 /*    金胖胖        2015年8月27日        新建
 47 /***************************************************/
 48 vector<string> CSerial::GetPortNames()
 49 {
 50     vector<string> 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<size; i++ ){
212         this->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_TXCLEAR
287 }
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<Total;i++)
317     {
318         itoa(lpDataBuffer[i],OneNumber,16);
319 
320         if(strlen(OneNumber) < 2)
321         {
322             OneNumber[2] = OneNumber[1];
323             OneNumber[1] = OneNumber[0];
324             OneNumber[0] = '0';
325         }
326         ReturnStr+=OneNumber;
327         ReturnStr+=",";
328         memset(OneNumber,0,5);
329     }
330 
331     return ReturnStr;
332 }
View Code

 

posted @ 2015-08-31 19:13  金胖胖  阅读(758)  评论(0编辑  收藏  举报