/* 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