现在的位置: 首页 > 综合 > 正文

同步串口类

2018年02月08日 ⁄ 综合 ⁄ 共 7889字 ⁄ 字号 评论关闭

头文件

// SerialPort.h: interface for the CSerialPort class.
// 类名: CSerialPort
// 创建人: 郑新华
// 创建日期:2005-7-13
// 概述:该类封装了对串口的基本操作,目前为同步操作,日后逐渐完善为同步
//       异步可配置状态
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_SERIALPORT_H__5F418CEB_1BFD_4A54_9ABD_4984A825E4CF__INCLUDED_)
#define AFX_SERIALPORT_H__5F418CEB_1BFD_4A54_9ABD_4984A825E4CF__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

typedef struct {
//串口号
DWORD m_dwPort;
//波特率
DWORD m_dwBaudRate;
//停止位
DWORD m_dwStopBit;
//奇偶校验
//DWORD m_dwParity;
char m_chrParity;
//字节大小
BYTE m_bytByteSize;
//串口输入缓冲大小
DWORD m_dwInputSize;
//串口输出缓冲大小
DWORD m_dwOutputSize;
//串口句柄
HANDLE m_hCommHandle;
//是否同步
BOOL m_bSync;
}UDT_PortParam;

class CSerialPort
{
public:
BOOL IsOpen();
//获取串口配置参数
UDT_PortParam GetParam();
//设置串口配置
void SetParam(UDT_PortParam udtParam);
//向串口写数据
DWORD Write(char* pszBuffer, DWORD dwBufferLen);
//从串口读数据
DWORD Read(char* pszBuffer, DWORD dwBufferLen, DWORD dwWaitTime = 20);
//关闭串口
void Close();
//打开串口
BOOL Open();
CSerialPort(UDT_PortParam udtPortParam);
CSerialPort();
virtual ~CSerialPort();
protected:
char szPort[20];
private:
BOOL Setup();
UDT_PortParam m_udtPortParam;

};

#endif // !defined(AFX_SERIALPORT_H__5F418CEB_1BFD_4A54_9ABD_4984A825E4CF__INCLUDED_)

cpp文件

// SerialPort.cpp: implementation of the CSerialPort class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "Comm.h"
#include "SerialPort.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

CSerialPort::CSerialPort()
{
m_udtPortParam.m_dwBaudRate = 9600;
m_udtPortParam.m_dwPort = 1;
m_udtPortParam.m_bytByteSize = 8;
m_udtPortParam.m_dwStopBit = ONESTOPBIT;
//m_udtPortParam.m_dwParity = NOPARITY;
m_udtPortParam.m_chrParity = 'N';
m_udtPortParam.m_dwInputSize = 4096;
m_udtPortParam.m_dwOutputSize = 4096;
m_udtPortParam.m_hCommHandle = INVALID_HANDLE_VALUE;
m_udtPortParam.m_bSync = TRUE;
}

CSerialPort::~CSerialPort()
{
Close();
}

CSerialPort::CSerialPort(UDT_PortParam udtPortParam)
{
m_udtPortParam = udtPortParam;
}

/***************************************************************************
*功能: 打开串口
*参数: 无
*返回值:执行成功返回TRUE,否则返回FALSE
***************************************************************************/
BOOL CSerialPort::Open()
{
ASSERT(m_udtPortParam.m_dwPort >= 1 && m_udtPortParam.m_dwPort <= 1024);

//组合成欲打开的串口名
memset(szPort, '/0', 20);
strcpy(szPort, "////.//COM");
char p[5];
ltoa(m_udtPortParam.m_dwPort, p, 10);

strcat(szPort, p);

TRACE1("/n串口为:%s", szPort);
if(IsOpen())
   Close();

m_udtPortParam.m_hCommHandle = CreateFile(
   szPort,
   GENERIC_READ | GENERIC_WRITE,
   0,
   NULL,
   OPEN_EXISTING,
   FILE_ATTRIBUTE_NORMAL,
   NULL
   );

if(m_udtPortParam.m_hCommHandle == INVALID_HANDLE_VALUE)
   return FALSE;

//设置缓冲区
if(!::SetupComm(m_udtPortParam.m_hCommHandle, m_udtPortParam.m_dwInputSize, m_udtPortParam.m_dwOutputSize))
{

   Close();
   return FALSE;
}

//设置超时时间
COMMTIMEOUTS _CO;
if(!::GetCommTimeouts(m_udtPortParam.m_hCommHandle, &_CO))
   return FALSE;
_CO.ReadIntervalTimeout = 0xFFFFFFFF;
_CO.ReadTotalTimeoutMultiplier = 0;
_CO.ReadTotalTimeoutConstant = 0;
_CO.WriteTotalTimeoutMultiplier = 0;
_CO.WriteTotalTimeoutConstant = 2000;
if(!::SetCommTimeouts(m_udtPortParam.m_hCommHandle, &_CO))
{
   Close();
   return FALSE;
}

//清空串口缓冲区
if(!::PurgeComm(m_udtPortParam.m_hCommHandle, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ))
{
   Close();
   return FALSE;
}

return Setup();
}

/*********************************************************************************
*功能: 关闭串口
*参数: 无
*返回值:无
*********************************************************************************/
void CSerialPort::Close()
{
if(IsOpen())
{
   ::CloseHandle(m_udtPortParam.m_hCommHandle);
   m_udtPortParam.m_hCommHandle = INVALID_HANDLE_VALUE;
}
}
/***************************************************************************
*功能: 读取串口
*参数: pszBuffer    数据存放缓冲区首地址
*        dwBufferLen 缓冲长度
*        dwWaitTime   等待时间,默认20毫秒
*返回值:执行失败返回0,否则为读出数据长度
****************************************************************************/
DWORD CSerialPort::Read(char *pszBuffer, DWORD dwBufferLen, DWORD dwWaitTime)
{
ASSERT(pszBuffer != NULL);

if(!IsOpen())
{
   TRACE0("/n串口没有打开!");
   return 0;
}

COMSTAT Stat;
DWORD dwError;

//清除错误
if(::ClearCommError(m_udtPortParam.m_hCommHandle, &dwError, &Stat) && dwError > 0)
{
   //清空输入缓冲区
   ::PurgeComm(m_udtPortParam.m_hCommHandle, PURGE_RXABORT | PURGE_RXCLEAR);
   TRACE0("/n清除错误失败!");
   return 0;
}
//Sleep(500);

pszBuffer[0] = '/0';

unsigned long uReadLength = 0;
//dwBufferLen = dwBufferLen - 1 > Stat.cbInQue ? Stat.cbInQue : dwBufferLen - 1;

//同步读取
if(m_udtPortParam.m_bSync)
{
  
   if(!::ReadFile(m_udtPortParam.m_hCommHandle, pszBuffer, dwBufferLen, &uReadLength, NULL))
   {
    TRACE0("/n读取串口失败!");
    if(::GetLastError() != ERROR_IO_PENDING)
     uReadLength = 0;
   }
   TRACE1("/nReadFile读出%d个字符!", uReadLength);

   //清空缓冲区
   ::PurgeComm(m_udtPortParam.m_hCommHandle, PURGE_RXABORT | PURGE_RXCLEAR);
}
else //异步
{
   OVERLAPPED _ReadOverlapped;
   memset(&_ReadOverlapped, 0 ,sizeof(_ReadOverlapped));
   _ReadOverlapped.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
   ASSERT(_ReadOverlapped.hEvent != INVALID_HANDLE_VALUE);

   if(!::ReadFile(m_udtPortParam.m_hCommHandle, pszBuffer, dwBufferLen, &uReadLength, &_ReadOverlapped))
   {
    //结束异步IO
    if(::GetLastError() == ERROR_IO_PENDING)
    {
     WaitForSingleObject(_ReadOverlapped.hEvent, dwWaitTime);
     if(!::GetOverlappedResult(m_udtPortParam.m_hCommHandle, &_ReadOverlapped, &uReadLength, false))
     {
      //其他错误
      if(::GetLastError() == ERROR_IO_INCOMPLETE)
       uReadLength = 0;
     }
     else
      uReadLength = 0;
    }
   }
   if(_ReadOverlapped.hEvent != INVALID_HANDLE_VALUE)
    CloseHandle(_ReadOverlapped.hEvent);
}

pszBuffer[uReadLength] = '/0';

return uReadLength;
}
/*********************************************************************************
*功能: 向串口写入数据
*参数: pszBuffer   欲写入数据首地址
*        dwBufferLen 欲写入数据长度
*返回值:执行失败返回0,否则为写入数据长度
**********************************************************************************/
DWORD CSerialPort::Write(char *pszBuffer, DWORD dwBufferLen)
{
ASSERT(pszBuffer != NULL);

if(!IsOpen())
   return FALSE;

DWORD dwError;
//清除错误
if(::ClearCommError(m_udtPortParam.m_hCommHandle, &dwError, NULL) && dwError > 0)
   //清空输入缓冲区
   ::PurgeComm(m_udtPortParam.m_hCommHandle, PURGE_TXABORT | PURGE_TXCLEAR);

unsigned long uWriteLength = 0;

//同步写入
if(m_udtPortParam.m_bSync)
{
   if(!::WriteFile(m_udtPortParam.m_hCommHandle, pszBuffer, dwBufferLen, &uWriteLength, NULL))
    if(::GetLastError() != ERROR_IO_PENDING)
     uWriteLength = 0;
}
else //异步
{
   OVERLAPPED _WriteOverlapped;
   memset(&_WriteOverlapped, 0 ,sizeof(_WriteOverlapped));
   _WriteOverlapped.hEvent = ::CreateEvent(NULL, TRUE, FALSE, NULL);
   ASSERT(_WriteOverlapped.hEvent != INVALID_HANDLE_VALUE);

   if(!::WriteFile(m_udtPortParam.m_hCommHandle, pszBuffer, dwBufferLen, &uWriteLength, &_WriteOverlapped))
    if(::GetLastError() != ERROR_IO_PENDING)
     uWriteLength = 0;

   if(_WriteOverlapped.hEvent != INVALID_HANDLE_VALUE)
    CloseHandle(_WriteOverlapped.hEvent);
}

return uWriteLength;
}

void CSerialPort::SetParam(UDT_PortParam udtParam)
{
m_udtPortParam = udtParam;
}

UDT_PortParam CSerialPort::GetParam()
{
return m_udtPortParam;
}

BOOL CSerialPort::IsOpen()
{
return m_udtPortParam.m_hCommHandle != INVALID_HANDLE_VALUE;
}

/****************************************************************************
*功能: 设置波特率、停止位等
*参数: 无
*返回值:执行成功返回TRUE,否则返回FALSE
*****************************************************************************/
BOOL CSerialPort::Setup()
{
BOOL bResult = FALSE;
if(IsOpen())
{
   DCB dcb;
   if(!::GetCommState(m_udtPortParam.m_hCommHandle, &dcb))
    return FALSE;

   /*
   dcb.BaudRate = m_udtPortParam.m_dwBaudRate;
   dcb.ByteSize = m_udtPortParam.m_bytByteSize;
   dcb.StopBits = m_udtPortParam.m_dwStopBit;
   dcb.Parity = m_udtPortParam.m_dwParity;*/
   char chrSet[50];
   
   sprintf(chrSet, "%d,%c,%d,%d", m_udtPortParam.m_dwBaudRate, m_udtPortParam.m_chrParity, m_udtPortParam.m_bytByteSize, m_udtPortParam.m_dwStopBit);
   if(BuildCommDCB(chrSet, &dcb))
   {
    if(::SetCommState(m_udtPortParam.m_hCommHandle, &dcb))
     bResult = TRUE;
   }
  
}
if(!bResult)
   Close();
return bResult;
}

 

 

更多技术文章请参看施昌权的个人网站: http://www.joyvc.cn

 

 

抱歉!评论已关闭.