Windows vc++读取串口信息(同步读取,伪异步)

个人文章地址

1. 头文件

#pragma once
#include <string>
#include <memory>
#include <tuple>
#include <functional>
#include <thread>

template<typename T>
class Thread {
private:
	// 线程指针
	std::shared_ptr<std::thread> m_threadPtr = nullptr;

	// 子线程状态
	bool status = false;
private:
	void Start(){
		status = true;
	}
	void End(){
		if (m_threadPtr != nullptr && m_threadPtr->joinable())
		{
			m_threadPtr->join();
		}
		m_threadPtr = nullptr;
		status = false;
	}
public:

	bool Run(std::function<T> fn){
		if (status)
		{
			return false;
		}
		m_threadPtr = std::make_shared<std::thread>(fn);
		Start();
		return true;
	}

	~Thread(){
		if (m_threadPtr != nullptr)
		{
			End();
			m_threadPtr = nullptr;
		}
	}
};

class Serial
{
private:
	HANDLE m_portHandle = (HANDLE)-1;
	// 配置串口信息
	struct _DCB m_dcb;
	// in:输入缓冲区大小
	unsigned long in;
	// out:输出缓冲区大小
	unsigned long out;
	// 超时配置
	COMMTIMEOUTS TimeOuts;
	std::shared_ptr<Thread<void()>> threadPtr = nullptr;
public:
private:

	// 描述: 打开串口
	// lpFileName: 串口名
	// ways: 打开方式;0同步方式,          FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED 重叠方式
	void OpenPort(LPCTSTR lpFileName, int ways);
public:
	// 描述: 同步打开串口
	// lpFileName: 串口名
	void SyncOpenPort(LPCTSTR lpFileName);

	// 描述: 配置串口信息
	// rata: 波特率
	// fParity: 奇偶校验;若此成员为1,允许奇偶校验检查
	// byteSize:通信字节位数,4—8
	// parity:指定奇偶校验方法;EVENPARITY 偶校验; NOPARITY 无校验; MARKPARITY 标记校验; ODDPARITY 奇校验;
	// stopBits: 停止位的位数;ONESTOPBIT 1位停止位; TWOSTOPBITS 2位停止位; ON5STOPBITS 1.5位停止位;
	void SetConfig(int rate, unsigned long fParity, unsigned char byteSize, unsigned char parity, unsigned char stopBits);

	// 描述:设置输入输出缓冲区大小
	// in:输入缓冲区大小
	// out:输出缓冲区大小
	void SetBuffSize(unsigned long in = 1024, unsigned long out = 1024);

	// 设置超时配置
	// rTimeOut:读间隔超时
	// rMTimeOut:读时间系数
	// rConstant:读时间常量
	// wMTimeOut:写时间系数
	// wConstant:写时间常量
	void SetTimeOut(
		unsigned long rTimeOut = 500,
		unsigned long rMTimeOut = 500,
		unsigned long rConstant = 5000,
		unsigned long wMTimeOut = 500,
		unsigned long wConstant = 100
		);

	// 同步读取串口信息
	// 返回值: index 1:读取结果
	//		   index 2: 读取的字节数
	std::tuple<std::string, unsigned long> SyncRead();

	// 同步写串口
	// outStr:写入的字符串
	void SyncWrite(std::string outStr);

	// 关闭串口
	void ClosePort();

	// 关闭串口
	~Serial();

	// 描述:伪异步读串口
	// fn: 读取到后执行的功能体
	void FakeAsynRead(std::function<void(std::string)> fn);

};


2. 具体实现

#include "stdafx.h"
#include "Serial.h"


// 描述: 打开串口
// lpFileName: 串口名
// ways: 打开方式;0同步方式,          FILE_ATTRIBUTE_NORMAL | FILE_FLAG_OVERLAPPED 重叠方式
void Serial::OpenPort(LPCTSTR lpFileName, int ways){
	if (m_portHandle != (HANDLE)-1)
	{
		CloseHandle(m_portHandle);
		this->m_portHandle = (HANDLE)-1;
	}
	HANDLE hCom; //全局变量,串口句柄
	hCom = CreateFile(lpFileName,//COM1口
		GENERIC_READ | GENERIC_WRITE, //允许读和写
		0, //独占方式
		NULL,
		OPEN_EXISTING, //打开而不是创建
		ways, //同步方式
		NULL);
	if (hCom == (HANDLE)-1)
	{
		AfxMessageBox(_T("打开COM失败!"));
		return;
	}
	this->m_portHandle = hCom;
}
// 描述: 同步打开串口
// lpFileName: 串口名
void Serial::SyncOpenPort(LPCTSTR lpFileName){
	OpenPort(lpFileName, 0);
}

// 描述: 配置串口信息
// rata: 波特率
// fParity: 奇偶校验;若此成员为1,允许奇偶校验检查
// byteSize:通信字节位数,4—8
// parity:指定奇偶校验方法;EVENPARITY 偶校验; NOPARITY 无校验; MARKPARITY 标记校验; ODDPARITY 奇校验;
// stopBits: 停止位的位数;ONESTOPBIT 1位停止位; TWOSTOPBITS 2位停止位; ON5STOPBITS 1.5位停止位;

void Serial::SetConfig(int rate, unsigned long fParity, unsigned char byteSize, unsigned char parity, unsigned char stopBits){
	this->m_dcb.BaudRate = rate;
	this->m_dcb.fParity = fParity;
	this->m_dcb.ByteSize = byteSize;
	this->m_dcb.Parity = parity;
	this->m_dcb.StopBits = stopBits;
	SetCommState(this->m_portHandle, &this->m_dcb);
}

// 描述:设置输入输出缓冲区大小
// in:输入缓冲区大小
// out:输出缓冲区大小
void Serial::SetBuffSize(unsigned long in, unsigned long out){
	SetupComm(this->m_portHandle, // 通信设备的句柄
		this->in = in, // 输入缓冲区的大小(字节数) 
		this->out = out // 输出缓冲区的大小(字节数) 
		);
}


// 设置超时配置
// rTimeOut:读间隔超时
// rMTimeOut:读时间系数
// rConstant:读时间常量
// wMTimeOut:写时间系数
// wConstant:写时间常量
void Serial::SetTimeOut(
	unsigned long rTimeOut,
	unsigned long rMTimeOut,
	unsigned long rConstant,
	unsigned long wMTimeOut,
	unsigned long wConstant
	){
	TimeOuts.ReadIntervalTimeout = rTimeOut; //读间隔超时
	TimeOuts.ReadTotalTimeoutMultiplier = rMTimeOut; //读时间系数
	TimeOuts.ReadTotalTimeoutConstant = rConstant;//读时间常量
	//设定写超时
	TimeOuts.WriteTotalTimeoutMultiplier = wMTimeOut;// 写时间系数
	TimeOuts.WriteTotalTimeoutConstant = wConstant; //写时间常量
	//设置超时
	SetCommTimeouts(this->m_portHandle, &TimeOuts);
}

// 同步读取串口信息
// 返回值: index 1:读取结果
//		   index 2: 读取的字节数
std::tuple<std::string, unsigned long> Serial::SyncRead(){
	char *str = new char[this->in + 1]{'\0'};
	unsigned long  wCount;//读取的字节数
	BOOL bReadStat;
	bReadStat = ReadFile(this->m_portHandle, str, this->in, &wCount, NULL);
	if (!bReadStat) {
		AfxMessageBox(_T("读串口失败!"));
	}
	str[wCount] = '\0';
	auto rs = std::string(str);
	delete[]str;
	return std::tuple<std::string, unsigned long>(rs, wCount);
}

// 同步写串口
// outStr:写入的字符串
void Serial::SyncWrite(std::string outStr){
	// 写缓冲区大小
	unsigned long  dwBytesWrite = outStr.size();
	COMSTAT ComStat;
	// 错误标志
	unsigned long dwErrorFlags;
	//写状态
	BOOL bWriteStat;
	// 清楚错误信息
	ClearCommError(this->m_portHandle, &dwErrorFlags, &ComStat);
	// 开始写
	bWriteStat = WriteFile(this->m_portHandle, outStr.c_str(), dwBytesWrite, &dwBytesWrite, NULL);

	if (!bWriteStat) {
		AfxMessageBox(_T("写串口失败!"));
	}
	// 清空串口的输入输出缓冲区
	PurgeComm(this->m_portHandle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR);
}

// 关闭串口
void Serial::ClosePort(){
	if (this->m_portHandle != (HANDLE)-1)
	{
		CloseHandle(this->m_portHandle);
		this->m_portHandle = (HANDLE)-1;
	}
}

// 关闭串口
Serial::~Serial(){
	if (this->m_portHandle != (HANDLE)-1)
	{
		CloseHandle(this->m_portHandle);
		this->m_portHandle = (HANDLE)-1;
	}
}

// 描述:伪异步读串口
// fn: 读取到后执行的功能体
void Serial::FakeAsynRead(std::function<void(std::string)> fn){

	Serial* isMy = this;

	std::function<void()> asynFun = [=](){
		std::string rs = std::get<0>(isMy->SyncRead());
		fn(rs);
	};
	threadPtr = std::make_shared<Thread<void()>>();
	threadPtr->Run(asynFun);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值