⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 serialcommlayer.cpp

📁 串口通讯在客户端/服务器类型的应用程序设计中经常要使用到
💻 CPP
📖 第 1 页 / 共 5 页
字号:
#ifdef __RCC_DEBUG__
					DisplayMessage("重发帧");
					ASSERT(FALSE);
#endif
					SendMsgFrame(frmDataAnswer); //发送终止传输帧
				}
				else if (FrameHeader.FrameNo == ReceFrameNo)
				{ //帧收到
					if(FrameHeader.Length + DataBufferLength > DataBufferMaxLength)
					{ //应用程序缓冲区不够
						LastError = RCC_ERROR_OVERFLOW;
						PostRCCMessage(RCC_ERROR,RCC_ERROR_OVERFLOW);
						SendMsgFrame(frmAbort); //发送终止传输帧
						return 1;
					}
					else
					{ //数据收到
						memcpy(&DataBuffer[DataBufferLength],Data.Data,FrameHeader.Length);
						DataBufferLength += FrameHeader.Length;
						PostRCCMessage(RCC_READ,0);
						PrevReceFrameNo = ReceFrameNo;
						SendMsgFrame(frmDataAnswer); //发送终止传输帧
					}
				}
				else 
				{ //同步丢失
					LastError = RCC_ERROR_SYNC;
					PostRCCMessage(RCC_ERROR,RCC_ERROR_SYNC);
					SendMsgFrame(frmAbort); //发送终止传输帧
					return 1;
				}

			}
		}
		else
		{
			LastError = RCC_ERROR_FRAME;
			PostRCCMessage(RCC_ERROR,RCC_ERROR_FRAME);
			SendMsgFrame(frmAbort); //发送终止传输帧
			return 1;
		}
		break;
	case frmZippedData://压缩数据帧
		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
#ifdef __RCC_DEBUG__
					DisplayMessage("重发帧");
					ASSERT(FALSE);
#endif
					SendMsgFrame(frmDataAnswer); //发送终止传输帧
				}
				else if (FrameHeader.FrameNo == ReceFrameNo)
				{ //帧收到
					if(FrameHeader.Length + DataBufferLength > DataBufferMaxLength)
					{ //应用程序缓冲区不够
						LastError = RCC_ERROR_OVERFLOW;
						PostRCCMessage(RCC_ERROR,RCC_ERROR_OVERFLOW);
						SendMsgFrame(frmAbort); //发送终止传输帧
						return 1;
					}
					else
					{ //数据收到
						int RealLength = *(WORD *)Data.Data;
						int UnzippedLength;
						FileEncodeDecode encodeObject(Data.Data+2,ZippedBuf,Data.Header.Length-2);
						UnzippedLength = encodeObject.Decode(); //赋值压缩后的长度
						if(UnzippedLength == -1 || UnzippedLength != RealLength )
						{
							ASSERT(FALSE);
							return 1;
						}
						memcpy(&DataBuffer[DataBufferLength],ZippedBuf,UnzippedLength);
						DataBufferLength += UnzippedLength;
						PostRCCMessage(RCC_READ,0);
						PrevReceFrameNo = ReceFrameNo;
						SendMsgFrame(frmDataAnswer); //发送应答帧
					}
				}
				else 
				{ //同步丢失
					LastError = RCC_ERROR_SYNC;
					PostRCCMessage(RCC_ERROR,RCC_ERROR_SYNC);
					SendMsgFrame(frmAbort); //发送终止传输帧
					return 1;
				}

			}
		}
		else
		{
			LastError = RCC_ERROR_FRAME;
			PostRCCMessage(RCC_ERROR,RCC_ERROR_FRAME);
			SendMsgFrame(frmAbort); //发送终止传输帧
			return 1;
		}
		break;
	case frmDataAnswer://数据应答帧
		DelDealtData(ReceiveBuffer,ReceiveBufferLength,HeaderSize);
		if(RCCStatus == RCC_STAT_DATA)
		{ //仅只有在数据发送出去时才接收DataAnswer
			RCCStatus = RCC_STAT_COMM;
			int SendFrameNo = (PrevSendFrameNo==1?255:PrevSendFrameNo - 1);

			if(FrameHeader.FrameNo == SendFrameNo)
			{ //重发上一帧

				SendDataFrame();
			}
			else if(FrameHeader.FrameNo == PrevSendFrameNo)
			{ //如果上一帧接收到了
				PostRCCMessage(RCC_RAWWRITE,0); //发送完毕,继续发送下一帧
			}
			else
			{ //帧同步丢失
				DisplayMessage("数据帧应答时帧同步丢失");
				ASSERT(FALSE);
				LastError = RCC_ERROR_SYNC;
				PostRCCMessage(RCC_ERROR,RCC_ERROR_SYNC);
				SendMsgFrame(frmAbort); //发送终止传输帧
				return 1;
			}
		}
		else 
		{ //忽略
		}
		break;
	case frmPolling://检测帧
		DelDealtData(ReceiveBuffer,ReceiveBufferLength,HeaderSize);
		SendMsgFrame(frmPlAnswer);
		break;
	case frmPlAnswer://检测应答帧
		DelDealtData(ReceiveBuffer,ReceiveBufferLength,HeaderSize);
		if(RCCStatus == RCC_STAT_POLLING)
		{ //仅只有在检测状态时才接收frmPlAnswer
			RCCStatus = RCC_STAT_COMM;
			int SendFrameNo = (PrevSendFrameNo==1?255:PrevSendFrameNo - 1);

			if(FrameHeader.FrameNo == SendFrameNo)
			{ //重发上一帧
				SendDataFrame();
			}
			else if(FrameHeader.FrameNo == PrevSendFrameNo)
			{ //如果上一帧接收到了
				PostRCCMessage(RCC_RAWWRITE,0); //发送完毕,继续发送下一帧
			}
			else
			{ //帧同步丢失
				LastError = RCC_ERROR_SYNC;
				PostRCCMessage(RCC_ERROR,RCC_ERROR_SYNC);
				SendMsgFrame(frmAbort); //发送终止传输帧
				return 1;
			}
		}
		else 
		{ //忽略
		}
		break;
	case frmAbort://异常中止帧
		PostRCCMessage(RCC_ERROR,0);
		Close();
		break;
	case frmSysError://系统错误帧
		DelDealtData(ReceiveBuffer,ReceiveBufferLength,ReceiveBufferLength);
		if(LastFrameClass == 0) //上次什么帧也没有发送
			break;
		else if(LastFrameClass == 1) 
		{//数据帧
			SendDataFrame();
		}
		else if(LastFrameClass == 2) 
		{ //消息帧
			SendMsgFrame(RESEND);
		}
		else
			ASSERT(FALSE);

		break;
	default:
		LastError = RCC_ERROR_FRAMETYPE;
		PostRCCMessage(RCC_ERROR,RCC_ERROR_FRAMETYPE);
		SendMsgFrame(frmAbort); //发送终止传输帧
		return 1;
	}
	return 0;
}


void CRCCComm::OnConnect()
{
	DisplayMessage("链接建立");
}

void CRCCComm::OnSend()
{
	DisplayMessage("数据空闲,发送下一块");
	if(nBytesRead >= FileSize)
	{
		char Msg[50];
		sprintf(Msg,"结束时间:%lu",GetTickCount());
		DisplayMessage(Msg);
	}

	int SendLen = min(FileSize-nBytesRead,8192);
	Send(&FileBuf[nBytesRead],SendLen);
	nBytesRead += SendLen;
}

void CRCCComm::OnReceive()
{
	char Msg[50];
	static long num = 0;
	sprintf(Msg,"接收到数据",num++);
	DisplayMessage(Msg);
//#ifdef __RCC_DEBUG__
	char buffer[3000];
	int Length = Receive(buffer,3000);
//	if(Length > 0)
//	{
//		buffer[Length] = 0;
//		DisplayMessage(buffer);
//	}
//#endif
}

void CRCCComm::OnClose()
{
	DisplayMessage("链接关闭");
}

void CRCCComm::OnError()
{
	DisplayMessage("发生错误");
}

void CRCCComm::OnBinaryState(DWORD State)
{
	DWORD ModemStatus;
	if(State & MDM_CONN)
	{
		 if(GetCommModemStatus(hCommFile,&ModemStatus))
		 {
			 if (!(ModemStatus & MS_RLSD_ON ))
			 {
				 Close();
			 }
			 else if ( (ModemStatus & MS_RLSD_ON) && (RCCMode == MODE_RS232))
			 {
				RCCStatus = RCC_STAT_COMM;
				PostRCCMessage(RCC_CONNECT,0);
			 }
		 }
	}
}

void CRCCComm::OnStringState(DWORD State)
{
	if(State & MDM_CONN)
	{
		RCCStatus = RCC_STAT_COMM;
		PostRCCMessage(RCC_CONNECT,0);
	}

}
//MODEM返回字符串
char MDMAnswerStr[][20] =
{
	"OK",
	"NO CARRIER",
	"ERROR",
	"NO DIAL",
	"BUSY",
	"NO ANSWER",
	"RING",
	"CONNECT",
	"PROTOCOL:",
	"COMPRESSION:",
	"CARRIER"
};
//
//  函数: int CRCCComm::ParseAnswer(LPSTR AnswerString,DWORD dwLength)
//  用途: 分解命令状态下MODEM返回的字符串的含义
//  参数: 无
//  返回值:
//       0 分解成功
//       1 分解失败
//  备注:
// 
//
int CRCCComm::ParseAnswer(LPSTR AnswerString,DWORD dwLength)
{
	DWORD MDMStatus = MDM_UNKOWN;
	LPSTR pStr;
	char tmpStr[40];
	int i,j;
	for ( i=0; i<MDMAnswerNum; i++)
	{
		if(pStr = strstr(AnswerString,MDMAnswerStr[i]))
			break;
	}
	if ( i == MDMAnswerNum )
	{
		PostRCCMessage(RCC_STR_STATE,MDMStatus);
		return 1;
	}

	switch(i)
	{
	case 0: //"OK"
		MDMStatus = MDM_OK;
		break;
	case 1: //	"NO CARRIER"
		MDMStatus = MDM_DCD;
		break;
	case 2: //	"ERROR"
		MDMStatus = MDM_CMDERR;
		break;
	case 3: // "NO DIAL"
		MDMStatus = MDM_NOTONE;
		break;
	case 4: // "BUSY"
		MDMStatus = MDM_BUSY;
		break;
	case 5: //"NO ANSWER";
		MDMStatus = MDM_NOANSW;
		break;
	case 6: //"RING"
		MDMStatus = MDM_RING;
		break;
	case 7: //"CONNECT"
		MDMStatus = MDM_CONN;
		//继续分析以下三条语句
		pStr += strlen(MDMAnswerStr[i]);
		while(*pStr == ' ')
			pStr ++;
		j=0;
		for(j=0;*pStr != 0x0D && *pStr != 0x0A && j<30;j++)
		{
			tmpStr[j] = *pStr;
			pStr ++;
		}
		tmpStr[j]=0;
		MDMConnect = atoi(tmpStr);

		if(pStr = strstr(AnswerString,"PROTOCOL:"))
		{
			pStr += strlen("PROTOCOL:");
			while(*pStr == ' ')
				pStr ++;
			j=0;
			for(j=0;*pStr != 0x0D && *pStr != 0x0A && j<30;j++)
			{
				tmpStr[j] = *pStr;
				pStr ++;
			}
			tmpStr[j]=0;
			strcpy(MDMProtocol,tmpStr);
			MDMStatus |= MDM_PROT;
		}

		if(pStr = strstr(AnswerString,"COMPRESSION:"))
		{
			pStr += strlen("COMPRESSION:");
			while(*pStr == ' ')
				pStr ++;
			j=0;
			for(j=0;*pStr != 0x0D && *pStr != 0x0A && j<30;j++)
			{
				tmpStr[j] = *pStr;
				pStr ++;
			}
			tmpStr[j]=0;
			strcpy(MDMProtocol,tmpStr);
			MDMStatus |= MDM_COMP;
		}

		if(pStr = strstr(AnswerString,"CARRIER"))
		{
			pStr += strlen("CARRIER");
			while(*pStr == ' ')
				pStr ++;
			j=0;
			for(j=0;*pStr != 0x0D && *pStr != 0x0A && j<30;j++)
			{
				tmpStr[j] = *pStr;
				pStr ++;
			}
			tmpStr[j]=0;
			MDMCarrier = atoi(tmpStr);
			MDMStatus |= MDM_CARRIER;
		}
		break;
	case 8: //"PROTOCOL:"
		MDMStatus = MDM_PROT;
		break;
	case 9:	//"COMPRESSION:"
		MDMStatus = MDM_COMP;
		break;
	case 10: //"CARRIER"
		MDMStatus = MDM_CARRIER;
		break;
	}
	MDMResult = MDMStatus;
	PostRCCMessage(RCC_STR_STATE,MDMStatus);
	return 0;
}

//
//  函数: BOOL CRCCComm::SetCommState(LPDCB lpDCB) 
//  用途: 设置串口状态
//  参数: 
//    lpDCB 串口通讯参数结构
//  返回值:
//       TRUE 设置成功
//       FALSE 设置失败
//  备注:
// 
BOOL CRCCComm::SetCommState(LPDCB lpDCB) //设置串口状态
{
	DCB dcb;
	char dcbStr[100];
	sprintf( dcbStr, "\\\\.\\COM%d: baud=%lu parity=N data=8 stop=1",
		CommNo,BaudRate) ;

	::GetCommState( hCommFile, &dcb );
	::BuildCommDCB( dcbStr,&dcb);

	dcb.fNull = 0; //将NULL字符当普通字符传送
	dcb.fOutxCtsFlow = 1; //采用硬件流控制
	dcb.fOutxDsrFlow = 1;
	dcb.fOutX = 0;
	dcb.fInX = 0;
	dcb.fDtrControl =  DTR_CONTROL_HANDSHAKE;
	dcb.fRtsControl =  RTS_CONTROL_HANDSHAKE;

	dcb.fDsrSensitivity = 1;
	dcb.fTXContinueOnXoff = 1;
	dcb.fErrorChar = 0;
	dcb.fAbortOnError = 0;
	dcb.fDummy2 = 0;
	dcb.wReserved = 0;
	dcb.XonLim = 65535;
	dcb.XoffLim = 65535;
	dcb.XonChar = 17;
	dcb.XoffChar = 19;
	dcb.ErrorChar = 0;
	dcb.EofChar = 0;
	dcb.EvtChar = 0;
	dcb.wReserved1 = 0;

//	dcb.fOutX=0;
	return ::SetCommState( hCommFile, &dcb);
}

BOOL CRCCComm::GetCommState(LPDCB lpDCB) //得到串口的当前设置状态
{
	return ::GetCommState(hCommFile,lpDCB);
}

//在进入本函数之前,一定要将MDMResult变量设置为MDM_NONE
//等待MODEM命令串的返回,返回类似MDM_OK
int CRCCComm::WaitForCommandResult(DWORD TimeOut)
{
	int OldRCCStatus = RCCStatus;
	RCCStatus = RCC_STAT_INIT; //步入初始化状态,等待返回
	DWORD CurTickCou

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -