#include "stdafx.h"
#include "SerialPort.h"
#include <assert.h>
CSerialPortEx::CSerialPortEx()
{
m_hComm = NULL;
ISSTOP = FALSE;
tOverLaped.hEvent = NULL;
tOverLaped.Internal = 0;
tOverLaped.InternalHigh = 0;
tOverLaped.Offset = 0;
tOverLaped.OffsetHigh = 0;
rOverLaped.hEvent = NULL;
rOverLaped.Internal = 0;
rOverLaped.InternalHigh = 0;
rOverLaped.Offset = 0;
rOverLaped.OffsetHigh = 0;
}
//
// Delete dynamic memory
//
CSerialPortEx::~CSerialPortEx()
{
TRACE("Thread ended\n");
}
BOOL CSerialPortEx::InitPort(CWnd* pPortOwner, // the owner (CWnd) of the port (receives message)
UINT portnr, // portnumber (1..4)
UINT baud, // baudrate
char parity, // parity
UINT databits, // databits
UINT stopbits, // stopbits
DWORD dwCommEvents, // EV_RXCHAR, EV_CTS etc
UINT writebuffersize) // size to the writebuffer
{
assert(pPortOwner != NULL);
char *szPort = new char[50];
char *szBaud = new char[50];
closeflag = TRUE;//2012-10-27表示的是要打开串口
if (m_hComm != NULL)
{
CloseHandle(m_hComm);
m_hComm = NULL;
}
sprintf(szPort, "COM%d", portnr);
sprintf(szBaud, "baud=%d parity=%c data=%d stop=%d", baud, parity, databits, stopbits);
m_hComm = CreateFile(szPort, // communication port string (COMX)
GENERIC_READ | GENERIC_WRITE, // read/write types
0, // comm devices must be opened with exclusive access
NULL, // no security attributes
OPEN_EXISTING, // comm devices must use OPEN_EXISTING
FILE_FLAG_OVERLAPPED|FILE_ATTRIBUTE_NORMAL, // Async I/O
0); // template must be 0 for comm devices
if (m_hComm == INVALID_HANDLE_VALUE)
{
delete [] szPort;
delete [] szBaud;
MessageBox(NULL,"串口已经被占用请重新选择","提示信息",MB_OK);
return FALSE;
}
delete [] szPort;
delete [] szBaud;
SetupComm(m_hComm,writebuffersize,writebuffersize);
GetCommState(m_hComm,&m_dcb);
m_dcb.BaudRate = baud;
m_dcb.fBinary = TRUE;
m_dcb.fParity = TRUE;
m_dcb.ByteSize = databits;
m_dcb.Parity = NOPARITY;
m_dcb.StopBits = ONESTOPBIT;
if(!SetCommState(m_hComm,&m_dcb))
{
MessageBox(NULL,"设置DCB失败","提示信息",MB_OK);
return FALSE;
}
if (!SetCommMask(m_hComm,EV_RXCHAR))
{
MessageBox(NULL,"设置掩码失败","提示信息",MB_OK);
return FALSE;
}
return TRUE;
}
/*
函数名称 : CommThread
函数功能 : 创建接收线程
*/
UINT CSerialPortEx::CommThread(LPVOID pParam)
{
CSerialPortEx *port = (CSerialPortEx*)pParam;
DWORD BytesTransfered = 0;
DWORD Event = 0;
DWORD dwResult = 0;;
DWORD CommEvent = 0;
DWORD dwError = 0;
BOOL bResult = TRUE,read_falg = false;
INT Length = 1024;
port->rOverLaped.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
for (;;)
{
if (port->closeflag == FALSE)
{
break;
}
Length = 1024;
WaitCommEvent(port->m_hComm, &Event, &(port->rOverLaped));//等待IO口发送接收事件
dwResult = WaitForSingleObject(port->rOverLaped.hEvent,100);
if (dwResult == WAIT_OBJECT_0)
{
if (Event == EV_RXCHAR)//表示接收数据
{
if (port->ISSTOP)//说明的是发送成功
{
Sleep(400);//等待接收完成
port->ReadBlock(port,Length);
PurgeComm(port->m_hComm, PURGE_RXCLEAR|PURGE_RXABORT);//清空接收缓冲区
}
}
}
}
return 0;
}
/*********************************************************
函数名称 : ReadBlock(CSerialPortEx *port, int& readLen)
函数功能 : 从串口读取一块数据
函数返回 : void
***********************************************************/
void CSerialPortEx::ReadBlock(CSerialPortEx *port, int& readLen)
{
BOOL bRead = TRUE;
BOOL bResult = TRUE;
BYTE *DataBuffer = NULL;
UINT i = 0;
DWORD dwError = 0;
DWORD BytesRead = 0;
DWORD BytesToRead=readLen;
DWORD res,factbyte;
COMSTAT rst;
ClearCommError(m_hComm,&res,&rst);
if (rst.cbInQue == 0)
{
readLen=0;
return;
}
else
{
BytesToRead= BytesToRead+2 > rst.cbInQue ? rst.cbInQue : BytesToRead+2;
DataBuffer=new BYTE[BytesToRead];
}
rOverLaped.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
if(!ReadFile(m_hComm,DataBuffer,BytesToRead,&factbyte,&rOverLaped))//成功返回的是非零
{
dwError = GetLastError();
if (dwError == ERROR_IO_PENDING)
{
bResult = GetOverlappedResult(m_hComm,&rOverLaped,&factbyte,TRUE);
if (!bResult)
{
MessageBox(NULL,"接收失败","鹏奥达友情提示",MB_OK);
}
}
}
for(i = 0; i<factbyte;i++)
{
porttail %= MAXLENGTH;//0~255
Serialport[port->porttail] = DataBuffer[ i ];
porttail++;
}
delete [] DataBuffer;
DataBuffer = NULL;
ISSTOP = FALSE;
}
/*******************************************************
函数名称 : WriteToPort(BYTE *string,int nLength)
函数功能 : 写串口
函数注意 : ISSTOP == FALSE 表示的是发送失败
ISSTOP == TRUE 表示的是发送成功
*********************************************************/
void CSerialPortEx::WriteToPort(BYTE *string,int nLength)
{
DWORD res;
DWORD facedata = 0;
PurgeComm(m_hComm, PURGE_TXCLEAR);
tOverLaped.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
ISSTOP = FALSE;
if(WriteFile(m_hComm,string,nLength,&facedata,&tOverLaped))
{
ISSTOP = TRUE;
}
else
{
res = WaitForSingleObject(tOverLaped.hEvent,5000);
if (WAIT_OBJECT_0 == res){
ISSTOP = TRUE;
}
else{
ISSTOP = FALSE;
Sleep(500);
}
}
}
/****************************************************
函数名称 : void closemyport(void)
函数功能 : 关闭串口
*****************************************************/
void CSerialPortEx::closemyport(void)
{
closeflag = FALSE;
Sleep(10);//等待10ms;
//m_Thread->SuspendThread();
if (m_hComm != NULL)
{
CloseHandle(m_hComm);
m_hComm = NULL;
}
}
/*****************************************************
函数名称 : StartMonitoring()
函数功能 : 开启数据监听
******************************************************/
BOOL CSerialPortEx::StartMonitoring()
{
if (!(m_Thread = AfxBeginThread(CommThread, this)))
return FALSE;
TRACE("Thread started\n");
return TRUE;
}
/**************************************************
函数名称 : GetDataFormBuffer
函数功能 : 从缓冲区获取一个数据
函数参数 : posdata表示的是要获取数据的编号
***************************************************/
BYTE CSerialPortEx::GetDataFormBuffer(UINT posdata)
{
UINT TempHead = porthead;
TempHead += posdata;
TempHead %= MAXLENGTH;
return Serialport[TempHead];
}
/***************************************************
函数名称 : DeletDataFromBuffer
函数功能 : 从缓冲区清除一个数据
函数参数 : 要从缓冲区中清除的数据的个数
****************************************************/
void CSerialPortEx::DeletDataFromBuffer(BYTE count)
{
porthead += count;
porthead %= MAXLENGTH;
}
/**************************************************
函数名称 : ReportLeng
***************************************************/
UINT CSerialPortEx::ReportLeng(void)
{
return ((porttail + MAXLENGTH - porthead))%MAXLENGTH;
}
/************************************
函数名称 : Initbuffer
函数功能 : 初始化接收buffer
*************************************/
void CSerialPortEx::Initbuffer(void)
{
porttail = 0;
porthead = 0;
memset(Serialport,0,1024);
}
/***************************************************************
函数名称 : SendAndGetData
函数功能 : 发送并接受一帧数据
函数参数 : senddata 发送缓冲区
mybuffer 接收缓冲区
函数返回 : FALSE 发送接收失败
TRUE 发送接收成功
****************************************************************/
BOOL CSerialPortEx::SendAndGetData(BYTE *senddata,BYTE *mybuffer)
{
UINT i = 0;
UINT length;
BYTE cs = 0;
Initbuffer();
WriteToPort(&senddata[1],senddata[0]);
do
{
Sleep(10);
i++;
} while ((i<1000)&&(ISSTOP != FALSE));
if( ReportLeng()>4 )
{
if(Ge