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
  • 相关阅读:
    Reactive Extensions (Rx) 入门(5) —— Rx的事件编程
    Reactive Extensions (Rx) 入门(4) —— Rx的事件编程
    Reactive Extensions (Rx) 入门(3) —— Rx的事件编程
    Reactive Extensions (Rx) 入门(2) —— 安装 Reactive Extensions
    Reactive Extensions (Rx) 入门(1) —— Reactive Extensions 概要
    Xamarin NuGet 缓存包导致 already added : Landroid/support/annotation/AnimRes 问题解决方案
    Android 系统Action大全
    Xamarin Forms 实现发送通知点击跳转
    如何理解灰度发布
    推荐一款分布式微服务框架 Surging
  • 原文地址:https://www.cnblogs.com/-jpp/p/4773856.html
Copyright © 2011-2022 走看看