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 ...
随机推荐
- C#Graphics画图
public Form1() { InitializeComponent(); } private void button1_Click(object sender, EventArgs e) { G ...
- ECMAscript v.s. Javascript
ECMAscript是一种中性的语言,中性表示与所处环境(宿主环境)无关(客户端/服务器/浏览器),它仅仅是一个纯粹意义上的语言. ECMAscript-262定义了这门语言的基础,或者说规则(比如说 ...
- C++ 知识点1
typedef的陷阱 严格来说typedef并不是定义别名,而是定义类型,比如typedef int a;按照大部分书本说来,就是把a看做int,这种说法初学看来是正确的,也易于理解,但是遇到type ...
- 关于在transform下的子元素设置fixed无效的困惑
最近的项目是要实现一个点击显示隐藏边栏的效果,而且需要边栏随着滚动而滚动. 思路简单,不就一个css的动画和一个position为fixed,搞定!但不想,设为fixed的子元素竟然无法fixed,这 ...
- SSH-key密钥生成
为了能够不用输入密码访问git库(github/gitlab),需要使用ssh key ssh-keygen -t rsa -C "<your email address>&qu ...
- xml文件操作
public static XmlDocument getDoc(String path)//加载xml文档 { XmlDocument doc = new XmlDocument(); doc.Lo ...
- dll signing issue
1. Verify if a dll has been signed sn.exe -v module.dll Scenario: sometimes for security reasons, a ...
- JS中的phototype是JS中比较难理解的一个部分
本文基于下面几个知识点: 1 原型法设计模式 在.Net中可以使用clone()来实现原型法 原型法的主要思想是,现在有1个类A,我想要创建一个类B,这个类是以A为原型的,并且能进行扩展.我们称B的原 ...
- java实现双端链表
PS:双端链表(持有对最后一个节点的引用,允许表尾操作与表头操作等效的功能) public class DoubleLinkedList { //节点类 static class Node { pub ...
- (摘)C#comboBox绑定数据
C#中comboBox用代码绑定数据库中在某一列.用处:跟radioButton联系在一起,可以根据radioButton在选择而在comboBox显示出不同的值. private void radi ...