练习串口传输文件

目录

一、实验叙述 

二、通过串口传输文件

1、简单的对话

2、文件的传输

3、延伸


​​​​​​​

一、实验叙述 

将两台笔记本电脑,借助 usb转rs232 模块和杜邦线,建立起串口连接。然后用串口助手等工具软件(带文件传输功能)将一台笔记本上的一个大文件(图片、视频和压缩包软件)传输到另外一台电脑,预算文件大小、波特率和传输时间三者之间的关系,并对比实际传输时间。

这里会用到一些串口通信的知识,可以参考一下之前的博客完成一个STM32的USART串口通讯程序_afadgfansfa的博客-CSDN博客任务:完成一个STM32的USART串口通讯程序(查询方式即可,暂不要求采用中断方式),要求:1)设置波特率为115200,1位停止位,无校验位;2)STM32系统给上位机(win10)连续发送“hello windows!”。win10采用“串口助手”工具接收。想了解串口通信的参照此博客:https://blog.csdn.net/afadgfansfa/article/details/120956561?spm=1001.2014.3001.5502https://blog.csdnhttps://blog.csdn.net/afadgfansfa/article/details/121022298?spm=1001.2014.3001.5501

二、通过串口传输文件

正确连接硬件,打开串口调制工具,并且打开两次SSCOM软件,选择两个不同的串口。

ps:设置波特率等相关参数一致

1、简单的对话

通过对话框发送简单的文字,信息会通过杜邦线将信息传递回来。比如,我们通过串口6发送Hi,串口7便会接收到串口6发来的信息Hi。再通过串口7发送Hello,wolrd!,串口6会接收到串口7发送的信息。

2、文件的传输

接下来文件的传输。首先需要在SSCOM中打开文件。

然后点击发送文件,此时串口7便会接收到串口6发送的数据。 

注意需要勾选接收数据到文件,否则没有文件生成 

在SSCOM的同级目录下,将文件名更改为jpg结尾。如果在文件中查看文件时没有文件扩展名(后缀),在文件资源管理器的菜单栏点击查看将文件扩展名选项勾选上,然后再修改文件名。 

下面是对比图(左边是串口传输的文件,右边是源文件) 

3、延伸

笔者还试过不同的波特率,也遇到一些问题。当波特率过高时,误码率上升,因为根据著名的香农公式:
                                               C=B log2​ (1+NS​)

当信噪比一定时,令 x = S / N 0  ,这样上面的公式可以写成


                        C t = S n 0 B n 0 S log ⁡ 2 ( 1 + x ) 1 / x = S n 0 log ⁡ 2 ( 1 + x ) 1 / x 


又利用关系式,


                        lim ⁡ x − > 0 ln ⁡ ( 1 + x ) 1 / x = 1


                                log ⁡ 2 a = log ⁡ 2 e ⋅ ln ⁡ a

可以推出


        lim ⁡ B − > ∞ C t = lim ⁡ x − > 0 S n 0 log ⁡ 2 ( 1 + x ) 1 / x = S n 0 log ⁡ 2 e ≈ 1.44 S n 0

所以,波特率趋于无穷大时,传输速率实则趋近于恒定的值。当我使用这个软件的最大波特率2000000波特率时,传输的文件转化为图片,打开时出现了一些错误。同时,SSCOM软件根据波特率和文件大小计算出了传输时间。如果以I为传信率,S为波特率,N为每个符号承载的信息量,则
                                

                                        I = S log ⁡ 2 N

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
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表示正确 }
串口传输文件工具C是一种用于通过串行通信口(串口传输文件的工具。 在计算机系统中,串口是一种用于与外部设备进行通信的接口,常用于连接计算机与打印机、数码相机、调制解调器等设备。串口传输文件工具C就是使用串口作为传输通道,将文件从一个设备传输到另一个设备的工具。 串口传输文件工具C的原理是通过串行通信口将文件分割成一个个数据包进行传输,接收端按照一定的协议将数据包重新组装成完整的文件传输的数据包通常包括文件名、文件大小、数据内容等信息,以保证接收端能够正确地还原文件。 通过串口传输文件工具C,可以实现在没有网络连接或无法使用其他传输方式的情况下,通过串口进行文件传输。它可以用于在计算机之间传输文件,也可以用于与一些特定设备进行文件的交互。 串口传输文件工具C使用简单,只需在发送端选择要传输文件,设定串口通信参数,然后点击发送按钮即可。接收端需要打开串口接收程序,设定相同的串口通信参数,并点击接收按钮,即可等待文件传输完成。 需要注意的是,由于串口通信的速度相对较慢,传输文件可能需要较长的时间。同时,由于串口的距离限制较大,传输过程中需要确保发送端与接收端之间的串口连接稳定,避免数据丢失或错误。 总之,串口传输文件工具C是一种便捷的文件传输工具,适用于没有网络连接或无法使用其他传输方式的场景。它可以通过串口文件从一个设备传输到另一个设备,实现数据的交互和共享。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值