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 };

实现文件 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 }

时间: 2024-10-11 11:33:58

VC 串口通信类的相关文章

VC++串口通信编程详解

总结来看串口通信原理,(也可以说大多数通信原理也是如此). 通信首先要有个通信,可以简单的把通信看成一个小桶,发送方住水桶里装水,接收方从水桶中取水.如果你要和对方通信首先需要将桶盖打开,再将水装入到桶中,这时接收方才能够从桶中取到水.这里就存在着一定的问题, 1,如果桶盖还没有打开,发送方已经发送了.这时接收方再从桶中取水,肯定取的水不对,会不一部分缺失了.解决方式就是让桶盖打开再往其中加水. 2,但是桶盖何时打开,发送方何时发送,这个不好把握.解决方法:接收方接到数据时,要返回一个应答标志,

串口通信类,WPF

参考之前的资料,写了一个自己常用的串口类, 字符串发送类型用了两种方式,char[] 和byte[] : 数据接收也是采用两种 char[] 和byte[] 两种. 类代码贴出来: public class SerialPortManager { private bool _recStaus = true;//接收状态字 private bool _comPortIsOpen; private void SetAfterClose()//成功关闭串口或串口丢失后的设置 { _comPortIsO

c#串口通信类代码可以直接调用

文章首发于浩瀚先森博客 直接上代码 public struct SerialPara { private string portName; public string PortNameSetGet { get { return portName; } set { portName = value; } } private int baudRate; public int BaudRateSetGet { get { return baudRate; } set { baudRate = valu

一个由印度人编写的VC串口类

软件介绍 一个由印度人编写的VC串口类(也是一种VC串口控件),他还配合这个类写了VC 串口通信方面的一些基础知识,如怎么用VC打开串口,如何对串口进行配置,读串口.写串口等. 这个类有点特别,它没有使用事件驱动原理,它是以查询方式工作的. 简介: 对没有接触过串口通信的VC程序员来说显得非常困难,很久以前我在 codeguru.com 上搜索过串口通信相关信息得到了非常大的帮助,从那时起能编写一个简单易用的VC 串口类是我的梦想. 经过七个月在串口通信编程方面实践经验后,我编写了一个基于API

一个印度人写的VC串口类CSerialCom(有串口基础介绍)

一个由印度人编写的VC串口类(也是一种VC串口控件),他还配合这个类写了VC 串口通信方面的一些基础知识,如怎么用VC打开串口,如何对串口进行配置,读串口.写串口等. 这个类有点特别,它没有使用事件驱动原理,它是以查询方式工作的. 简介: 对没有接触过串口通信的VC程序员来说显得非常困难,很久以前我在 codeguru.com 上搜索过串口通信相关信息得到了非常大的帮助,从那时起能编写一个简单易用的VC 串口类是我的梦想. 经过七个月在串口通信编程方面实践经验后,我编写了一个基于API实现的简单

VC++USB及串口通信程序(附工程)

为公司开发产品测试程序,实际上是基于VC++的USB通信及串口通信.当初编写程序时,网上找了很多资料及程序,感觉大都只是说了一点点,没有一个完整的工程以供其他开发者借鉴,完全要靠开发者东拼西凑,最后凑成一个整体工程,还要在这个工程基础上进行相当艰苦的排查问题.解决问题的调试过程.本人对这一过程极其厌烦,现将走完的以上的"艰苦历程"之后的成果列出,以供后来者借鉴. 这一工程中包含了以下知识点: 1. VC++ USB通信: 2. VC++串口通信: 3. 文件(设备)同步异步操作: 4.

(转载)用vs2010开发基于VC++的MFC 串口通信一*****两台电脑同一个串口号之间的通信

此文章以visual C++数据採集与串口通信測控应用实战为參考教程 此文章适合VC++串口通信入门 一.页面布局及加入控件 1, 安装好vs2010如图 2, 新建一个基于VC++的MFC项目comm 注意:点击ok,然后next,这时候要将application type改成dialog base.接着next到最后一个对话框是将generated dasses改成CcommDlg,然后finish 4, 将新生成的项目的对话框默认dialog edit删去,如图 5,在对话框中加入两个st

Qt 串口通信

在Qt5之前,串口通信基本依赖于第三方库,下面是我曾接触过的串口通信类库: 名称 语言 平台   QextSerialPort QT C++ Win/Linux http://sourceforge.net/projects/qextserialport/files/ QSerialPort QT C++ QT5已经集成 libserial C++ Linux http://files.cnblogs.com/kyyblabla/libserial-0.5.2.gz.7z 以上串口通信类库通信过

串口通信(基础)

参考文章:http://www.cnblogs.com/aierong/archive/2009/08/21/1551589.html http://www.cnblogs.com/procoder/archive/2009/04/07/1430871.html http://blog.csdn.net/cy757/article/details/4474930 SerialPort Class Windows 7 虚拟串口 VSPD 6 最近总结了串口(COM)读写操作的三种方式:第1种方式是