OpenEdv-开源电子网

 找回密码
 立即注册
正点原子全套STM32/Linux/FPGA开发资料,上千讲STM32视频教程免费下载...
查看: 7137|回复: 9

Ymodem协议+MicroSD卡+文件系统(R0.07C)--传输rar文件出现问题了

[复制链接]

6

主题

48

帖子

0

精华

初级会员

Rank: 2

积分
96
金钱
96
注册时间
2013-11-18
在线时间
3 小时
发表于 2014-11-22 19:33:39 | 显示全部楼层 |阅读模式
5金钱
[mw_shl_code=c,true]打算通过串口的Ymodem协议将文件发送到STM32F103单片机上,单片机再把收到的文件存到SD卡上。[/mw_shl_code] [mw_shl_code=c,true]目前成功接收了一个24kb的txt文件,30kb的jpg文件。但是还是有问题,请往下看。不知道怎么把图片和代码一起上传,见谅啊呵呵[/mw_shl_code] [mw_shl_code=c,true]/* * * ymodem.c * * Created on: 2014年11月22日 * Author: jianghs * Version: v1.0 * Description: Ymodem传输与存储。 */ #include "includes.h" FIL fsrc; // file objects INT32U filebw; //File R/W count //串口发送缓存区 INT8U USART2_TX_BUF[USART2_MAX_SEND_LEN]; //发送缓冲,最大USART2_MAX_SEND_LEN=20字节 INT8U USART2_RX_BUF[USART2_MAX_RECV_LEN]; //发送缓冲,最大USART2_MAX_SEND_LEN=1024字节 volatile INT16U USART2_RECV_LEN=0; INT8U MODEM_PACK=0; // 帧类型标识 INT16U MODEM_CRC=0;      // 收到的CRC16校验 INT8U MODEM_CURP=0; // 数据包序号 INT8U MODEM_CURB=0; // 数据包序号补码 INT8U MODEM_CURN=0; // 下一帧数据包的序号 INT8U MODEM_DLEN=0; INT32U MODEM_FST=0; // 帧计数器 INT8U MODEM_DATA[1024]={0,}; // data buffer INT16U MODEM_DATA_LEN; // data buffer数据包长度(去掉0x1A后的有效数据个数) INT32U MODEM_FLEN=0; // File length field for Ymodem char MODEM_FNAME[FILE_NAMELEN]; // File name field for Ymodem //******************************************************************************************************** //* 函 数 名 : void COMInit(void) 串口2初始化,中断接收,DMA发送 //**------------------------------------------------------------------------------------------------------ //* 描 述 : 串口2 配置函数 //* Parameter: 无。 //* Return: 无。 //*************************************************************************************************** //******************************************************************************************************** //* 函 数 名 : void Ymodem_Loop(void) //**------------------------------------------------------------------------------------------------------ //* 描 述 : 串口数据校验处理,与文件储存 //* Parameter: 无 //* Return: 无 //******************************************************************************************************** void Ymodem_Loop(void) { INT8U ch=0; INT8U err=0; INT8U cannum=0; INT8U retries=0; INT16U check; INT32S i=0; // FRESULT res; while(1) { if(MODEM_FST==0) //没有接收的数据时,帧计数器为0,此时发送C,请求上位机数据 { ch = MODEM_C; uart_send(&ch, 1); //发送数据请求字符 } err=uart_read(MODEM_DATA,500); //500ms 之内不返回数据,返回ERROR。 if(err!=0) //得到正确的应答 { MODEM_FST++; //帧计数器++ switch(MODEM_PACK) { case MODEM_SOH: //包长度为128 check=CRC_16(MODEM_DATA,128); //CRC校验 if(check!=MODEM_CRC) //错误处理 { retries++; //错误计数 ch = MODEM_NAK; uart_send(&ch, 1); //校验错误,请求重传 //printf("CRC\r\n"); break; } if(MODEM_CURP ==MODEM_CURN && MODEM_CURP==(0xFF-MODEM_CURB)) //校验补码是否正确,包顺序是否出错 { if(MODEM_CURP<0xFF) { MODEM_CURN = MODEM_CURP+1; } else { MODEM_CURN = 0; } MODEM_DATA_LEN=128; //取有效数据位长度 for(i=127;i>=0;i--) //去掉数组末端填的0x1A { if(MODEM_DATA==0x1A) { MODEM_DATA=0; MODEM_DATA_LEN=i; }else { break; } } } else { retries++; //错误计数 ch = MODEM_NAK; uart_send(&ch, 1); //包顺序出错,请求重传。 //printf("SCN\r\n"); break; } if(MODEM_CURP == 0x00 && MODEM_CURB == 0xFF && MODEM_FST == 1 ) //是否第0个数据包 { for(i=0; MODEM_DATA!=0x00 && i<FILE_NAMELEN;) //获取文件名 { MODEM_FNAME[i+3]=MODEM_DATA; i++; } MODEM_FNAME[i+3]=0; //文件名末尾补零 MODEM_FNAME[0]=0x30; //存0:/根目录下 MODEM_FNAME[1]=0x3A; MODEM_FNAME[2]=0x2F; //文件长度,占不处理 MODEM_CURN=0x01; //下一帧数据包序号为1 CreateFile(&fsrc,MODEM_FNAME); //创建文件 } retries=0; if(MODEM_FST>1) //帧大于1则是数据包 { File_SaveToMemory(&fsrc,MODEM_DATA,MODEM_DATA_LEN,&filebw); //写入文件,下面 } /* printf("\r\n datelen:= %d",MODEM_DATA_LEN); for(i=0;i<128;i++) { while (!(USART1->SR & USART_FLAG_TXE)); USART1->DR = MODEM_DATA; }*/ ch = MODEM_ACK; uart_send(&ch, 1); //接收信息确认! break; case MODEM_STX: //包长度为1024 check=CRC_16(MODEM_DATA,1024); //CRC校验 if(check!=MODEM_CRC) //错误处理 { retries++; //错误计数 ch = MODEM_NAK; uart_send(&ch, 1); //校验错误重发 //printf("CRC\r\n"); break; } if(MODEM_CURP ==MODEM_CURN && MODEM_CURP==(0xFF-MODEM_CURB)) //校验补码是否正确,包顺序是否出错 { if(MODEM_CURP<0xFF) { MODEM_CURN = MODEM_CURP+1; } else { MODEM_CURN = 0; } MODEM_DATA_LEN=1024; for(i=1023;i>=0;i--) //去掉数组末端填的0x1A { if(MODEM_DATA==0x1A) { MODEM_DATA=0; MODEM_DATA_LEN=i; }else { break; } } }else { retries++; //错误计数 ch = MODEM_NAK; uart_send(&ch, 1); //包顺序出错,重发。 //printf("SCN\r\n"); break; } if(MODEM_CURP == 0x00 && MODEM_CURB == 0xFF && MODEM_FST == 1 ) //是否第0个数据包 { for(i=0; MODEM_DATA!=0x00 && i<FILE_NAMELEN;) { MODEM_FNAME[i+3]=MODEM_DATA; i++; } MODEM_FNAME[i+3]=0; //补零。 MODEM_FNAME[0]=0x30; MODEM_FNAME[1]=0x3A; MODEM_FNAME[2]=0x2F; MODEM_CURN=0x01; CreateFile(&fsrc,MODEM_FNAME); //创建文件 } retries=0; if(MODEM_FST>1) //数据包 { File_SaveToMemory(&fsrc,MODEM_DATA,MODEM_DATA_LEN,&filebw); } ch = MODEM_ACK; uart_send(&ch, 1); //接收信息确认! break; case MODEM_ETX: //文件传输结束 //printf("ETX\r\n"); break; case MODEM_EOT: ch = MODEM_ACK; uart_send(&ch, 1); OSSemPend(Data_SIM,100,&err); //等待串口2接收完一帧数据 ch = MODEM_ACK; uart_send(&ch, 1); OSSemPend(Data_SIM,100,&err); //等待串口2接收完一帧数据 f_close(&fsrc); //关闭文件 //printf("EOT\r\n"); MODEM_FST=0; //帧计数清零,从新开始等待文件传输。 MODEM_PACK=0; //寄存器清零 MODEM_CRC=0; MODEM_CURP=0; MODEM_CURB=0; MODEM_CURN=0; MODEM_DLEN=0; MODEM_FLEN=0; break; case MODEM_CAN: //取消传输 //printf("CAN\r\n"); cannum++; if(cannum>MODEM_CAN_COUNT) { f_close(&fsrc); //关闭文件 MODEM_FST=0; //帧计数清零,从新开始等待文件传输。 MODEM_PACK=0; //寄存器清零 MODEM_CRC=0; MODEM_CURP=0; MODEM_CURB=0; MODEM_CURN=0; MODEM_DLEN=0; MODEM_FLEN=0; } break; default: //printf("deft\r\n"); break; } } else { if(MODEM_FST) //如果帧计数器大于0 { if(retries==0) { //printf("ACK\r\n"); ch = MODEM_ACK; uart_send(&ch, 1); //接收信息确认! } retries++; //错误计数++; if(retries<MODEM_MAX_RETRIES) { ch = MODEM_NAK; uart_send(&ch, 1); //请求重传。 //printf("NUM\r\n"); } else { MODEM_PACK=0; //寄存器清零 MODEM_CRC=0; MODEM_CURP=0; MODEM_CURB=0; MODEM_CURN=0; MODEM_DLEN=0; MODEM_FST=0; MODEM_FLEN=0; retries=0; for(i=0;i<1024;i++) { MODEM_DATA=0; } } } LED2_Blink; } } } [/mw_shl_code] [mw_shl_code=c,true][/mw_shl_code]

最佳答案

查看完整内容[请看2#楼]

回复【7楼】w0rmis20: --------------------------------- 是啊,谢谢您。通过您的指点,我发现问题了。ymodem协议中当最后一帧数据包不足时在后面补充0x1A。我程序里面默认吧数据包结尾中的这个0x1A给去掉了,但是这个被发送文件里数据也存在0x1A,所以出错了。
正点原子逻辑分析仪DL16劲爆上市
回复

使用道具 举报

6

主题

48

帖子

0

精华

初级会员

Rank: 2

积分
96
金钱
96
注册时间
2013-11-18
在线时间
3 小时
 楼主| 发表于 2014-11-22 19:33:40 | 显示全部楼层
回复【7楼】w0rmis20:
---------------------------------
是啊,谢谢您。通过您的指点,我发现问题了。ymodem协议中当最后一帧数据包不足时在后面补充0x1A。我程序里面默认吧数据包结尾中的这个0x1A给去掉了,但是这个被发送文件里数据也存在0x1A,所以出错了。
回复

使用道具 举报

6

主题

48

帖子

0

精华

初级会员

Rank: 2

积分
96
金钱
96
注册时间
2013-11-18
在线时间
3 小时
 楼主| 发表于 2014-11-22 19:33:40 | 显示全部楼层
百度上找的
5.数据包说明
    对于标准Xmodem协议来说,如果传送的文件不是128的整数倍,那么最后一个数据包的有效内容肯定小于帧长,不足的部分需要用CTRL- Z(0x1A)来填充。这里可能有人会问,如果我传送的是bootloader工程生成的.bin文件,mcu收到后遇到0x1A字符会怎么处理?其实如 果传送的是文本文件,那么接收方对于接收的内容是很容易识别的,因为CTRL-Z不是前128个ascii码,不是通用可见字符,如果是二进制文件,mcu其实也不会把它当作代码来执行。哪怕是excel文件等,由于其内部会有些结构表示各个字段长度等,所以不会读取多余的填充字符。否则 Xmodem太弱了。对于1k-Xmodem,同上理。
回复

使用道具 举报

6

主题

48

帖子

0

精华

初级会员

Rank: 2

积分
96
金钱
96
注册时间
2013-11-18
在线时间
3 小时
 楼主| 发表于 2014-11-22 19:34:30 | 显示全部楼层
[mw_shl_code=c,true]
[mw_shl_code=c,true]/============================================================= // ----Function: CreateFile() // ------Syntax: FRESULT CreateFile(FIL *fp,char *name) // ---- 创建新文件 //============================================================= FRESULT CreateFile(FIL *fp,char *name) { FRESULT res; // FatFs function common result code res = f_open(fp,name,FA_CREATE_ALWAYS | FA_WRITE); return(res); } //=========================================================================== //============================================================= // ----Function: File_SaveToMemory() //============================================================= FRESULT File_SaveToMemory(FIL *fp, INT8U *buff,INT32U btw,INT32U *brw) { FRESULT res; // FatFs function common result code INT16S len=0; len=0; if(btw>512)//写入大于512会出错,因此将1024字节数据分为两部分储存 { len=btw-512;//剩余长度为len,没有错误处理 res = f_write(fp, buff, 512, brw); //将缓冲区的数据写到文件中 res = f_write(fp,(buff+512), len, brw); //将缓冲区的数据写到文件中 } else { res = f_write(fp, buff, btw, brw); //将缓冲区的数据写到文件中 } return(res); } Ymodem协议+MicroSD卡+文件系统(R0.07C)--成功传输txt和jpg文件,但是传输rar文件出现问题了,请大神指点 [/mw_shl_code]

[/mw_shl_code]
回复

使用道具 举报

6

主题

48

帖子

0

精华

初级会员

Rank: 2

积分
96
金钱
96
注册时间
2013-11-18
在线时间
3 小时
 楼主| 发表于 2014-11-22 19:37:01 | 显示全部楼层


后来我又发送了一个3.4Mb左右rar的压缩文件,数据传输过程也没提示错误,但是收到的压缩文件后,解压缩居然少了两个文件夹!?,其中APP、HAL中的文件是正确且完整的,但是Projects文件夹里的文件也少了很多,请大神分析一下,不知道是哪出的错??

回复

使用道具 举报

6

主题

123

帖子

1

精华

金牌会员

Rank: 6Rank: 6

积分
1281
金钱
1281
注册时间
2012-5-27
在线时间
200 小时
发表于 2014-11-22 21:45:42 | 显示全部楼层
怎么感觉着是在电脑的USB口被封的情况下 为了通过串口来获得电脑内部的文件 ???
回复

使用道具 举报

4

主题

200

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
236
金钱
236
注册时间
2012-12-19
在线时间
0 小时
发表于 2014-11-22 22:54:41 | 显示全部楼层
没有log很难分分析啊
目前在玩STM32,BBB,RPi
回复

使用道具 举报

6

主题

48

帖子

0

精华

初级会员

Rank: 2

积分
96
金钱
96
注册时间
2013-11-18
在线时间
3 小时
 楼主| 发表于 2014-11-23 09:58:27 | 显示全部楼层
回复【5楼】w0rmis20:
---------------------------------

需要什么log?
回复

使用道具 举报

4

主题

200

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
236
金钱
236
注册时间
2012-12-19
在线时间
0 小时
发表于 2014-11-24 08:32:49 | 显示全部楼层
在程序里把收到的收据打印到串口,然后保存为文件,和用utraedit打开的原始rar进行对比。
目前在玩STM32,BBB,RPi
回复

使用道具 举报

17

主题

111

帖子

0

精华

中级会员

Rank: 3Rank: 3

积分
252
金钱
252
注册时间
2012-11-3
在线时间
30 小时
发表于 2015-1-3 21:08:22 | 显示全部楼层
赞!可以共享工程源码不?
老夫驾鹤,有事烧纸!
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则



关闭

原子哥极力推荐上一条 /2 下一条

正点原子公众号

QQ|手机版|OpenEdv-开源电子网 ( 粤ICP备12000418号-1 )

GMT+8, 2025-6-27 12:32

Powered by OpenEdv-开源电子网

© 2001-2030 OpenEdv-开源电子网

快速回复 返回顶部 返回列表