file-type

串口通信协议实现大文件传输

ZIP文件

3星 · 超过75%的资源 | 下载需积分: 11 | 7.55MB | 更新于2025-05-02 | 15 浏览量 | 20 下载量 举报 1 收藏
download 立即下载
根据提供的文件内容和标签,可以看出这是一个与串口通信相关的编程头文件,主要用于大文件的发送。文件中定义了一些宏、枚举、结构体以及一个校验和计算函数。接下来,我将详细解析这些内容,并围绕串口通信、大文件传输和数据帧结构展开讨论。 ### 串口通信基础 串口通信是一种常用的设备间通信方式,它通过串行接口传输数据。在早期的计算机和嵌入式设备中,串口通信非常普遍,它支持全双工通信,并且可以进行点对点的通信。由于成本低廉且实现简单,串口至今仍被广泛应用于工业控制、嵌入式系统和一些特定的数据采集任务中。 ### 大文件传输策略 在串口通信中发送大文件时,为了保证传输的可靠性和效率,通常需要对大文件进行分块处理。文件被分成多个数据块,每个数据块都有特定的大小(在本文件中定义为`FILEDATA_LEN`),这样可以有效地管理内存使用,同时减少因错误导致的重传代价。文件的传输过程可能包括以下几个步骤: 1. 文件信息的发送:在传输文件数据之前,先发送包含文件名称和文件大小的文件信息。 2. 文件数据块的发送:将文件分成多个块,每块包含一定量的数据,按照一定顺序发送。 3. 文件传输结束的确认:发送文件结束命令,以表明所有数据块都已传输完毕。 ### 数据帧结构 为了保证数据的完整性和准确性,本文件中定义了多个结构体来封装不同类型的消息。这些结构体均包含一个`CMDHEADER`帧头,该帧头定义了消息的同步字、命令类型、命令状态和包长度。 - `FILEINFO`:用于封装文件信息,包括文件名称和长度。 - `FILEDATA`:用于封装文件数据块。 - `FILEEOF`:用于表示文件发送结束。 - `ADDATA`:用于封装通道数据,这可能与特定的设备通信协议有关。 每个结构体都定义了相应的数据字段,并且所有结构体的包长度都是可计算的,这有助于接收方进行数据包的解析和验证。 ### 校验和计算 文件中提供了一个`CheckSum`函数,用于计算给定数据缓冲区的校验和。校验和的计算方式是累加缓冲区内的每个字节,然后返回累加和。这种简单的校验和通常用于错误检测,但它的错误检测能力有限,对于更可靠的数据传输,可能需要更复杂的校验算法。 ### 关键点总结 - `SERIALPORT_BUFF_LEN` 定义了串口缓冲区的大小,这里为100KB。 - `FILEDATA_LEN` 定义了文件数据块的长度,这里为2KB。 - `CMDTYPE` 和 `CMDSTATE` 枚举分别定义了消息类型和状态。 - `CMDHEADER` 是所有通信消息的共同头部,用于标识消息的同步字、类型、状态和长度。 - `CheckSum` 函数用于计算数据缓冲区的校验和,以确保数据在传输过程中未被篡改或损坏。 ### 实际应用场景 在实际应用中,此类编程头文件通常会被嵌入到一个更大的项目中,用于处理串口数据的接收和发送。开发人员需要根据这个头文件中定义的数据帧格式和协议,实现串口的初始化、数据的发送和接收、帧的解析和校验、以及错误处理等。在大文件发送时,还需要考虑文件的分片、发送顺序、异常处理和确认机制等。 综合来看,该文件涉及了串口通信、数据帧设计、校验和算法等多个方面的知识,是嵌入式系统编程和通信协议设计的典型实例。

相关推荐

filetype
LONG CSCOMMDlg::OnCommunication(WPARAM ch, LPARAM port) { g_ucRecvBuf[g_ulRecvLen++]=UCHAR(ch); if(g_ulRecvLen>=51) { memcpy(&g_ADData,g_ucRecvBuf,51); //return 1; } // return 1; if(g_ulRecvLen<4) return 1; //1表示接收数据长度不够 ULONG ulCheckSum =0; CMDHEADER header; header = *((CMDHEADER *)g_ucRecvBuf); //如果不相等,将Buffer中的每个数据前移动一个位置 if(CMD_SYN_WORD!= header.ulSyncWord) { memmove(g_ucRecvBuf,g_ucRecvBuf+1,3); return 2;//2表示没有接收到同步字 } if(g_ulRecvLen<sizeof(CMDHEADER)) return 3; //3表示没有接收到帧头 CString strTemp; CString strFileName; char szFilePath[MAX_PATH]={0}; switch(header.cmdType) { case CMD_FILEINFO://文件信息(包括名称,大小)命令 if(g_ulRecvLen<header.ulPackLen) return 4; //没有收到完整的文件信息命令 if(g_ulRecvLen==(sizeof(CMDHEADER)+header.ulPackLen)) { FILEINFO fileInfo; fileInfo=*((FILEINFO *)g_ucRecvBuf); ulCheckSum = CheckSum(fileInfo.ucFileName,fileInfo.ulFileNameLen) +fileInfo.lFileLen; if(ulCheckSum!=fileInfo.ulCheckSum) { fileInfo.header.cmdState = CMD_STATE_ERROR; g_lErrorPackNum++; //strTemp.Format("%d",g_lErrorPackNum); } else { fileInfo.header.cmdState = CMD_STATE_OK; //增加接收文件的计时功能 memset(&g_tRecvBegin,0,sizeof(time_t)); time(&g_tRecvBegin); m_bRecvFileIsBegin = TRUE; } m_nCurFileRecvLen=0; m_nFileRecvLen = fileInfo.lFileLen; //文件长度 fileInfo.header.cmdType =CMD_FILEINFO_RESP; m_Port.WriteToPort((char*)&fileInfo.header,sizeof(CMDHEADER)); memcpy(szFilePath,fileInfo.ucFileName,fileInfo.ulFileNameLen); strFileName.Format("%s",szFilePath); m_strCurFilePath= m_strSaveFileDir+strFileName; if(NULL!=g_file.m_hFile) g_file.Close(); g_file.Open(m_strCurFilePath,CFile::modeCreate|CFile::modeReadWrite); TRACE("1,RECV FILEINFO CMD,File Name = %s,g_ulRecvLen = %d\n", fileInfo.ucFileName,g_ulRecvLen); // if(m_nFileRecvLen1024*1024) // { // strTemp.Format("%0.3fKB",m_nFileRecvLen/1024.0/1024.0); // } // //显示"传输总耗时" // const ULONG ulFrameBytes = g_nBaud/10 -(sizeof(CMDHEADER)+4); // long lComm_TimeSum = m_nFileRecvLen/ulFrameBytes; // //传输总耗时间,单位:秒 // // WORD wHour =0; // WORD wMinute =0; // WORD wSecond =0; // // wSecond = lComm_TimeSum%60; // wMinute = lComm_TimeSum/60%60; // wHour = lComm_TimeSum/60/60%60; // // if((0==wSecond)&&(0==wMinute)&&(0==wHour)) // wSecond =1; // strTemp.Format("%02d:%02d:%02d",wHour,wMinute,wSecond); g_ulRecvLen =0; } break; case CMD_FILEDATA: //发送文件中数据的命令 if(g_ulRecvLen<header.ulPackLen) return 5;//没有收到完整的文件数据帧命令 if(g_ulRecvLen == (sizeof(CMDHEADER)+header.ulPackLen)) { FILEDATA fileData; fileData = *((FILEDATA *)g_ucRecvBuf); fileData.pucBuf = new UCHAR[fileData.header.ulPackLen-4]; memset(fileData.pucBuf,0,fileData.header.ulPackLen-4); memcpy(fileData.pucBuf,g_ucRecvBuf+sizeof(CMDHEADER)+4,fileData.header.ulPackLen-4); ulCheckSum=CheckSum(fileData.pucBuf, fileData.header.ulPackLen-4); if(ulCheckSum!= fileData.ulCheckSum) { fileData.header.cmdState =CMD_STATE_ERROR; g_lErrorPackNum++; strTemp.Format("%d",g_lErrorPackNum); //m_editErrorFrames } else fileData.header.cmdState =CMD_STATE_OK; fileData.header.cmdType = CMD_FILEDATA_RESP; g_file.Write(fileData.pucBuf,fileData.header.ulPackLen-4); //fileData.header.ulPackLen-4, DELETE_ARRAYOBJS(fileData.pucBuf); g_ulRecvLen=0; m_Port.WriteToPort((char*)&fileData.header,sizeof(CMDHEADER)); m_nCurFileRecvLen+=fileData.header.ulPackLen-4; strTemp.Format("%0.2f",(float)m_nCurFileRecvLen/(float)m_nFileRecvLen*100); strTemp+=_T("%"); float step = (float)m_nCurFileRecvLen/(float)m_nFileRecvLen*100; // m_progress.SetPos((int)step); /*if(m_nFileRecvLen1024*1024) { strTemp.Format("%0.3fKB",m_nFileRecvLen/1024.0/1024.0); }*/ } break; case CMD_FILEEOF://文件发送结束命令 if(g_ulRecvLen<header.ulPackLen) return 6;//没有发到完整的文件发送结束命令 if(g_ulRecvLen == (sizeof(CMDHEADER)+header.ulPackLen)) { FILEEOF fileEOF; fileEOF= *((FILEEOF *)g_ucRecvBuf); fileEOF.pucBuf = new UCHAR[fileEOF.header.ulPackLen-4]; memset(fileEOF.pucBuf,0,fileEOF.header.ulPackLen-4); memcpy(fileEOF.pucBuf,g_ucRecvBuf+sizeof(CMDHEADER)+4,fileEOF.header.ulPackLen-4); ulCheckSum = CheckSum(fileEOF.pucBuf,fileEOF.header.ulPackLen-4); if(ulCheckSum!=fileEOF.ulCheckSum) { fileEOF.header.cmdState=CMD_STATE_ERROR; g_lErrorPackNum++; strTemp.Format("%d",g_lErrorPackNum); } else { fileEOF.header.cmdState =CMD_STATE_OK; m_bRecvFileIsBegin = FALSE;//接收文件完成,停止显示时间 } fileEOF.header.cmdType =CMD_FILEEOF_RESP; g_file.Write(fileEOF.pucBuf,fileEOF.header.ulPackLen-4); g_file.Close(); //解决大文件发送时,第二个文件打开错误原因是没“置0”原因 g_file.m_hFile=NULL; DELETE_ARRAYOBJS(fileEOF.pucBuf); g_ulRecvLen=0; m_Port.WriteToPort((char*)&fileEOF.header,sizeof(CMDHEADER)); m_nCurFileRecvLen += fileEOF.header.ulPackLen-4; if(m_nFileRecvLen<=0) { strTemp=_T("0%"); } else { strTemp.Format("%0.2f", (float)m_nCurFileRecvLen/(float)m_nFileRecvLen*100); strTemp+=_T("%"); } if(m_nFileRecvLen1024*1024) { strTemp.Format("%0.3fKB",m_nFileRecvLen/1024.0/1024.0); } } break; //=================处理接收端的响应信息 begin 信息头================= case CMD_FILEINFO_RESP://发送文件信息命令后,发到接收端的响应信息 if(CMD_STATE_OK==header.cmdState) { m_bFileInfoIsOK = TRUE; g_ulRecvLen = 0; g_bIsRecvData = TRUE; } else if(CMD_STATE_ERROR==header.cmdState) { m_bFileInfoIsOK = FALSE; g_ulRecvLen=0; SendFileInfo(); } break; //=================处理接收端的响应信息 文件数据================= case CMD_FILEDATA_RESP://发送文件体命令后,发到接收端的响应信息 if(CMD_STATE_OK==header.cmdState) m_bFileDataIsOK = TRUE; else if(CMD_STATE_ERROR==header.cmdState) m_bFileDataIsOK = FALSE; g_ulRecvLen =0; g_bIsRecvData = TRUE; break; //=================处理接收端的响应信息 文件结尾================= case CMD_FILEEOF_RESP://发送文件尾命令后,发到接收端的响应信息 if(CMD_STATE_OK==header.cmdState) { m_bFileEOFIsOK = TRUE; g_bFileSendEnd = TRUE; } else if (CMD_STATE_ERROR == header.cmdState) { m_bFileEOFIsOK = FALSE; m_bSendFileIsBegin = FALSE; } g_ulRecvLen = 0; g_bIsRecvData = TRUE; break; //====================默认处理================= default:break; } //设置信号量 SetEvent(m_hRecvMsgEvent); return 0; //返回0表示正确 }
wjh627641217
  • 粉丝: 1
上传资源 快速赚钱