目录
一、参考:
https://blog.csdn.net/qq_18984151/article/details/79267005
一.自己做
1.Com.h
#pragma once
#ifndef _com_h_
#define _com_h_
#include <tchar.h>
#include <math.h>
#include<iostream>
#include <process.h>
#include <stdio.h>
#include <stdlib.h>
#include <windows.h>
#include <conio.h>
extern BYTE aaaa[4096];
class ComAsy//定义类
{
public:
ComAsy();
~ComAsy();
bool InitCOM(LPCTSTR Port);//打开串口
void UninitCOM(); //关闭串口并清理
//写入数据
bool ComWrite(LPBYTE buf, int &len);
//读取线程
static unsigned int __stdcall OnRecv(void*);
private:
HANDLE m_hCom;
OVERLAPPED m_ovWrite;//用于写入数据
OVERLAPPED m_ovRead;//用于读取数据
OVERLAPPED m_ovWait;//用于等待数据
volatile bool m_IsOpen;//串口是否打开
HANDLE m_Thread;//读取线程句柄
};
#endif
1.Com.cpp
#include "stdafx.h"
#include"Com.h"
/*************************************串口定义***************************************************/
HANDLE hCom;
unsigned char d[8];
DWORD dwBytesWritten = 9;
DWORD dwErrorFlags = 0;
COMSTAT ComStat;
OVERLAPPED m_osWrite;
BOOL bWriteStat;
bool a;
int i;
int flag = 1;
int serialflag = 0;
int receiveSign;
BOOL bRead = TRUE;
BOOL bResult = TRUE;
DWORD dwError = 0;
DWORD BytesRead = 0;
char RXBuff;
BYTE aaaa[4096];
/*****************************************数据定义**************************/
/*****************************************串口类定义**************************/
ComAsy::ComAsy() ://构造函数
m_hCom(INVALID_HANDLE_VALUE),
m_IsOpen(false),
m_Thread(NULL)
{
memset(&m_ovWait, 0, sizeof(m_ovWait));
memset(&m_ovWrite, 0, sizeof(m_ovWrite));
memset(&m_ovRead, 0, sizeof(m_ovRead));
}
ComAsy::~ComAsy()//析构函数
{
UninitCOM();//串口对象被释放时关闭串口
}
bool ComAsy::InitCOM(LPCTSTR Port)//配置串口
{
m_hCom = CreateFile(Port, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING,
FILE_FLAG_OVERLAPPED | FILE_ATTRIBUTE_NORMAL,//设置异步标识
NULL);
if (INVALID_HANDLE_VALUE == m_hCom)
{
return false;
}
SetupComm(m_hCom, 4096, 4096);//设置发送接收缓存
DCB dcb;//96n81模式
GetCommState(m_hCom, &dcb);
dcb.DCBlength = sizeof(dcb);
dcb.BaudRate = 9600;//波特率
dcb.StopBits = ONESTOPBIT;//停止位数为1位
dcb.Parity = 0;//校验方式为无校验
dcb.ByteSize = 8;//数据位为8位
SetCommState(m_hCom, &dcb);//配置串口
PurgeComm(m_hCom, PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR | PURGE_TXABORT);
COMMTIMEOUTS ct;
ct.ReadIntervalTimeout = MAXDWORD;//两字符之间最大的延时,读取无延时,因为有WaitCommEvent等待数据
ct.ReadTotalTimeoutConstant = 0; //读时间常量
ct.ReadTotalTimeoutMultiplier = 0;// 读时间系数
ct.WriteTotalTimeoutMultiplier = 500;// 写时间系数
ct.WriteTotalTimeoutConstant = 5000;// 写时间常量
SetCommTimeouts(m_hCom, &ct);//配置读写超时
//创建事件对象
m_ovRead.hEvent = CreateEvent(NULL, false, false, NULL);
m_ovWrite.hEvent = CreateEvent(NULL, false, false, NULL);
m_ovWait.hEvent = CreateEvent(NULL, false, false, NULL);
SetCommMask(m_hCom, EV_ERR | EV_RXCHAR);//设置接受事件
//创建读取线程
m_Thread = (HANDLE)_beginthreadex(NULL, 0, &ComAsy::OnRecv, this, 0, NULL);
m_IsOpen = true;
return true;
}
void ComAsy::UninitCOM()//关闭串口
{
m_IsOpen = false;
if (INVALID_HANDLE_VALUE != m_hCom)
{
CloseHandle(m_hCom);
m_hCom = INVALID_HANDLE_VALUE;
}
if (NULL != m_ovRead.hEvent)
{
CloseHandle(m_ovRead.hEvent);
m_ovRead.hEvent = NULL;
}
if (NULL != m_ovWrite.hEvent)
{
CloseHandle(m_ovWrite.hEvent);
m_ovWrite.hEvent = NULL;
}
if (NULL != m_ovWait.hEvent)
{
CloseHandle(m_ovWait.hEvent);
m_ovWait.hEvent = NULL;
}
if (NULL != m_Thread)
{
WaitForSingleObject(m_Thread, 5000);//等待线程结束
CloseHandle(m_Thread);
m_Thread = NULL;
}
}
bool ComAsy::ComWrite(LPBYTE buf, int &len)//发送数据
{
BOOL rtn = FALSE;
DWORD WriteSize = 0;
PurgeComm(m_hCom, PURGE_TXCLEAR | PURGE_TXABORT);
m_ovWait.Offset = 0;
rtn = WriteFile(m_hCom, buf, len, &WriteSize, &m_ovWrite);
len = 0;
if (FALSE == rtn && GetLastError() == ERROR_IO_PENDING)//后台读取
{
//等待数据写入完成
if (FALSE == ::GetOverlappedResult(m_hCom, &m_ovWrite, &WriteSize, TRUE))
{
return false;
}
}
len = WriteSize;
return rtn != FALSE;
}
unsigned int __stdcall ComAsy::OnRecv(void* LPParam)//接收数据
{
ComAsy *obj = static_cast<ComAsy*>(LPParam);
DWORD WaitEvent = 0, Bytes = 0;
BOOL Status = FALSE;
BYTE ReadBuf[4096];
DWORD Error;
COMSTAT cs = { 0 };
while (obj->m_IsOpen)
{
WaitEvent = 0;
obj->m_ovWait.Offset = 0;
Status = WaitCommEvent(obj->m_hCom, &WaitEvent, &obj->m_ovWait);
//WaitCommEvent也是一个异步命令,所以需要等待
if (FALSE == Status && GetLastError() == ERROR_IO_PENDING)//
{
//如果缓存中无数据线程会停在此,如果hCom关闭会立即返回False
Status = GetOverlappedResult(obj->m_hCom, &obj->m_ovWait, &Bytes, TRUE);
}
ClearCommError(obj->m_hCom, &Error, &cs);
if (TRUE == Status //等待事件成功
&& WaitEvent&EV_RXCHAR//缓存中有数据到达
&& cs.cbInQue > 0)//有数据
{
Bytes = 0;
obj->m_ovRead.Offset = 0;
memset(ReadBuf, 0, sizeof(ReadBuf));
//数据已经到达缓存区,ReadFile不会当成异步命令,而是立即读取并返回True
Status = ReadFile(obj->m_hCom, ReadBuf, sizeof(ReadBuf), &Bytes, &obj->m_ovRead);
PurgeComm(obj->m_hCom, PURGE_RXCLEAR | PURGE_RXABORT);
for (int i = 0; i < 4096; i++)
aaaa[i] = ReadBuf[i];
}
}
return 0;
}
1.头文件
#include "Com.h"
public:
ComAsy m_ca;
1.源文件:使用
m_ca.InitCOM(L"COM3");
char sData1[MAX_PATH] = { 0 };
sData1[0] = 0x15;
sData1[1] = 0x06;
sData1[2] = 0x00;
sData1[3] = 0x00;
sData1[4] = 0x00;
sData1[5] = 0x01;
sData1[6] = 0x4B;
sData1[7] = 0x1E;
//sData1[5] = 0x02;
//sData1[6] = 0x0B;
//sData1[7] = 0x1F;
int ii = 8;
m_ca.ComWrite((LPBYTE)sData1, ii);
//m_ca.UninitCOM();
1.效果
1.注意
①UninitCOM:不能在ComWrite后面立马使用,否则串口信号还米有发送过去就关闭串口了,