摘自--http://wangbo352.blog.163.com/blog/static/35148141200941345244651/
http://lijinshui.bokee.com/576993.html
只一个框架性流程而矣............
实现重叠模型的步骤
下面就结合俺写的一个Console程序简单示例进行说明:
【第一步】打开串口
HANDLE m_hCom = CreateFile("com1",GENERIC_READ | GENERIC_WRITE, 0, NULL,
OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL);
if (m_hCom == INVALID_HANDLE_VALUE)
{
cout<<"CreateFile fail!"<
return -1;
}
cout<<"CreateFile OK!"<< p="" />
【第二步】设置缓冲区大小
if(!SetupComm(m_hCom,2048,2048))
{
cout<<"SetupComm fail! Close Comm!"<
CloseHandle(m_hCom);
return -1;
}
cout<<"SetupComm OK!"<< p="" />
【第三步】设置超时
COMMTIMEOUTS TimeOuts;
memset(&TimeOuts,0,sizeof(TimeOuts));
TimeOuts.ReadIntervalTimeout = MAXDWORD;
TimeOuts.ReadTotalTimeoutConstant = 0;
TimeOuts.ReadTotalTimeoutMultiplier = 0;
TimeOuts.WriteTotalTimeoutConstant = 2000;
TimeOuts.WriteTotalTimeoutMultiplier = 50;
SetCommTimeouts(m_hCom,&TimeOuts);
【第四步】设置串口参数
DCB dcb;
if (!GetCommState(m_hCom,&dcb))
{
cout<<"GetCommState fail! Comm close"<
CloseHandle(m_hCom);
return -1;
}
cout<<"GetCommState OK!"<
dcb.DCBlength = sizeof(dcb);
if (!BuildCommDCB("9600,n,8,1",&dcb))//填充DCB的数据传输率、奇偶校验类型、数据位、停止位
{
//参数修改错误,进行错误处理
cout<<"BuileCOmmDCB fail,Comm close!"<
CloseHandle(m_hCom);
return -1;
}
if(SetCommState(m_hCom,&dcb))
{
cout<<"SetCommState OK!"<
}
【第五步】建立并初始化重叠结构
OVERLAPPED wrOverlapped;
ZeroMemory(&wrOverlapped,sizeof(wrOverlapped));
if (wrOverlapped.hEvent != NULL)
{
ResetEvent(wrOverlapped.hEvent);
wrOverlapped.hEvent = CreateEvent(NULL,TRUE,FALSE,NULL);
}
【第六步】封装数据(按照自己的格式封装需要发送的数据,此步可以省略)
typedef enum
{
HEAT_BEAT, //心跳数据
NET_STATE,//网络状态数据
PACKET //正常数据包
//支持可扩展性......
}ProtocolType;
typedef enum
{
Train_No,//无线车次信息
Attemper_Command,//调度命令信息
Revert_Command,//调度命令回执信息
Replay_Command,//重发的调度命令信息
KGL_SING //开关量数据
//支持可扩展性......
}PacketDataType;
//串口数据结构
typedef struct SerialNetProto
{
unsigned long PacketSize; //包总长度,不包括本身字段
ProtocolType NetState; //协议包类型
PacketDataType DataType; //数据类型
unsigned long SourcedAddr; //数据包源地址
unsigned long DestinationAddr; //数据包目的地址
unsigned long DataLength; //包的数据段长度
unsigned long Offset; // 数据在整个包中的偏移地址
}PacketHead;
int DataLen = 100;
char *pBuf = new char[DataLen];
strcpy(pBuf,"Hello World!");
DataLen = strlen(pBuf);
PacketHead Myhead;
Myhead.DestinationAddr = 11;
Myhead.SourcedAddr = 10;
Myhead.DataType = Attemper_Command;
Myhead.DataLength = DataLen;
Myhead.NetState = PACKET;
Myhead.PacketSize = sizeof(PacketHead) - sizeof(unsigned long);
Myhead.Offset = sizeof(Myhead.DestinationAddr) +sizeof(Myhead.SourcedAddr) + sizeof(Myhead.DataType) +sizeof(Myhead.DataLength) + sizeof(Myhead.NetState) + sizeof(Myhead.PacketSize);
char *pSendBuffer = new char[sizeof(Myhead)+DataLen+ 4];//发送的数据
memcpy(pSendBuffer,"##",2);//包头标志
memcpy(pSendBuffer+2,(char*)&Myhead,sizeof(Myhead));//包头
memcpy(pSendBuffer+2+sizeof(Myhead),pBuf,DataLen);//数据
memcpy(pSendBuffer+2+sizeof(Myhead)+DataLen,"@@",2);//包尾标志
【第七步】发送数据
DWORD dwError;
//DWORD dwWantSend = 100;
DWORD dwRealSend = 0;
char* pReadBuf = NULL;
if (ClearCommError(m_hCom,&dwError,NULL))
{
PurgeComm(m_hCom,PURGE_TXABORT | PURGE_TXCLEAR);
cout<<"PurgeComm OK!"<
}
if (!WriteFile(m_hCom,pSendBuffer,sizeof(Myhead)+DataLen+ 4,&dwRealSend,&wrOverlapped))
{
if (GetLastError() == ERROR_IO_PENDING)
{
while (!GetOverlappedResult(m_hCom,&wrOverlapped,&dwRealSend,FALSE))
{
if (GetLastError() == ERROR_IO_INCOMPLETE)
{
//cout<<"写未完成,继续!"<
continue;
}
else
{
cout<<"发生错误,尝试恢复!"<
ClearCommError(m_hCom,&dwError,NULL);
break;
}
}
}
}
【第八步】数据接收
DWORD dwError;
DWORD dwWantRead = 100;
DWORD dwRealRead = 0;
char* pReadBuf = new char[100];
if (ClearCommError(m_hCom,&dwError,NULL))
{
PurgeComm(m_hCom,PURGE_TXABORT | PURGE_TXCLEAR);
cout<<"PurgeComm OK!"<
}
if(!ReadFile(m_hComm,pReadBuf,dwWantRead,&RealRead,&wrOverlapped))
{
if(dwError = GetLastError()==ERROR_IO_PENDING)
{
While(GetOverlappedResult(m_hComm,&wrOverlapped,&dwRealRead,FALSE))
{
//对接收到的数据进行数据解析,处理
//【第九步】............
cout<<"dwRealRead = "<<
}
}
}
【第九步】数据解析(数据解包处理)
#define MAX_SERIAL_BUFFER 4096
BOOL CanGetFullFrame(char* pReadBuf,int& dwRealRead)
{
static char Buf[MAX_SERIAL_BUFFER*2];//自定义一个数据缓冲区
static unsigned long nFrameStart = 0;//数据祯的开始位置
static unsigned long nFrameEnd = 0;//数据祯的结束位置
static unsigned long nCurrectPos = 0;//指针当前位置
char *pdest = NULL;
if (pReadBuf && (dwRealRead!= 0))
{
memcpy(&Buf[nCurrectPos],pReadBuf,dwRealRead);
nCurrectPos = nCurrectPos + dwRealRead;//更新当前位置
}
//查找数据祯的开始标志
pdest = (char*)Find(Buf,"##",MAX_SERIAL_BUFFER*2,2);
if (pdest)
{
nFrameStart = unsigned long(pdest - Buf);//找到数据祯的开始位置
}
else//没有找到开始祯标志"##"
{
Buf[0] = Buf[nCurrectPos];//丢弃数据
nFrameStart = 0;
return FALSE;
}
//查找数据祯的结尾标志
pdest = (char*)Find(Buf,"@@",MAX_SERIAL_BUFFER*2,2);
if (pdest)
{
nFrameEnd = unsigned long (pdest - Buf+2);
dwRealRead= nFrameEnd - nFrameStart;
memcpy(pReadBuf,&Buf[nFrameStart],dwRealRead);
nFrameStart = nFrameEnd;//指向下一帧的开始位置
nCurrectPos = nCurrectPos - dwRealRead;//修正nCurrentPos值
memcpy(Buf,&Buf[nFrameEnd],nCurrectPos);//向前移动数据
return TRUE;
}
else
{
return FALSE;
}
}
//一个在内存块中查找指定字符串的函数
void* Find(const char *pSour,const char *pDest,int SourLen,int DestLen)
{
int i = 0, j = 0;
while(i < SourLen && j < DestLen)
{
if(*(pSour + i) == *(pDest + j))
{
i++;
j++;
}
else
{
i =i - j + 1;
j = 0;
}
}
if(j == DestLen)
{
return (void*)(pSour + (i - DestLen));
}
else
{
return NULL;
}
}
【第十步】重新投递Overlapped,略......