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;
}
VC 串口通信类的更多相关文章
- 串口通信类,WPF
参考之前的资料,写了一个自己常用的串口类, 字符串发送类型用了两种方式,char[] 和byte[] : 数据接收也是采用两种 char[] 和byte[] 两种. 类代码贴出来: public cl ...
- c#串口通信类代码可以直接调用
文章首发于浩瀚先森博客 直接上代码 public struct SerialPara { private string portName; public string PortNameSetGet { ...
- 一个由印度人编写的VC串口类
http://www.cnblogs.com/lwngreat/p/4098374.html 软件介绍 一个由印度人编写的VC串口类(也是一种VC串口控件),他还配合这个类写了VC 串口通信方面的一些 ...
- (转载)用vs2010开发基于VC++的MFC 串口通信一*****两台电脑同一个串口号之间的通信
此文章以visual C++数据採集与串口通信測控应用实战为參考教程 此文章适合VC++串口通信入门 一.页面布局及加入控件 1, 安装好vs2010如图 2, 新建一个基于VC++的MFC项目com ...
- boost实现串口通信(一):小试牛刀
/************************************************************************/ /* 功能:boost实现串口通信类 */ /* ...
- Qt 串口通信
在Qt5之前,串口通信基本依赖于第三方库,下面是我曾接触过的串口通信类库: 名称 语言 平台 QextSerialPort QT C++ Win/Linux http://sourceforge. ...
- java 串口通信 代码
下面是我自己实现的串口接收的类,串口发送比较简单,就直接发送就可以了.下面的这个类可以直接使用. package com.boomdts.weather_monitor.util; import ja ...
- Qt串口通信
1. Qt串口通信类QSerialPort 在Qt5的的更新中,新增了串口通信的相关接口类QSerialPort,这使得在开发者在使用Qt进行UI开发时,可以更加简单有效地实现串口通信的相关功能. 开 ...
- C\C++串口通信编程的一点技术记录
新工作接的第一个活,要写一个配合设备调试的上位机程序. 除了MFC界面的部分,就是要处理几条命令. 串口通信部分代码借鉴的是这一篇文章:http://blog.sina.com.cn/s/blog_a ...
随机推荐
- nginx 配置文件解析(一)
nginx.conf user nginx; # nginx服务的运行用户 worker_processes ; # 启动进程数,通常设置成和CPU的数量相等 error_log /var/log/n ...
- html+css布局小练习w3cfuns
虽然花了很长时间,但是也知道了不少,这次也不像以前了,不知道怎么下手,虽然是照着图片做,不过也做出来了图片来自w3cfuns:网站图片url 看了w3cfuns的两天驾驭DIV+CSS 这个网站对新 ...
- Python新手学习基础之运算符——算术运算符
算术运算符 之前文章在介绍变量类型的时候,其实已经用过了很多算术符,比如+.-.*././/.** 等,除此之外,还有一个符号是之前内容没提到的,就是 % ,用来返回除法余数的运算符号. 假设有变量x ...
- Sql数据保存到Excel文件中
public string ExportExcel( DataSet ds,string saveFileName) { try { if (ds == null) return "数据库为 ...
- Python 升级
1.到官网下载对于的版本: 2.下载之后并解压出来,编译: tar xf python.xx.xx.tar.xz sudo mkdir /usr/local/python ./configure -- ...
- 命令行工具命令 - run包到手机里
命令行工具命令 你完全可以选择不输入以下这些命令,执行这些命令的结果与在 Android Studio 中单击"运行"按钮是一样的. chmod +x gradlew - 此命令只 ...
- 关于css中overflow的一些理解
在做移动端开发的时候,遇到过这么个问题:要把图片进行放大,但有时候图片比较长,一个手机的版面看不了,于是需要用到overflow的属性,刚开始用了overflow-y:scroll, 于是问题来了,如 ...
- [转]IBInspectable / IBDesignable
原文:http://www.cocoachina.com/ios/20150227/11202.html 无论陈词滥调多少次,比起一个需要我们记住并且输入什么的界面来说,如果替换成我们能够看见并可控制 ...
- Method Swizzling以及AOP编程:在运行时进行代码注入-备用
概述 今天我们主要讨论iOS runtime中的一种黑色技术,称为Method Swizzling.字面上理解Method Swizzling可能比较晦涩难懂,毕竟不是中文,不过你可以理解为“移花接木 ...
- mobile js
5个jQuery的备选轻量级移动客户端开发(Mobile development)类库 http://www.gbin1.com/technology/jquerymobile/20120423mob ...