mfc的一个串口类

这几天一直再看串口相关知识,对于其总结为如下串口类:

头文件声明如下:

 #pragma once

 // 声明当串口接收到线程的时候调用的函数指针
// 参数: 1,接收到的数据; 2,数据长度; 3,发送的目标地址
typedef void (*DataArriveProc)(char *data, int len, DWORD dest); /***********************************
1,实现一个串口类,用于进行串口的通信;
2,其中的特性是,主动发送数据,被动接受
做出响应,其中开辟一个线程进型串口读取;
3,线程函数响应时,应该将接受到的数据转
发给使用此串口的上层应用;
************************************/
class CSerialPort
{
public:
CSerialPort(void);
virtual ~CSerialPort(void); // 串口操作函数
BOOL OpenPort(LPCTSTR portName, DWORD baudRate, int dataBits, int stopBits, int parity, DataArriveProc proc, DWORD dest);
BOOL ClosePort(); // 关闭串口
DWORD WritePort(char *data, DWORD size); // 往串口写数据 // 串口读操作线程的操作函数
static UINT AFX_CDECL ReadPortProc(LPVOID lpParam);// 往串口读数据的线程函数
BOOL Activate(); // 激活串口的读操作
BOOL Deactivate(); // 取消串口的读操作
BOOL IsActivate(); // 窗口是否已经准备好进行读操作 private:
HANDLE m_hPortHandle; // 串口句柄
HANDLE m_hReadThread; // 读线程
BOOL m_bReading; // 读线程是否处于工作状态
DCB m_dcbPort; // 串口的工作参数
COMMTIMEOUTS m_tmOut; // 串口通信超时参数 DataArriveProc m_pDataArriveProc; // 接收到数据后的调用的方法
DWORD m_dwDestAddress; // 数据发送的目的地址
};

源文件定义如下:

 #include "StdAfx.h"
#include "SerialPort.h"
#include "Resource.h" CSerialPort::CSerialPort(void)
{
m_hPortHandle = INVALID_HANDLE_VALUE;
m_hReadThread = INVALID_HANDLE_VALUE;
m_bReading = FALSE;
} CSerialPort::~CSerialPort(void)
{
if(INVALID_HANDLE_VALUE != m_hPortHandle){
ClosePort();
}
if(INVALID_HANDLE_VALUE != m_hReadThread){
Deactivate();
}
} // 打开串口
// 1,打开串口文件;
// 2,设置串口属性
// 3,完成操作;
BOOL CSerialPort::OpenPort(LPCTSTR portName, DWORD baudRate, int dataBits, int stopBits, int parity, DataArriveProc proc, DWORD dest)
{
if(INVALID_HANDLE_VALUE != m_hPortHandle){
// 串口已经打开
return TRUE;
} CString temp; // 保存数据到达后的响应地址,及目的地
m_pDataArriveProc = proc;
m_dwDestAddress = dest; // 1, 打开串口文件
m_hPortHandle = ::CreateFile(portName, GENERIC_READ | GENERIC_WRITE, , NULL, OPEN_EXISTING, , NULL);
if(INVALID_HANDLE_VALUE == m_hPortHandle){
temp.LoadString(IDS_OPENPORT_FAIL);
AfxMessageBox(temp);
return FALSE;
} // 2, 获取串口的工作参数并重新赋值
GetCommState(m_hPortHandle, &m_dcbPort);
m_dcbPort.BaudRate = baudRate; // 设置波特率(外部设置)
m_dcbPort.ByteSize = dataBits; // 通信字节位数
m_dcbPort.fParity = ; // 奇偶校验使能,1可以
m_dcbPort.Parity = parity; // 校验方式:外设
m_dcbPort.StopBits = stopBits;// 停止位
m_dcbPort.fBinary = ;
m_dcbPort.fDtrControl = ;
m_dcbPort.fRtsControl = ;
m_dcbPort.fOutX= m_dcbPort.fInX= m_dcbPort.fTXContinueOnXoff=; // 3,设置一组监视串口设备的事件,什么信息到达时通知
SetCommMask(m_hPortHandle, EV_RXCHAR);
// 4,设置串口的通信参数,主要是缓冲区大小
SetupComm(m_hPortHandle, , );
// 5,设置工作参数
if(!SetCommState(m_hPortHandle, &m_dcbPort)){
temp.LoadString(IDS_SETSTATE_FAIL);
AfxMessageBox(temp);
ClosePort();
return FALSE;
} // 6,获取通信超时信息并重新设置
GetCommTimeouts(m_hPortHandle, &m_tmOut);
m_tmOut.ReadIntervalTimeout = ;
m_tmOut.ReadTotalTimeoutConstant = ;
m_tmOut.ReadTotalTimeoutMultiplier = ;
m_tmOut.WriteTotalTimeoutMultiplier = ;
m_tmOut.WriteTotalTimeoutConstant = ;
if(!SetCommTimeouts(m_hPortHandle, &m_tmOut)){
temp.LoadString(IDS_SETTTMOUT_FAIL);
AfxMessageBox(temp);
ClosePort();
return FALSE;
} // 7,清空串口缓冲区
PurgeComm(m_hPortHandle, PURGE_RXCLEAR | PURGE_TXCLEAR);
return TRUE;
}
// 关闭串口
// 1,清空通信设备监听事件;
// 2,清空串口缓冲区;
// 3,关闭串口文件句柄;
BOOL CSerialPort::ClosePort()
{
if(INVALID_HANDLE_VALUE != m_hPortHandle){
SetCommMask(m_hPortHandle, );
PurgeComm(m_hPortHandle, PURGE_RXCLEAR | PURGE_TXCLEAR);
CloseHandle(m_hPortHandle);
m_hPortHandle = INVALID_HANDLE_VALUE;
return TRUE;
} return TRUE;
} // 往串口写数据
// 1,首先检查串口是否处于工作状态;
// 2,向串口写入内容;
// 3,返回写入的内容大小;
DWORD CSerialPort::WritePort(char *data, DWORD size)
{
if(INVALID_HANDLE_VALUE == m_hPortHandle){
return ;
} DWORD writeLen = ;
BOOL ret = FALSE; ret = WriteFile(m_hPortHandle, data, size*sizeof(char), &writeLen, NULL); return writeLen;
} // 激活串口的读操作
// 1,判断串口是否已经打开;
// 2,判断串口读线程是否已经创建;
// 3,设置成员变量;
BOOL CSerialPort::Activate()
{
if(INVALID_HANDLE_VALUE == m_hPortHandle){
return FALSE;
} if(!m_bReading){
m_hReadThread = AfxBeginThread(ReadPortProc, this);
m_bReading = TRUE;
} if(INVALID_HANDLE_VALUE !=m_hReadThread){
// ResumeThread(m_hReadThread);
return TRUE;
}else{
m_bReading = FALSE;
return FALSE;
} return FALSE;
}
// 取消串口的读操作
// 1, 判断串口是否已经打开;
// 2,判断读线程是否已经创建;
// 3,设置成员变量;
BOOL CSerialPort::Deactivate()
{
if(INVALID_HANDLE_VALUE == m_hPortHandle){
return FALSE;
} if(INVALID_HANDLE_VALUE == m_hReadThread){
return FALSE;
} if(m_bReading){
WaitForSingleObject(m_hReadThread, INFINITE);
CloseHandle(m_hReadThread);
m_hReadThread = INVALID_HANDLE_VALUE;
m_bReading = FALSE;
return TRUE;
} return FALSE;
}
// 窗口是否已经准备好进行读操作
BOOL CSerialPort::IsActivate()
{
return m_bReading;
} // 往串口读数据的线程函数
// 对于线程处理函数需要是一个全局的或者静态的
// 所以你需要知道你当前需要知道你用的是哪个串口
// 实例,顾此函数参数为串口实例指针
UINT CSerialPort::ReadPortProc(LPVOID lpParam)
{
// 1, 变量准备
CSerialPort *pPort = (CSerialPort*)lpParam;
CString temp;
char *buffer = NULL;
int buferSize = ;
DWORD dwRead = ;
BOOL bRead = FALSE; // 2,基本条件判断
buffer = new char[buferSize];
while((pPort->m_hPortHandle != INVALID_HANDLE_VALUE) && (pPort->m_bReading)){
bRead = ReadFile(pPort->m_hPortHandle, buffer, buferSize, &dwRead, NULL);
if(!bRead){
temp.LoadString(IDS_READFILE_FAIL);
AfxMessageBox(temp);
}else{
if( != dwRead)
pPort->m_pDataArriveProc(buffer, buferSize, pPort->m_dwDestAddress);
}
} return ;
}

对于上述代码已编译通过,但是具体的还未测试,等后续完善!

谢谢支持!

上一篇:虚拟机安装Linux过程和踩坑


下一篇:Windows下虚拟机安装Mac OS X ----- VM12安装Mac OS X 10.11