VC 串口通信类

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

头文件 SerialPort.h

 /***************************************************************************************************
* SerialPort.h
*
* 功 能:串口通讯类
* 类 名:CSerialPort
*
* Ver 变更日期 负责人 变更内容
* ─────────────────────────────────────────────────────
* V1.0.0.0 2015年8月27日 金胖胖 新建
*
*****************************************************************************************************/ #pragma once
#include "StdAfx.h" #define FC_DTRDSR 0x01
#define FC_RTSCTS 0x02
#define FC_XONXOFF 0x04
#define ASCII_BEL 0x07
#define ASCII_BS 0x08
#define ASCII_LF 0x0A
#define ASCII_CR 0x0D
#define ASCII_XON 0x11
#define ASCII_XOFF 0x13 class CSerial
{
public:
CSerial();
~CSerial(); // 打开串口
BOOL Open( int nPort = , int nBaud = ); // 关闭串口
BOOL Close( void ); // 读取数据
int ReadData( void *, int ); //发送数据
int SendData( const char *, int ); //
int ReadDataWaiting( void ); // 是否打开串口
BOOL IsOpened( void ); // 清空缓冲区
void ClearBuffer(void); // 获取计算机中的所有串口号
vector<string> GetPortNames(); // 十六进制数据 转换到 字符串
CString HexToStr(unsigned char *lpDataBuffer,int Total);
protected: BOOL WriteCommByte( unsigned char );
HANDLE m_hIDComDev; // 串口文件句柄
OVERLAPPED m_OverlappedRead;
OVERLAPPED m_OverlappedWrite;
BOOL m_bOpened; // 是否打开标识
};

实现文件 SerialPort.cpp

 /***************************************************************************************************
* Serial.cpp
*
* 功 能:串口通讯类
* 类 名:CSerial
* 参考文献:http://blog.csdn.net/zw0558/article/details/4465835
* 参考文献:http://blog.csdn.net/cp1300/article/details/40591699
* 参考文献:http://dev.21tx.com/2001/08/01/10054.shtml
* Ver 变更日期 负责人 变更内容
* ─────────────────────────────────────────────────────
* V1.0.0.0 2015年8月27日 金胖胖 新建
*
*****************************************************************************************************/
#pragma region Include #include "stdafx.h"
#include "Serial.h"
CRITICAL_SECTION sec; #pragma endregion Include #pragma region 构造 析构函数 CSerial::CSerial()
{ memset( &this->m_OverlappedRead, , sizeof( OVERLAPPED ) );
memset( &this->m_OverlappedWrite, , sizeof( OVERLAPPED ) );
this->m_hIDComDev = NULL;
this->m_bOpened = FALSE; } CSerial::~CSerial()
{
this->Close();
} #pragma endregion 构造 析构函数 /***************************************************/
/* 函数: 获取计算机中的所有串口号
/* 返回: vector<string>
/* 创建人: 日期 内容
/* 金胖胖 2015年8月27日 新建
/***************************************************/
vector<string> CSerial::GetPortNames()
{
vector<string> vecArr; int i = ;
CHAR Name[];
UCHAR szPortName[];
LONG Status;
DWORD dwIndex = ;
DWORD dwName;
DWORD dwSizeofPortName;
DWORD Type;
HKEY hKey;
CString strSerialList[]; // 临时定义 256 个字符串组,因为系统最多也就 256 个
LPCTSTR data_Set="HARDWARE\\DEVICEMAP\\SERIALCOMM\\";
dwName = sizeof(Name);
dwSizeofPortName = sizeof(szPortName);
long ret0 = RegOpenKeyEx(HKEY_LOCAL_MACHINE, data_Set, , KEY_READ, &hKey); //打开一个制定的注册表键,成功返回ERROR_SUCCESS即“0”值
if(ret0 == ERROR_SUCCESS)
{
do
{
Status = RegEnumValue(hKey, dwIndex++, Name, &dwName, NULL, &Type, szPortName, &dwSizeofPortName);//读取键值
if((Status == ERROR_SUCCESS)||(Status == ERROR_MORE_DATA))
{
strSerialList[i] = CString(szPortName); // 串口字符串保存
vecArr.push_back(strSerialList[i].GetBuffer());
i++;// 串口计数
}
//每读取一次dwName和dwSizeofPortName都会被修改
//注意一定要重置,否则会出现很离奇的错误,本人就试过因没有重置,出现先插入串口号大的(如COM4),再插入串口号小的(如COM3),此时虽能发现两个串口,但都是同一串口号(COM4)的问题,同时也读不了COM大于10以上的串口
dwName = sizeof(Name);
dwSizeofPortName = sizeof(szPortName);
} while((Status == ERROR_SUCCESS)||(Status == ERROR_MORE_DATA));
RegCloseKey(hKey);
}
return vecArr ;
} /***************************************************/
/* 函数: 打开串口
/* 参数: int 串口号
/* 参数: int 波特率
/* 返回: BOOL 是否成功
/* 创建人: 日期 内容
/* 金胖胖 2015年8月31日 新建
/***************************************************/
BOOL CSerial::Open( int nPort, int nBaud )
{ DWORD dwErrorFlags;
COMSTAT ComStat; ::ClearCommError( this->m_hIDComDev, &dwErrorFlags, &ComStat ); if( this->m_bOpened ) return( TRUE ); char szPort[];
char szComParams[];
DCB dcb; wsprintf( szPort, "COM%d", nPort );
this->m_hIDComDev = ::CreateFile( szPort, GENERIC_READ | GENERIC_WRITE, , NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, NULL );
if( this->m_hIDComDev == NULL ) return( FALSE ); memset( &this->m_OverlappedRead, , sizeof( OVERLAPPED ) );
memset( &this->m_OverlappedWrite, , sizeof( OVERLAPPED ) ); COMMTIMEOUTS CommTimeOuts;
CommTimeOuts.ReadIntervalTimeout = 0xFFFFFFFF;
CommTimeOuts.ReadTotalTimeoutMultiplier = ;
CommTimeOuts.ReadTotalTimeoutConstant = ;
CommTimeOuts.WriteTotalTimeoutMultiplier = ;
CommTimeOuts.WriteTotalTimeoutConstant = ;
::SetCommTimeouts( this->m_hIDComDev, &CommTimeOuts ); wsprintf( szComParams, "COM%d:%d,n,8,1", nPort, nBaud ); this->m_OverlappedRead.hEvent = ::CreateEvent( NULL, TRUE, FALSE, NULL );
this->m_OverlappedWrite.hEvent = ::CreateEvent( NULL, TRUE, FALSE, NULL ); dcb.DCBlength = sizeof( DCB );
::GetCommState( m_hIDComDev, &dcb );
dcb.BaudRate = nBaud;
dcb.ByteSize = ;
unsigned char ucSet;
ucSet = (unsigned char) ( ( FC_RTSCTS & FC_DTRDSR ) != );
ucSet = (unsigned char) ( ( FC_RTSCTS & FC_RTSCTS ) != );
ucSet = (unsigned char) ( ( FC_RTSCTS & FC_XONXOFF ) != );
if( !::SetCommState( this->m_hIDComDev, &dcb ) ||!::SetupComm( this->m_hIDComDev, , ) ||this->m_OverlappedRead.hEvent == NULL ||this->m_OverlappedWrite.hEvent == NULL )
{
DWORD dwError = GetLastError();
if( this->m_OverlappedRead.hEvent != NULL ) ::CloseHandle( this->m_OverlappedRead.hEvent );
if( this->m_OverlappedWrite.hEvent != NULL ) ::CloseHandle( this->m_OverlappedWrite.hEvent );
::CloseHandle( this->m_hIDComDev );
return( FALSE );
} this->m_bOpened = TRUE;
return( this->m_bOpened ); } /***************************************************/
/* 函数: 关闭函数
/* 返回: BOOL 是否成功
/* 创建人: 日期 内容
/* 金胖胖 2015年8月31日 新建
/***************************************************/
BOOL CSerial::Close( void )
{ if( !this->m_bOpened || this->m_hIDComDev == NULL ) return( TRUE ); if( this->m_OverlappedRead.hEvent != NULL ) ::CloseHandle( this->m_OverlappedRead.hEvent );
if( this->m_OverlappedWrite.hEvent != NULL ) ::CloseHandle( this->m_OverlappedWrite.hEvent );
::CloseHandle( this->m_hIDComDev );
this->m_bOpened = FALSE;
this->m_hIDComDev = NULL;
return( TRUE ); } /***************************************************/
/* 函数: 写串口数据 字节
/* 参数: unsigned char 字节
/* 返回: BOOL 是否成功
/* 创建人: 日期 内容
/* 金胖胖 2015年8月31日 新建
/***************************************************/
BOOL CSerial::WriteCommByte( unsigned char ucByte )
{
BOOL bWriteStat;
DWORD dwBytesWritten; bWriteStat = ::WriteFile( this->m_hIDComDev, (LPSTR) &ucByte, , &dwBytesWritten, &m_OverlappedWrite );
if( !bWriteStat && ( GetLastError() == ERROR_IO_PENDING ) ){
if( ::WaitForSingleObject( this->m_OverlappedWrite.hEvent, ) ) dwBytesWritten = ;
else{
::GetOverlappedResult( this->m_hIDComDev, &this->m_OverlappedWrite, &dwBytesWritten, FALSE );
this->m_OverlappedWrite.Offset += dwBytesWritten;
}
} return( TRUE ); } /***************************************************/
/* 函数: 发送数据
/* 参数: const char 缓冲区
/* 参数: int 长度
/* 返回: int 发送的成功的长度
/* 创建人: 日期 内容
/* 金胖胖 2015年8月31日 新建
/***************************************************/
int CSerial::SendData( const char *buffer, int size )
{ if( !this->m_bOpened || this->m_hIDComDev == NULL ) return( ); DWORD dwBytesWritten = ;
int i;
for( i=; i<size; i++ ){
this->WriteCommByte( buffer[i] );
dwBytesWritten++;
}
return( (int) dwBytesWritten );
} /***************************************************/
/* 函数: 清除错误信息 获取通讯状态
/* 返回: int 通讯状态
/* 创建人: 日期 内容
/* 金胖胖 2015年8月31日 新建
/***************************************************/
int CSerial::ReadDataWaiting( void )
{ if( !this->m_bOpened || this->m_hIDComDev == NULL ) return( ); DWORD dwErrorFlags;
COMSTAT ComStat; ::ClearCommError( this->m_hIDComDev, &dwErrorFlags, &ComStat ); return( (int) ComStat.cbInQue ); } /***************************************************/
/* 函数: 读取数据
/* 参数: void * 缓冲区
/* 参数: int 缓冲区长度
/* 返回: int 读到的字节数
/* 创建人: 日期 内容
/* 金胖胖 2015年8月31日 新建
/***************************************************/
int CSerial::ReadData( void *buffer, int limit )
{ if( !this->m_bOpened || this->m_hIDComDev == NULL )
return( ); BOOL bReadStatus;
DWORD dwBytesRead, dwErrorFlags;
COMSTAT ComStat; ::ClearCommError( this->m_hIDComDev, &dwErrorFlags, &ComStat );//清空错误信息
if( !ComStat.cbInQue )
return( ); dwBytesRead = (DWORD) ComStat.cbInQue;
if( limit < (int) dwBytesRead )
dwBytesRead = (DWORD) limit; bReadStatus = ::ReadFile( this->m_hIDComDev, buffer, dwBytesRead, &dwBytesRead, &m_OverlappedRead );
if( !bReadStatus )
{
if( GetLastError() == ERROR_IO_PENDING )
{
::WaitForSingleObject( this->m_OverlappedRead.hEvent, );
return( (int) dwBytesRead );
}
return( );
} return( (int) dwBytesRead );
} /***************************************************/
/* 函数: 清空缓冲区
/* 返回: void
/* 创建人: 日期 内容
/* 金胖胖 2015年8月31日 新建
/***************************************************/
void CSerial::ClearBuffer()
{
::PurgeComm(this->m_hIDComDev,PURGE_RXABORT | PURGE_RXCLEAR );//| PURGE_TXABORT | PURGE_TXCLEAR
} /***************************************************/
/* 函数: 串口是否打开
/* 返回: BOOL 是否打开
/* 创建人: 日期 内容
/* 金胖胖 2015年8月31日 新建
/***************************************************/
BOOL CSerial::IsOpened( void )
{
return( this->m_bOpened );
} /***************************************************/
/* 函数: 十六进制数据 转换到 字符串
/* 参数: unsigned char * 缓冲区
/* 参数: int 长度
/* 返回: CString 转换成功的字符串
/* 创建人: 日期 内容
/* 金胖胖 2015年8月31日 新建
/***************************************************/
CString CSerial::HexToStr(unsigned char *lpDataBuffer,int Total)
{
CString ReturnStr;
char OneNumber[]; ReturnStr.Empty();
memset(OneNumber,,); for(int i=;i<Total;i++)
{
itoa(lpDataBuffer[i],OneNumber,); if(strlen(OneNumber) < )
{
OneNumber[] = OneNumber[];
OneNumber[] = OneNumber[];
OneNumber[] = '';
}
ReturnStr+=OneNumber;
ReturnStr+=",";
memset(OneNumber,,);
} return ReturnStr;
}
上一篇:Ext使用中问题总结


下一篇:hyperledge工具-cryptogen