📄 serialcommlayer.cpp
字号:
LPBYTE lpszStringToWrite = (LPBYTE) LocalAlloc(LPTR, dwNumberOfBytesToWrite);
memcpy(lpszStringToWrite,cCmdStr,dwNumberOfBytesToWrite);
if (WriteThread->PostThreadMessage(PWM_COMMWRITE,
(WPARAM) (dwNumberOfBytesToWrite), (LPARAM) lpszStringToWrite))
{
return 0;
}
LocalFree(lpszStringToWrite);
return 1;
}
//
// 函数: BOOL CRCCComm::CheckSum(RCCFrameHead Header)
// 用途: 校验检查和是否正确.
// 参数:
// Header 帧头数据
// 返回值:
// TRUE 校验成功
// FALSE 校验失败
// 备注:
// 帧头检查和是一字节的简单数据校验和
//
BOOL CRCCComm::CheckSum(RCCFrameHead Header)
{
WORD wCheckSum=0;
BYTE bCheckSum=0;
int i;
bCheckSum = Header.CheckSum;
Header.CheckSum = 0;
for ( i=0;i < HeaderSize; i++)
wCheckSum += ((BYTE *)&Header)[i];
if((wCheckSum & 0xFF) == bCheckSum)
return TRUE;
else return FALSE;
}
//
// 函数: BYTE CRCCComm::GetCheckSum(RCCFrameHead *Header)
// 用途: 得到帧头检查和
// 参数:
// Header 帧头数据
// 返回值:
// 帧头数据校验值
// 备注:
// 帧头检查和是一字节的简单数据校验和
//
BYTE CRCCComm::GetCheckSum(RCCFrameHead *Header)
{
WORD wCheckSum=0;
int i;
for ( i=0;i < HeaderSize; i++)
wCheckSum += ((BYTE *)Header)[i];
return (BYTE)(wCheckSum&0xFF);
}
//
// 函数: int CRCCComm::GenOneFrame(void)
// 用途: 将SendBuffer之中的数据生成一个帧,放入类变量DataFrame,准备发送出去。
// 参数: 无
// 返回值:
// 0表示成功
// 备注:
// 数据发送将采取压缩方式,如果压缩后长度大于压缩前长度,则采用非压缩方式
//
int CRCCComm::GenOneFrame(void)
{
int FrameLength = min(BytesPerBlock,SendBufferLength);
DataFrame.Header.Flag = FrameFlag;
DataFrame.Header.Version = RCC_VERSION;
int SendFrameNo = (PrevSendFrameNo==255?1:PrevSendFrameNo+1);
DataFrame.Header.FrameNo = SendFrameNo;
PrevSendFrameNo = SendFrameNo;
DataFrame.Header.Reserved = 0;
DataFrame.Header.CheckSum = 0;
#ifdef __RCC_ZIP__
FileEncodeDecode encodeObject(SendBuffer,ZippedBuf,FrameLength);
int ZippedLength = encodeObject.Encode(); //赋值压缩后的长度
if((ZippedLength != -1) && (ZippedLength+2 < FrameLength))
{
DataFrame.Header.Kind = frmZippedData;
memcpy(DataFrame.Data+2,ZippedBuf,ZippedLength);
DataFrame.Header.Length = ZippedLength + 2;
*(WORD *)DataFrame.Data = FrameLength;
DataFrame.Crc = GetCrc(ZippedLength+2,(BYTE *)DataFrame.Data);
}
else
{
#endif
DataFrame.Header.Kind = frmData;
DataFrame.Header.Length = FrameLength;
memcpy(DataFrame.Data,SendBuffer,FrameLength);
DataFrame.Crc = GetCrc(FrameLength,(BYTE *)DataFrame.Data);
#ifdef __RCC_ZIP__
}
#endif
DataFrame.Header.CheckSum = GetCheckSum(&DataFrame.Header);
#ifdef __RCC_DEBUG__
char DbgMsg[100];
sprintf(DbgMsg,"[%d]生成一帧,长度[%d],RCCStatus[%d]",SendFrameNo,FrameLength+10,RCCStatus);
DisplayMessage(DbgMsg);
int hLogFile;
if ( ( hLogFile = sopen ( "Log.Txt", O_RDWR | O_APPEND | O_CREAT ,SH_DENYNO,
S_IREAD | S_IWRITE ) ) != -1 )
{
_write ( hLogFile, DbgMsg, strlen ( DbgMsg ) );
_write ( hLogFile,"\r\n",2);
for ( int m=0; m<FrameLength+10; m++)
{
if(!(m%20))
_write ( hLogFile,"\r\n",2);
sprintf(DbgMsg,"[%X]",((unsigned char*)&DataFrame)[m]);
_write ( hLogFile, DbgMsg, strlen ( DbgMsg ) );
}
_write ( hLogFile,"\r\n",2);
_close(hLogFile);
}
#endif
DelDealtData(SendBuffer,SendBufferLength,FrameLength);
return 0;
}
//
// 函数: int CRCCComm::SendDataFrame(void)
// 用途: 将GenOneFrame函数生成的DataFrame帧发送出去。
// 参数: 无
// 返回值:
// 0 表示成功
// 1 表示失败
// 备注:
//
int CRCCComm::SendDataFrame(void)
{
int dwNumberOfBytesToWrite = HeaderSize+2+DataFrame.Header.Length;
LPBYTE lpszStringToWrite = (LPBYTE) LocalAlloc(LPTR, dwNumberOfBytesToWrite);
memcpy(lpszStringToWrite,&DataFrame,dwNumberOfBytesToWrite);
if (WriteThread->PostThreadMessage(PWM_COMMWRITE,
(WPARAM) dwNumberOfBytesToWrite, (LPARAM) lpszStringToWrite))
{
WriteTime = GetTickCount();
return 0;
}
LocalFree(lpszStringToWrite);
return 1;
}
//
// 函数: int CRCCComm::SendMsgFrame(BYTE frmType,int NewFrameOrReSend)
// 用途: 生成一个消息帧,用于应答数据
// 参数:
// frmType 帧类别
// NewFrameOrReSend 指示是重新生成还是重发上一消息帧
// 返回值:
// 0 表示成功
// 1 表示失败
// 备注:
// 如果发送frmSysError帧数量达到十次,再关闭链接
//
int CRCCComm::SendMsgFrame(BYTE frmType,int NewFrameOrReSend)
{
if(NewFrameOrReSend != RESEND)
{ //重新生成新的一帧
MsgFrame.Flag = FrameFlag;
MsgFrame.Version = RCC_VERSION;
MsgFrame.FrameNo = PrevReceFrameNo;
MsgFrame.Length = HeaderSize;
MsgFrame.Reserved = 0;
MsgFrame.CheckSum = 0;
switch(frmType)
{
case frmDataAnswer://数据应答帧
MsgFrame.Kind = frmDataAnswer;
frmErrorNums = 0;
break;
case frmPolling://检测帧
MsgFrame.FrameNo = PrevSendFrameNo;
MsgFrame.Kind = frmPolling;
frmErrorNums = 0;
break;
case frmPlAnswer://检测应答帧
MsgFrame.Kind = frmPlAnswer;
frmErrorNums = 0;
break;
case frmAbort://异常中止帧
MsgFrame.FrameNo = 0;
MsgFrame.Kind = frmAbort;
frmErrorNums = 0;
break;
case frmSysError://系统错误帧
MsgFrame.Kind = frmSysError;
frmErrorNums ++;
if(frmErrorNums >= 10)
{
PostRCCMessage(RCC_ERROR,0);
Close();
return 1;
}
break;
default:
ASSERT(FALSE);
return 1;
}
MsgFrame.CheckSum = GetCheckSum(&MsgFrame);
if(frmType != frmSysError)
{
LastFrameClass = 2;
}
}
#ifdef __RCC_DEBUG__
char DbgMsg[100];
sprintf(DbgMsg,"发应的应答帧[%d],帧号[%d]",MsgFrame.Kind,MsgFrame.FrameNo);
DisplayMessage(DbgMsg);
#endif
LPBYTE lpszStringToWrite = (LPBYTE) LocalAlloc(LPTR, HeaderSize);
memcpy(lpszStringToWrite,&MsgFrame,HeaderSize);
if (WriteThread->PostThreadMessage(PWM_COMMWRITE,
(WPARAM)HeaderSize, (LPARAM) lpszStringToWrite))
{
return 0;
}
LocalFree(lpszStringToWrite);
return 1;
}
//
// 函数: LRESULT CRCCComm::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
// 用途: 底层通讯消息截获函数
// 参数:
// 返回值:
// 备注:
// 本底层主要的通讯方式基于消息,所有的消息分发都通过本函数
LRESULT CRCCComm::WindowProc(UINT message, WPARAM wParam, LPARAM lParam)
{
// TODO: Add your specialized code here and/or call the base class
int Device;
int NotifyCode;
switch(message)
{
case WM_TIMER: //时间处理函数
Timer();
return 1;
case PWM_GOTCOMMDATA:
OnRawReceive((LPSTR)lParam,(DWORD)wParam); //LPSTR lpNewString,DWORD dwSizeOfNewString)
return 1;
case PWM_REQUESTHANGUP: //关闭链接
#ifdef __RCC_DEBUG__
DisplayMessage("关闭!");
#endif
Close();
return 1;
case PWM_RECEIVEERROR:
#ifdef __RCC_DEBUG__
DisplayMessage("发生错误!");
#endif
return 1;
case WM_RCCNOTIFY:
NotifyCode = LOWORD(wParam);
Device = HIWORD(wParam);
switch(NotifyCode)
{
case RCC_RAWWRITE: //原始写入
if(SendBufferLength <= 0)
{
PostRCCMessage(RCC_WRITE,0);
return 1;
}
if(RCCStatus == RCC_STAT_COMM) // || RCCStatus == RCC_STAT_POLLING
{
GenOneFrame(); //生成一帧数据帧
SendDataFrame(); //发送一帧数据帧
RCCStatus = RCC_STAT_DATA;
LastFrameClass = 1;
}
return 1;
case RCC_CONNECT:
OnConnect();
break;
case RCC_READ:
OnReceive();
break;
case RCC_WRITE:
OnSend();
break;
case RCC_CLOSE:
OnClose();
break;
case RCC_ERROR:
OnError();
break;
case RCC_RAWREAD:
break;
case RCC_BIN_STATE:
OnBinaryState(lParam);
break;
case RCC_STR_STATE:
OnStringState(lParam);
break;
}
}
return CWnd::WindowProc(message, wParam, lParam);
}
//发送RCC底层通讯消息
int CRCCComm::PostRCCMessage(int Msg,int Notify)
{
return PostMessage(WM_RCCNOTIFY,MAKEWPARAM(Msg,CommNo),Notify);
}
int CRCCComm::SendRCCMessage(int Msg,int Notify)
{
return SendMessage(WM_RCCNOTIFY,MAKEWPARAM(Msg,CommNo),Notify);
}
//
// 函数: int CRCCComm::DelDealtData(char *Buffer,int &Length,int DelNum)
// 用途: 删除缓冲区的数据,并将剩下的数据往前挪
// 参数:
// Buffer 数据缓冲区
// Length 数据缓冲区长度
// DelNum 需要删除的数据长度
// 返回值: 目前无具体涵义
// 备注:
//
int CRCCComm::DelDealtData(char *Buffer,int &Length,int DelNum)
{
ASSERT(Length >= DelNum);
if(DelNum <= 0) return 0;
if(Length == DelNum)
{
Length = 0;
}
else
{
memcpy(Buffer,&Buffer[DelNum],Length-DelNum);
Length -= DelNum;
}
return 0;
}
//
// 函数: int CRCCComm::OnRawReceive(LPSTR lpNewString,DWORD dwSizeOfNewString)
// 用途: 原始数据的接收,本函数是进行RCC协议解析的函数。
// 参数:
// lpNewString 接收到的新数据
// dwSizeOfNewString 新数据的长度
// 返回值: 目前无具体涵义
// 备注:
// 如果应用程序想直接获取原始数据,可稍做修改,派生本函数
//
int CRCCComm::OnRawReceive(LPSTR lpNewString,DWORD dwSizeOfNewString)
{
#ifdef __RCC_DEBUG__
char DbgMsg[100];
sprintf(DbgMsg,"接收到字符串[%d],RCCStatus[%d]",dwSizeOfNewString,RCCStatus);
DisplayMessage(DbgMsg);
#endif
if((RCCStatus == RCC_STAT_INIT || RCCStatus == RCC_STAT_ABORT) && (RCCMode == MODE_MODEM))
{
ParseAnswer(lpNewString,dwSizeOfNewString);
delete lpNewString;
return 1;
}
#ifdef __RCC_DEBUG__
int hLogFile;
if ( ( hLogFile = sopen ( "Log.Txt", O_RDWR | O_APPEND | O_CREAT ,SH_DENYNO,
S_IREAD | S_IWRITE ) ) != -1 )
{
_write ( hLogFile, DbgMsg, strlen ( DbgMsg ) );
_write ( hLogFile,"\r\n",2);
for ( unsigned int m=0; m<dwSizeOfNewString; m++)
{
if(!(m%20))
_write ( hLogFile,"\r\n",2);
sprintf(DbgMsg,"[%X]",(unsigned char)lpNewString[m]);
_write ( hLogFile, DbgMsg, strlen ( DbgMsg ) );
}
_write ( hLogFile,"\r\n",2);
_close(hLogFile);
}
#endif
if(ReceiveBufferLength + dwSizeOfNewString > ReceiveBufferMaxLength)
{ //接收缓冲区溢出
LastError = RCC_ERROR_OVERFLOW;
PostRCCMessage(RCC_ERROR,RCC_ERROR_OVERFLOW);
SendMsgFrame(frmAbort); //发送终止传输帧
delete lpNewString;
return 1;
}
memcpy(&ReceiveBuffer[ReceiveBufferLength],lpNewString,dwSizeOfNewString);
ReceiveBufferLength += dwSizeOfNewString;
delete lpNewString;
int ret = 0;
if(ReceiveBufferLength >= 54)
ret = 0;
while(ReceiveBufferLength >= HeaderSize)
{
ret = GetFrame(); //从接收缓冲区之内分析一个帧,将修改ReceiveBufferLength
if(ret) //返回零则继续,其它不再继续处理
break;
}
return 0;
}
//
// 函数: int CRCCComm::GetFrame(void)
// 用途: 在帧缓冲区内进行帧分析,根据返回的错误进行相应的处理
// 本函数是系统中最重要的函数之一
// 参数: 无
// 返回值:
// 0 表示可继续解析帧
// 1 表示不再继续解析帧
// 备注:
//
int CRCCComm::GetFrame(void)
{
RCCFrameHead FrameHeader;
int pos = SearchHead(); //首先找到帧头标志
if(ReceiveBufferLength - pos < HeaderSize)
{ //如果缓冲区不足以一个帧头
#ifdef __RCC_DEBUG__
DisplayMessage("字符不够解析,1");
#endif
return 1;
}
memcpy(&FrameHeader,&ReceiveBuffer[pos],HeaderSize);
pos += HeaderSize;
if(!CheckSum(FrameHeader))
{ //检查和不对
#ifdef __RCC_DEBUG__
DisplayMessage("检查和不对");
ASSERT(FALSE);
#endif
SendMsgFrame(frmSysError);
return 1;
}
if(FrameHeader.Version != RCC_VERSION)
{ //版本不对
#ifdef __RCC_DEBUG__
DisplayMessage("版本不对");
ASSERT(FALSE);
#endif
LastError = RCC_ERROR_VERSION;
PostRCCMessage(RCC_ERROR,RCC_ERROR_VERSION);
SendMsgFrame(frmAbort); //发送终止传输帧
Close();
return 1;
}
RCCDataFrame Data;
switch(FrameHeader.Kind)
{
case frmData://数据帧
if(pos + FrameHeader.Length + 2 > ReceiveBufferLength)
{ //缓冲区超出等待剩余部分数据到达
#ifdef __RCC_DEBUG__
DisplayMessage("数据字符不够解析,1");
#endif
return 1;
}
if(FrameHeader.Length>0 && FrameHeader.Length <=MaxBytesPerBlock)
{
//得到一帧数据
memcpy(&Data,&ReceiveBuffer[pos-HeaderSize],
HeaderSize + FrameHeader.Length + 2);
pos += (FrameHeader.Length + 2);
DelDealtData(ReceiveBuffer,ReceiveBufferLength,pos);
if(RCCStatus == RCC_STAT_COMM||RCCStatus == RCC_STAT_DATA)
{ //仅只有在此状态下才接收数据
WORD Crc = GetCrc(FrameHeader.Length,(BYTE *)Data.Data);
if(Data.Crc != Crc) //如果校验值不对
{
#ifdef __RCC_DEBUG__
DisplayMessage("CRC校验不对");
ASSERT(FALSE);
#endif
SendMsgFrame(frmDataAnswer,RESEND);
return 1;
}
int ReceFrameNo=PrevReceFrameNo==255?1:PrevReceFrameNo+1;
if(FrameHeader.FrameNo == PrevReceFrameNo)
{ //如果是上一帧的重发帧,则忽略,发送接收OK
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -