我的同步串口类

原创 2006年06月08日 14:39:00

头文件

// 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;
}

版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

win32串口同步、异步编程

在工业控制中,工控机(一般都基于Windows平台)经常需要与智能仪表通过串口进行通信。串口通信方便易行,应用广泛。 一般情况下,工控机和各智能仪表通过RS485总线进行通信。RS485的通信方式是...

Qt串口同步通信源代码

控制台下WinApi同步方式实现的串口发送数据

// ApiOpenCom1.cpp : Defines the entry point for the console application. // #include "stdafx.h" #i...

串口同步接收

串口 同步和异步 理解

本文主要三大块:一,串口同步和异步在地产通行上的区别(这部分点到为止,不是主要探讨内容,有个基本理解即可)。                 ...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)