个人文章地址
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;
unsigned long in;
unsigned long out;
COMMTIMEOUTS TimeOuts;
std::shared_ptr<Thread<void()>> threadPtr = nullptr;
public:
private:
void OpenPort(LPCTSTR lpFileName, int ways);
public:
void SyncOpenPort(LPCTSTR lpFileName);
void SetConfig(int rate, unsigned long fParity, unsigned char byteSize, unsigned char parity, unsigned char stopBits);
void SetBuffSize(unsigned long in = 1024, unsigned long out = 1024);
void SetTimeOut(
unsigned long rTimeOut = 500,
unsigned long rMTimeOut = 500,
unsigned long rConstant = 5000,
unsigned long wMTimeOut = 500,
unsigned long wConstant = 100
);
std::tuple<std::string, unsigned long> SyncRead();
void SyncWrite(std::string outStr);
void ClosePort();
~Serial();
void FakeAsynRead(std::function<void(std::string)> fn);
};
2. 具体实现
#include "stdafx.h"
#include "Serial.h"
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,
GENERIC_READ | GENERIC_WRITE,
0,
NULL,
OPEN_EXISTING,
ways,
NULL);
if (hCom == (HANDLE)-1)
{
AfxMessageBox(_T("打开COM失败!"));
return;
}
this->m_portHandle = hCom;
}
void Serial::SyncOpenPort(LPCTSTR lpFileName){
OpenPort(lpFileName, 0);
}
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);
}
void Serial::SetBuffSize(unsigned long in, unsigned long out){
SetupComm(this->m_portHandle,
this->in = in,
this->out = out
);
}
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);
}
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);
}
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;
}
}
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);
}