[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]
|