搜档网
当前位置:搜档网 › CommUtils

CommUtils

CommUtils
CommUtils

/* CommUtils.h */

#ifndef _CommUtils_H__

#define _CommUtils_H__

class CommUtils

{

public:

bool ReadCom(unsigned char * ReceiveData, DWORD& ReceiveLength);

void CloseCom();

bool WriteCom(unsigned char * sendchar,int sendsize);

bool OpenCom(int Port);

CommUtils();

virtual ~CommUtils();

int m_Port;

char szCurPath[256];

private:

OVERLAPPED ReadovReady, WriteovReady;

HANDLE hComm;

bool bOpenCom;

};

#endif

/*

CommUtils.cpp 串口通讯类

Author: edog 2007-11-21

EMail: comwell@https://www.sodocs.net/doc/6213122595.html,

*/

#include "stdafx.h"

#include "CommUtils.h"

#include "stdio.h"

const int READ_TIMEOUT = 500;

CommUtils::CommUtils()

{

bOpenCom = false;

}

CommUtils::~CommUtils()

{

this->CloseCom();

}

bool CommUtils::OpenCom(int Port)

{

if (bOpenCom)

{

this->CloseCom();

bOpenCom = false;

}

char szport[10];

sprintf(szport,"COM%d",Port);

hComm = CreateFile( szport,

GENERIC_READ|GENERIC_WRITE,

0,

NULL,

OPEN_EXISTING,

FILE_FLAG_OVERLAPPED, //FILE_ATTRIBUTE_NORMAL|

NULL);

if (hComm == INVALID_HANDLE_VALUE) return false;

if (!SetupComm(hComm, 1024, 512)) return false;

COMMTIMEOUTS commtimeouts;

commtimeouts.ReadIntervalTimeout = MAXDWORD;

commtimeouts.ReadTotalTimeoutConstant =0;

commtimeouts.ReadTotalTimeoutMultiplier =0;

commtimeouts.WriteTotalTimeoutConstant =0;

commtimeouts.WriteTotalTimeoutMultiplier=0;

if (!SetCommTimeouts(hComm, &commtimeouts)) return false;

memset(&ReadovReady,0,sizeof(OVERLAPPED));

memset(&WriteovReady,0,sizeof(OVERLAPPED));

ReadovReady.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);

WriteovReady.hEvent =CreateEvent(NULL,TRUE,FALSE,NULL);

SECURITY_ATTRIBUTES sa;

sa.nLength=sizeof(SECURITY_ATTRIBUTES);

sa.lpSecurityDescriptor=NULL;

sa.bInheritHandle=TRUE;

DCB dcb;

GetCommState(hComm, &dcb);

dcb.fBinary = TRUE;

dcb.fParity = TRUE;

dcb.BaudRate = CBR_9600; // 波特率 9600

dcb.ByteSize = 8; // 8 位数据位

dcb.Parity = NOPARITY; // 无奇偶校验

dcb.StopBits = ONESTOPBIT; // 1 个停止位

if (!SetCommState(hComm, &dcb )) return false;

bOpenCom = true;

return bOpenCom;

}

bool CommUtils::WriteCom(unsigned char *sendchar, int sendsize)

{

if (!bOpenCom) return false;

DWORD BytesSent;

DWORD resD;

PurgeComm(hComm, PURGE_RXCLEAR | PURGE_TXCLEAR | PURGE_RXABOR T | PURGE_TXABORT);

BytesSent=0;

BOOL hr = WriteFile(hComm, // Handle to COMM Port

sendchar, // Pointer to message buffer in calling finction

sendsize, // Length of message to send

&BytesSent, // Where to store the number of bytes sent

&WriteovReady); // Overlapped structure

if(!hr)

{

if(GetLastError() != ERROR_IO_PENDING)

{

return false ;

}

else

{

resD=WaitForSingleObject(WriteovReady.hEvent,INFINITE);

}

switch (resD)

{

case WAIT_OBJECT_0:

{

if (!GetOverlappedResult(hComm,&WriteovReady,&BytesSent,false ))

return false ;

else

return true ;

}

default :

return false ;

break ;

}

}

return true ; }

void CommUtils::CloseCom() {

if (!bOpenCom) return ;

CloseHandle(hComm);

hComm=NULL;

CloseHandle(ReadovReady.hEvent);

CloseHandle(WriteovReady.hEvent );

ReadovReady.hEvent =NULL;

WriteovReady.hEvent =NULL;

}

bool CommUtils::ReadCom(unsigned char * ReceiveData, DWORD& ReceiveLength) {

if (!bOpenCom) return false;

if (ReadovReady.hEvent == NULL) return false;

ReceiveLength = 0;

if (ReadFile(hComm, ReceiveData, 128, &ReceiveLength, &ReadovReady) == FALSE)

{

if (GetLastError() != ERROR_IO_PENDING) return false;

}

if(ReceiveLength == 0) return false;

ReceiveData[ReceiveLength] = 0;

DWORD dwRead;

DWORD dwRes = WaitForSingleObject(ReadovReady.hEvent, READ_TIMEOUT);

switch(dwRes)

{

case WAIT_OBJECT_0:

if (!GetOverlappedResult(hComm, &ReadovReady, &dwRead, FALSE)) return fals e;

break;

case WAIT_TIMEOUT:

break;

default:

break;

}

return true;

}

以下为使用方法:

// 1. 包含头文件,定义变量

#include "CommUtils.h"

CommUtils theComm;

unsigned char data[1024];

unsigned long len = 0;

// 2. 打开串口,设置接收定时器

theComm.OpenCom(1); // 打开COM1口

SetTimer(1, 50, 0);

// 3. 发送数据

theComm.WriteCom(data, len);

// 4. 接收数据处理

void CUARTDlg::OnTimer(UINT nIDEvent)

{

if (nIDEvent == 1)

{

if (theComm.ReadCom(data, len))

{

if (len > 0)

{

// 接收数据处理。。。

}

}

}

CDialog::OnTimer(nIDEvent);

}

一个实用的串口通信类

发表:不详阅读:84次关键字:字体:[大中小]

谢谢支持!

修改一下更好用

-------------------------------------------------------------------------------------------------------

//***************************************************************************** *****//

/**

File Name(文件名): SaimIO.h: interface for the CSaimIO class.

Author(作者): Wenjin Hu 胡文晋 (eg. Saimen Hu)

Version(版本): 1.0

Date(完成日期): 2000.10.10

Description(介绍): 用于 COM 口的读写类,完成对COM 口的选取,COM口的初始化。

对COM口的读写操作。

typedef struct tagIOINFO

{

HANDLE idComDev;

BYTE bPort;

BOOL fConnected,fXonXoff;

BYTE bByteSize,bFlowCtrl,bParity,bStopBits;

DWORD dwBaudRate;

OVERLAPPED osWrite,osRead;

}IOINFO;

配置串口通信的数据结构

HANDLE idComDev 为串口句柄

BYTE bPort 为串口号

BOOL fConnected 为是否连接

BYTE bByteSize 为字节数

BYTE bFlowCtrl 流量控制

BYTE bParity 校检类型

BYTE bStopBits 停止位

DWORD dwBaudRate 波特率

OVERLAPPED osWrite,osRead 读写事件及时限

**/

//***************************************************************************** ******//

// Flow control flags 流量控制类型

//

#define FC_DTRDSR 0x01

#define FC_RTSCTS 0x02

#define FC_XONXOFF 0x04

// ascii definitions 流量控制字符

//

#define ASCII_XON 0x11

#define ASCII_XOFF 0x13

typedef struct tagIOINFO

{

HANDLE idComDev;

BYTE bPort;

BOOL fConnected,fXonXoff;

BYTE bByteSize,bFlowCtrl,bParity,bStopBits;

DWORD dwBaudRate;

OVERLAPPED osWrite,osRead;

}IOINFO;

//////////////////////////////////////////////////////////////////////

#if !defined(AFX_SAIMIO_H__A2648CC2_9DBF_11D4_96BD_E54AFA740DAA__INCLUDED_) #define AFX_SAIMIO_H__A2648CC2_9DBF_11D4_96BD_E54AFA740DAA__INCLUDED_

#if _MSC_VER > 1000

#pragma once

#endif // _MSC_VER > 1000

#define MSG_NEW_IODATA WM_USER+100

class CSaimIO : public CFile

{

public:

CSaimIO();

virtual ~CSaimIO();

public:

void ResumeThread();

void SuspandThread();

BOOL ConnectCom(LPTSTR initStr);

BOOL EndListern();

BOOL BeginListen();

void ClearIObuffer();

CString HexToStr(unsigned char *lpDataBuffer,int Total);

void StrToHex(unsigned char *lpBuffer,int *Total);

void InitaiseIO();

void SetIO(IOINFO SetIoInfo);

BOOL DisConnect();

DWORD GetData(unsigned char *DataBuffer,DWORD DataLength);

BOOL SendData(unsigned char *lpCommand,DWORD CmdLength);

BOOL Connect();

IOINFO IoInfoData;

protected:

// 监听线程数据

private:

BOOL ThreadIsRun();

HANDLE hListenThread;

DWORD dwThreadID;

// DWORD WINAPI ListenThread(LPVOID lpParameter);

};

// 监听线程

DWORD WINAPI ListenThread(LPVOID lpParameter);

#endif

// !defined(AFX_SAIMIO_H__A2648CC2_9DBF_11D4_96BD_E54AFA740DAA__INCLUDED_)

---------------------------------------------------------------------------------------------------

//***************************************************************************** *****//

/**

File Name(文件名): SaimIO.cpp: implementation of the CSaimIO class.

Author(作者): Wenjin Hu 胡文晋 (eg. Saimen Hu)

Version(版本): 1.0

Date(完成日期): 2000.10.10

Description(介绍): 用于 COM 口的读写类,完成对COM 口的选取,COM口的初始化。

对COM口的读写操作。

Other(其它备注): 完成对串口的读写有两种情况:1.计算机之间通信

2.计算机和其它设备通信

对于这两种情况要注意在初始化COM的DCB结构时,成员不同的值对通信产后不

同的效果,也许是非常严重的。例下面:

如果把下面两个成员的值赋为以下情况

dcb.fDtrControl = DTR_CONTROL_ENABLE ;

dcb.fRtsControl = RTS_CONTROL_ENABLE ;

此时不能完成计算机和其它设备之间通信。

改为以下值就可以完成和其它设备能信。

dcb.fDtrControl = DTR_CONTROL_DISABLE ;

dcb.fRtsControl = RTS_CONTROL_ENABLE ;

Funtion List(主要函数):

1. void InitaiseIO()

用来对串口IOINFO 数据结构初始化为默认值

2. void SetIO(IOINFO SetIoInfo)

调用该函数用来修改IOINFO数据结构,配置串口

说明:该函数在 CONNECT 之前调用。

3. BOOL Connect()

用来连接串口,使用IOINFO中的数据结构,如果成功返回 TRUE;

不成功返回 FALSE;

4. BOOL DisConnect()

关闭对串口的连接,成功返回: TRUE 否则返回:FALSE

5. BOOL SendData(unsigned char *lpCommand,DWORD CmdLength)

向串口发送数据,数据长度为 CmdLength,lpCommand 为指向该命令的指针。

6. BOOL GetData(unsigned char *Databuffer,int DataLength)

读取串口缓冲中的数据。

History(修改记录):

1.Date: 2000.10.11

Author: 胡文晋 (EG. Saim Hu)

Modification:

添加函数: CString CSaimIO::HexToStr(unsigned char *lpDataBuffer) 功能:将入口参数unsigned char * DataBuffer 转换为CString 字符串

2.Date: 2000.11.10

Author: 胡文晋 (EG. Saim Hu)

Modifcation:

**/

//***************************************************************************** **//

/////////////////////////////////////////////////////////////////////////////// ////

#include "stdafx.h"

#include "SaimIO.h"

#ifdef _DEBUG

#undef THIS_FILE

static char THIS_FILE[]=__FILE__;

#define new DEBUG_NEW

#endif

extern BOOL KillListenThread ;

//////////////////////////////////////////////////////////////////////

// Construction/Destruction

//////////////////////////////////////////////////////////////////////

CSaimIO::CSaimIO()

{

InitaiseIO();

hListenThread = NULL;

}

CSaimIO::~CSaimIO()

{

}

// 以默认方式初始化串口

void CSaimIO::InitaiseIO()

{

IoInfoData.idComDev = 0 ;

IoInfoData.bByteSize = 8 ;

IoInfoData.fConnected = FALSE;

IoInfoData.bPort = 1 ;

IoInfoData.dwBaudRate = CBR_4800;

IoInfoData.bFlowCtrl = FALSE; //FC_XONXOFF; // FC_RTSCTS; //FC_XONXOFF; IoInfoData.bParity = EVENPARITY ; //MARKPARITY ; SPACEPARITY; ODDPARITY; IoInfoData.bStopBits = ONESTOPBIT; //ONE5STOPBITS; TWOSTOPBITS

IoInfoData.osWrite.Offset = 0;

IoInfoData.osWrite.OffsetHigh = 1024;

IoInfoData.osRead.Offset = 0;

IoInfoData.osRead.OffsetHigh = 1024;

IoInfoData.osRead.hEvent = NULL;

IoInfoData.osWrite.hEvent = NULL;

}

// 修改串口数据结构

void CSaimIO::SetIO(IOINFO SetIoInfo)

{

IoInfoData.idComDev = SetIoInfo.idComDev ;

IoInfoData.bByteSize = SetIoInfo.bByteSize ;

IoInfoData.fConnected = SetIoInfo.fConnected;

IoInfoData.bPort = SetIoInfo.bPort ;

IoInfoData.dwBaudRate = SetIoInfo.dwBaudRate;

IoInfoData.bFlowCtrl = SetIoInfo.bFlowCtrl;

IoInfoData.bParity = SetIoInfo.bParity;

IoInfoData.bStopBits = SetIoInfo.bStopBits;

IoInfoData.osWrite.Offset = SetIoInfo.osWrite.Offset;

IoInfoData.osWrite.OffsetHigh = SetIoInfo.osWrite.OffsetHigh;

IoInfoData.osRead.Offset = SetIoInfo.osRead.Offset;

IoInfoData.osRead.OffsetHigh = SetIoInfo.osRead.OffsetHigh;

}

// Connect IO before use it.

// 打开串开

BOOL CSaimIO::Connect()

{

BOOL fRetVal ;

BYTE bSet ;

DCB dcb ;

char szPort[10];

memset(szPort,0,10);

wsprintf(szPort,"COM%d:",IoInfoData.bPort);

IoInfoData.idComDev = CreateFile(szPort,GENERIC_READ|GENERIC_WRITE, 0,

NULL,

OPEN_EXISTING,

FILE_ATTRIBUTE_NORMAL|FILE_FLAG_OVERLAPPED,

NULL);

if( !IoInfoData.idComDev )

return FALSE;

if(!SetCommMask(IoInfoData.idComDev,EV_RXFLAG)) // EV_RXCHAR))

return FALSE;

// Alloc the buffer for Read and Write.

if( SetupComm(IoInfoData.idComDev,4096,4096) == 0 )

return FALSE;

//Setup for overlapped I/O

COMMTIMEOUTS CommTimesOuts;

CommTimesOuts.ReadIntervalTimeout = 100;

CommTimesOuts.ReadTotalTimeoutMultiplier = 20;

CommTimesOuts.ReadTotalTimeoutConstant = 1000 ;

CommTimesOuts.WriteTotalTimeoutMultiplier = 2*CBR_9600 /

IoInfoData.dwBaudRate ;

CommTimesOuts.WriteTotalTimeoutConstant = 1000;

SetCommTimeouts(IoInfoData.idComDev,&CommTimesOuts);

// Initise the com port.

dcb.DCBlength = sizeof( DCB ) ;

GetCommState( IoInfoData.idComDev, &dcb ) ;

dcb.BaudRate = IoInfoData.dwBaudRate ;

dcb.ByteSize = IoInfoData.bByteSize ;

dcb.Parity = IoInfoData.bParity ;

dcb.StopBits = IoInfoData.bStopBits ;

// setup hardware flow control

bSet = (BYTE) ((FC_RTSCTS & FC_DTRDSR) != 0) ;

dcb.fOutxDsrFlow = bSet ;

dcb.fDtrControl = DTR_CONTROL_DISABLE ; //给予提供电源,新的 485 就不需要提供

dcb.fRtsControl = RTS_CONTROL_ENABLE ;

bSet = (BYTE) FC_RTSCTS ;

dcb.fOutxCtsFlow = bSet ;

// setup software flow control

bSet = (BYTE) FC_XONXOFF ;

dcb.fInX = dcb.fOutX = bSet ;

dcb.XonChar = ASCII_XON ;

dcb.XoffChar = ASCII_XOFF ;

dcb.XonLim = 100 ;

dcb.XoffLim = 100 ;

// other various settings

dcb.fBinary = TRUE ;

dcb.fParity = 1 ; // Enalble Parity

fRetVal = SetCommState( IoInfoData.idComDev, &dcb ) ;

if( fRetVal != FALSE )

IoInfoData.fConnected = TRUE;

else

return fRetVal;

//Ceate I/O event used for overlapped reads / writes

IoInfoData.osRead.hEvent = CreateEvent( NULL , //no security

TRUE , //explicit reset req FALSE , //initial event reset

NULL); //no name

if( IoInfoData.osRead.hEvent == NULL )

{

return FALSE;

}

IoInfoData.osWrite.hEvent = CreateEvent( NULL , //no security

TRUE , //explicit reset req FALSE , //initial event reset

NULL); //no name

if( IoInfoData.osWrite.hEvent == NULL )

{

CloseHandle( IoInfoData.osRead.hEvent );

}

// Clear Read and Send IO buffer

if(PurgeComm(IoInfoData.idComDev,PURGE_RXCLEAR)== 0)

return FALSE;

if(PurgeComm(IoInfoData.idComDev,PURGE_TXCLEAR)== 0)

return FALSE;

// Set The DataSet is ready TO Get Data

EscapeCommFunction(IoInfoData.idComDev,SETDTR|SETRTS);

// set connected flag to TRUE

IoInfoData.fConnected = TRUE ;

return ( TRUE ) ;

}

// Close IO when exit the program.

// 关闭串口

BOOL CSaimIO::DisConnect()

{

if(IoInfoData.fConnected == FALSE )

return TRUE;

// Stop the Listen Thread

EndListern();

// set connected flag to FALSE

IoInfoData.fConnected = FALSE ;

// disable event notification and wait for thread

// to halt

SetCommMask( IoInfoData.idComDev , 0 ) ;

// drop DTR

EscapeCommFunction( IoInfoData.idComDev, CLRDTR | CLRRTS) ;

// purge any outstanding reads/writes and close device handle

if(PurgeComm( IoInfoData.idComDev, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR ) == 0 )

CloseHandle(IoInfoData.osRead.hEvent);

CloseHandle(IoInfoData.osWrite.hEvent);

return CloseHandle( IoInfoData.idComDev ) ;

}

// Send the Datas.

// 写数据到串口

BOOL CSaimIO::SendData(unsigned char *lpCommand, DWORD dwBytesToWrite)

{

BOOL fWriteStat ;

DWORD dwBytesWritten ;

DWORD dwErrorFlags;

DWORD dwError;

DWORD dwBytesSent=0;

COMSTAT ComStat;

char szError[ 128 ] ;

if (IoInfoData.fConnected == FALSE )

return ( FALSE ) ;

fWriteStat = WriteFile( IoInfoData.idComDev , lpCommand, dwBytesToWrite, &dwBytesWritten,NULL) ; // &IoInfoData.osWrite ) ;

if(dwBytesWritten != dwBytesToWrite)

return FALSE;

if (!fWriteStat)

{

if(GetLastError() == ERROR_IO_PENDING)

{

while(!GetOverlappedResult( IoInfoData.idComDev ,

&IoInfoData.osWrite, &dwBytesWritten, TRUE ))

{

dwError = GetLastError();

if(dwError == ERROR_IO_INCOMPLETE)

{

// normal result if not finished

dwBytesSent += dwBytesWritten;

continue;

}

else

{

// an error occurred, try to recover

wsprintf( szError, "向串口发送数据出错,错误代码: %u", dwError ) ; MessageBox(NULL,szError,"发送数据出错",MB_ICONEXCLAMATION);

ClearCommError( IoInfoData.idComDev , &dwErrorFlags, &ComStat ) ;

break;

}

}

}

else

{

// some other error occurred

ClearCommError( IoInfoData.idComDev , &dwErrorFlags, &ComStat ) ;

if (dwErrorFlags > 0)

{

wsprintf( szError, "向串口发送数据出错,错误代码: %u", dwErrorFlags ) ;

MessageBox(NULL,szError,"发送数据出错",MB_ICONEXCLAMATION);

}

return ( FALSE );

}

}

return ( TRUE ) ;

} // end of SendData()

// Read the Datas.

// 从串口中读出数据

DWORD CSaimIO::GetData(unsigned char *DataBuffer, DWORD DataLength)

{

BOOL fReadStat ;

COMSTAT ComStat ;

DWORD dwErrorFlags;

DWORD dwLength = DataLength;

DWORD dwError;

char szError[ 128 ] ;

if (IoInfoData.fConnected == FALSE)

return ( FALSE ) ;

// SetCommMask( IoInfoData.idComDev ,EV_RXCHAR) ; //设定为收到第一个字符时产生中断

// unsigned long dwFlg;

// WaitCommEvent(IoInfoData.idComDev , &dwFlg, &IoInfoData.osRead); //等侍收到第一个字符事件发生

// if( (dwFlg & ( EV_RXFLAG | EV_RXCHAR )) == (EV_RXFLAG | EV_RXCHAR) )

{

// only try to read number of bytes in queue

ClearCommError( IoInfoData.idComDev, &dwErrorFlags, &ComStat ) ;

dwLength = min( 128, ComStat.cbInQue ) ;

if (dwLength > 0)

{

fReadStat = ReadFile( IoInfoData.idComDev, DataBuffer,

dwLength, &dwLength, &IoInfoData.osRead );

if (!fReadStat)

{

if (GetLastError() == ERROR_IO_PENDING)

{

// We have to wait for read to complete.

// This function will timeout according to the

// CommTimeOuts.ReadTotalTimeoutConstant variable

// Every time it times out, check for port errors

while(!GetOverlappedResult( IoInfoData.idComDev,

&IoInfoData.osRead, &dwLength, TRUE ))

{

dwError = GetLastError();

if(dwError == ERROR_IO_INCOMPLETE)

// normal result if not finished

continue;

else

{

// an error occurred, try to recover

相关主题