zoukankan      html  css  js  c++  java
  • 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
  • 相关阅读:
    《构建之法》4、17章精读
    2016012005+小学四则运算练习软件项目报告
    Week2-作业一——《构建之法》三章精读之想
    虚拟到现实
    脚踏实地,莫问前程
    2016012010 赵瑞雪 散列函数的应用及其安全性
    结对项目报告
    《构建之法》第四章、第十七章读书笔记
    2016012010+小学四则运算练习软件项目报告
    《构建之法》第一、二、十六章读书笔记
  • 原文地址:https://www.cnblogs.com/-jpp/p/4773856.html
Copyright © 2011-2022 走看看