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 ...
随机推荐
- easyui之combobox(不定时补充)
1,combobox的valuefeild和textfeild这两个属性,可以理解为键值对,即:键valuefeild:值textfeild textfeild是文本框内显示的值,如果要取文本框内的值 ...
- (原)python使用ctypes调用C/C++接口
转载请注明出处: http://www.cnblogs.com/darkknightzh/p/6135514.html 参考网址: https://docs.python.org/2/library/ ...
- poi实现Excel导出
最近做了一个导出Excel的小功能,以前没接触过,现在分享下自己的代码,想让各位帮忙看看有啥地方可以优化,也方便自己以后查阅... 首先是excelAction的代码: /** * excelActi ...
- hibernate级联保存,更新个人遇到的问题
在级联更新的时候,数据库中的数据是增加的,只是外键不存在,导致这样的问题产生的原因是,字表主键ID没有添加到集合中,导致Hibernate找不到子项而执行更新.
- Html5 学习之 Html5功能判断插件 Modernizr
---恢复内容开始--- Modernizr 浏览器对HTML5和CSS3开发的功能检测类库 由于当前用户使用的浏览器版本较多,对H5和CSS3的支持也各不相同.前端的开发者,在使用一些新的特性的时候 ...
- dedecms _ 当前位置问题的代码
{dede:field name='position' runphp='yes'} $tc=" > "; $tf=split($tc,@me); $tn=count($tf) ...
- 文成小盆友python-num10 socketserver 原理相关。
本节主要内容: 1.IO多路复用 2.多线程多进程 3.小知识点补充(python中作用域相关) 4.socketserver源码分析补充 一.IO多路复用 I/O多路复用指:通过一种机制,可以监视多 ...
- Leakcanary
一.什么是内存泄漏 垃圾回收器无法回收应被回收的对象比如:在Activity生命周期过程中,旋转屏幕时应新建activity,原activity应被销毁.但如果线程一直在引用此activity,则会出 ...
- Android 源码编译环境搭建(64位Ubuntu)各种依赖包安装
1.准备: 普通PC(要求能上网), PC的操作系统Ubuntu 10.04 LTS(64位的),已经下载好的Android 1.6_r1的源代码. 2.Linux的依赖package安装: 为了更快 ...
- bindingredirect 没有效果
在搞在线聊天室的时候用到了SignalR 1.1.4,依赖于Newtonsoft.Json 4.5.0.0. 而我另外的dll又依赖Newtonsoft.Json 6.0.0.0 我只引用6.0.0. ...