📄 _com.h
字号:
/*
串口基础类库(WIN32) ver 0.1
编译器 : BC++ 5; C++ BUILDER 4, 5, 6, X; VC++ 5, 6; VC.NET; GCC;
class _base_com : 虚基类 基本串口接口;
class _sync_com : 同步I/O 串口类;
class _asyn_com : 异步I/O 串口类;
class _thread_com : 异步I/O 辅助读监视线程 可转发窗口消息 串口类(可继承虚函数on_receive用于读操作);
class _com : _thread_com 同名
copyright(c) 2004.8 llbird wushaojian@21cn.com
*/
/*
Example :
*/
#ifndef _COM_H_
#define _COM_H_
#pragma warning(disable: 4530)
#pragma warning(disable: 4786)
#pragma warning(disable: 4800)
#include <cassert>
#include <strstream>
#include <algorithm>
#include <exception>
#include <iomanip>
#include <fstream>
using namespace std;
#include "GPSParam.h"
#include <windows.h>
class _base_com //虚基类 基本串口接口
{
protected:
volatile int _port; //串口号
volatile HANDLE _com_handle;//串口句柄
char _com_str[20];
DCB _dcb; //波特率,停止位,等
COMMTIMEOUTS _co; // 超时时间
virtual bool open_port() = 0;
void init() //初始化
{
memset(_com_str, 0, 20);
memset(&_co, 0, sizeof(_co));
memset(&_dcb, 0, sizeof(_dcb));
_dcb.DCBlength = sizeof(_dcb);
_com_handle = INVALID_HANDLE_VALUE;
}
virtual bool setup_port()
{
if(!is_open())
return false;
if(!SetupComm(_com_handle, 8192, 8192))
return false; //设置推荐缓冲区
if(!GetCommTimeouts(_com_handle, &_co))
return false;
_co.ReadIntervalTimeout = 0xFFFFFFFF;
_co.ReadTotalTimeoutMultiplier = 0;
_co.ReadTotalTimeoutConstant = 0;
_co.WriteTotalTimeoutMultiplier = 0;
_co.WriteTotalTimeoutConstant = 2000;
if(!SetCommTimeouts(_com_handle, &_co))
return false; //设置超时时间
if(!PurgeComm(_com_handle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ))
return false; //清空串口缓冲区
return true;
}
inline void set_com_port(int port)
{
char p[12];
_port = port;
strcpy(_com_str, "\\\\.\\COM");
ltoa(_port, p, 10);
strcat(_com_str, p);
}
public:
_base_com()
{
init();
}
virtual ~_base_com()
{
close();
}
//设置串口参数:波特率,停止位,等 支持设置字符串 "9600, 8, n, 1"
bool set_state(char *set_str)
{
if(is_open())
{
if(!GetCommState(_com_handle, &_dcb))
return false;
if(!BuildCommDCB(set_str, &_dcb))
return false;
return SetCommState(_com_handle, &_dcb) == TRUE;
}
return false;
}
//设置内置结构串口参数:波特率,停止位
bool set_state(int BaudRate = 9600, int ByteSize = 8, int Parity = NOPARITY, int StopBits = ONESTOPBIT, char EvtChar='\n' )
{
if(is_open())
{
if(!GetCommState(_com_handle, &_dcb))
return false;
_dcb.BaudRate = BaudRate;
_dcb.ByteSize = ByteSize;
_dcb.Parity = Parity;
_dcb.StopBits = StopBits;
_dcb.EvtChar = EvtChar;
return SetCommState(_com_handle, &_dcb) == TRUE;
}
return false;
}
//打开串口 缺省 9600, 8, n, 1
inline bool open(int port)
{
return open(port, 9600);
}
//打开串口 缺省 baud_rate, 8, n, 1
inline bool open(int port, int baud_rate)
{
if(port < 1 || port > 1024)
return false;
set_com_port(port);
if(!open_port())
return false;
if(!setup_port())
return false;
return set_state(baud_rate);
}
//打开串口
inline bool open(int port, char *set_str)
{
if(port < 1 || port > 1024)
return false;
set_com_port(port);
if(!open_port())
return false;
if(!setup_port())
return false;
return set_state(set_str);
}
inline bool set_buf(int in, int out)
{
return is_open() ? SetupComm(_com_handle, in, out) : false;
}
//关闭串口
inline virtual void close()
{
if(is_open())
{
CloseHandle(_com_handle);
_com_handle = INVALID_HANDLE_VALUE;
}
}
//判断串口是或打开
inline bool is_open()
{
return _com_handle != INVALID_HANDLE_VALUE;
}
//获得串口句炳
HANDLE get_handle()
{
return _com_handle;
}
operator HANDLE()
{
return _com_handle;
}
};
class _sync_com : public _base_com
{
protected:
//打开串口
virtual bool open_port()
{
if(is_open())
close();
_com_handle = CreateFile(
_com_str,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL ,
NULL
);
assert(is_open());
return is_open();//检测串口是否成功打开
}
public:
_sync_com()
{
}
//同步读
int read(char *buf, int buf_len)
{
if(!is_open())
return 0;
buf[0] = '\0';
COMSTAT stat;
DWORD error;
if(ClearCommError(_com_handle, &error, &stat) && error > 0) //清除错误
{
PurgeComm(_com_handle, PURGE_RXABORT | PURGE_RXCLEAR); /*清除输入缓冲区*/
return 0;
}
unsigned long r_len = 0;
buf_len = min(buf_len - 1, (int)stat.cbInQue);
if(!ReadFile(_com_handle, buf, buf_len, &r_len, NULL))
r_len = 0;
buf[r_len] = '\0';
return r_len;
}
//同步写
int write(char *buf, int buf_len)
{
if(!is_open() || !buf)
return 0;
DWORD error;
if(ClearCommError(_com_handle, &error, NULL) && error > 0) //清除错误
PurgeComm(_com_handle, PURGE_TXABORT | PURGE_TXCLEAR);
unsigned long w_len = 0;
if(!WriteFile(_com_handle, buf, buf_len, &w_len, NULL))
w_len = 0;
return w_len;
}
//同步写
inline int write(char *buf)
{
assert(buf);
return write(buf, strlen(buf));
}
//同步写, 支持部分类型的流输出
template<typename T>
_sync_com& operator << (T x)
{
strstream s;
s << x;
write(s.str(), s.pcount());
return *this;
}
};
class _asyn_com : public _base_com
{
protected:
OVERLAPPED _ro, _wo; // 重叠I/O
virtual bool open_port()
{
if(is_open())
close();
_com_handle = CreateFile(
_com_str,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED, //重叠I/O
NULL
);
//assert(is_open());
return is_open();//检测串口是否成功打开
}
public:
_asyn_com()
{
memset(&_ro, 0, sizeof(_ro));
memset(&_wo, 0, sizeof(_wo));
_ro.hEvent = CreateEvent(NULL, true, false, NULL);
assert(_ro.hEvent != INVALID_HANDLE_VALUE);
_wo.hEvent = CreateEvent(NULL, true, false, NULL);
assert(_wo.hEvent != INVALID_HANDLE_VALUE);
}
virtual ~_asyn_com()
{
close();
if(_ro.hEvent != INVALID_HANDLE_VALUE)
CloseHandle(_ro.hEvent);
if(_wo.hEvent != INVALID_HANDLE_VALUE)
CloseHandle(_wo.hEvent);
}
//异步读
int read(char *buf, int buf_len, int time_wait = 20)
{
if(!is_open())
return 0;
buf[0] = '\0';
COMSTAT stat;
DWORD error;
if(ClearCommError(_com_handle, &error, &stat) && error > 0) //清除错误
{
PurgeComm(_com_handle, PURGE_RXABORT | PURGE_RXCLEAR); /*清除输入缓冲区*/
return 0;
}
if(!stat.cbInQue)// 缓冲区无数据
return 0;
unsigned long r_len = 0;
buf_len = min((int)(buf_len ), (int)stat.cbInQue);
if(!ReadFile(_com_handle, buf, buf_len, &r_len, &_ro)) //2000 下 ReadFile 始终返回 True
{
if(GetLastError() == ERROR_IO_PENDING) // 结束异步I/O
{
//WaitForSingleObject(_ro.hEvent, time_wait); //等待20ms
if(!GetOverlappedResult(_com_handle, &_ro, &r_len, false))
{
if(GetLastError() != ERROR_IO_INCOMPLETE)//其他错误
r_len = 0;
}
}
else
r_len = 0;
}
buf[r_len] = '\0';
return r_len;
}
//异步写
int write(char *buf, int buf_len)
{
if(!is_open())
return 0;
DWORD error;
if(ClearCommError(_com_handle, &error, NULL) && error > 0) //清除错误
PurgeComm(_com_handle, PURGE_TXABORT | PURGE_TXCLEAR);
unsigned long w_len = 0, o_len = 0;
if(!WriteFile(_com_handle, buf, buf_len, &w_len, &_wo))
if(GetLastError() != ERROR_IO_PENDING)
w_len = 0;
return w_len;
}
//异步写
inline int write(char *buf)
{
assert(buf);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -