/*
简单文件传输--从机部分
主机部分:C# 串口基础--简单文件传输协议 namespace UartSendFile
文件:devtranfile.h
版本 FileTranVer1.0.0
时间:2013年5月23日 第一个版本 在VS2008调试OK
*****************************************************************************************/
#ifndef __DEVTRANFILE_H_
#define __DEVTRANFILE_H_
#include "\embed\source\lib\basetype.h"
//****************************************************************************************
//传输过程控制
void DevTranFileTest(void);
void DevTranFileBegin(void);
void DevTranFileEnd(void);
//接收数据处理
void DevTranFileRecvName(void);
int DevTranFileRecvData(void);
void DevTranFileRecvDataEnd(void);
void DevTranFileRecvErrDeal(void);
u8 DevTranFileRecvXor(u8 *fdata,u32 flen);
//返回应答
void DevTranFileRecvSendOK(void);
void DevTranFileRecvSendNOK(void);
void DevTranFileRecvSendReSend(void);
//****************************************************************************************
#endif
/*****************************************************************************************
简单文件传输
文件:devtranfile.c
版本 FileTranVer1.0.0
*****************************************************************************************/
#include "devtranfile.h" //#include "\embed\dev\devtranfile.h"
#include "\embed\source\lib\math1.h"
#include "\embed\vs2008_ucos\bsp\BspUart0.h"
#include "\embed\vs2008_ucos\bsp\bspm25p16.h"
/*****************************************************************************************
数据传输协议
*****************************************************************************************/
//数据包传输格式。可以有很多种类型。此处的类型是文件传输。
#define DATA_BUF_LEN 256 //固定大小
typedef struct
{
u8 Head; //固定0xAA
u8 Xor; //校验
u8 To; //目的地
u8 Type; //固定 类型:==1文件传输
union
{
//主机发送的数据格式
struct
{
//文件的第n包数据 ==0文件名 ==0xFFFFFFFF结束
u32 Filenum;
//数据,实际接收到的长度=recvlen-8
u8 Fdata[DATA_BUF_LEN];
};
//从机发送的数据格式
struct
{
//+4与上面一样长了
u8 RetData[DATA_BUF_LEN+4];
};
};
}g_pakg;
//传输过程控制
typedef struct
{
u32 IsDoing:1; //是否正在进行文件传输
u32 ForkEnd:1; //因为出错,要强制退出
u32 filedataunm; //第n包数据了
u32 recvlen; //本次收到的数据长度
g_pakg pkg;
}g_ctrl;
g_ctrl ctl;
/*****************************************************************************************
数据传输过程控制
*****************************************************************************************/
void DevTranFileTest(void)
{
int timeout = 30;
//开始
DevTranFileBegin();
while(1)
{
//强制退出
if(ctl.ForkEnd==1)
{
break;
}
//接收数据
ctl.recvlen = BspUart0Recvs(&ctl.pkg.Head,sizeof(g_pakg),1000);
if( FALSE == DevTranFileRecvXor(&ctl.pkg.Head,ctl.recvlen))
{
DevTranFileRecvErrDeal();
//30秒超时退出
if(timeout-- <0)
{
break;
}
printf("timeout:%d\n",timeout);
continue;
}
timeout = 30;
//不是文件传输
if (ctl.pkg.Type != 1)
{
return;
}
//是传输的文件名
if(ctl.pkg.Filenum==0)
{
DevTranFileRecvName();
}
//传输的是文件内容
else
{
if(DevTranFileRecvData() == 0)
{
//文件传输结束
DevTranFileRecvDataEnd();
//break;
}
}
}
//结束
DevTranFileEnd();
return;
}
/*****************************************************************************************
传输的处理函数
*****************************************************************************************/
//开始传输
void DevTranFileBegin(void)
{
if(BspUart0Init()==FALSE)
{}
//设置标志位
ctl.filedataunm = 0;
ctl.ForkEnd = 0;
ctl.IsDoing = 1;
}
//结束
void DevTranFileEnd(void)
{
if (ctl.IsDoing==0)
{
return;
}
ctl.IsDoing = 0;
ctl.ForkEnd = 0;
BspUart0Close();
}
//处理接收错误
void DevTranFileRecvErrDeal(void)
{
//ctl.ForkEnd = 1;
}
/*****************************************************************************************
接收到主机数据的处理
所有的应答都归位以下几种
*****************************************************************************************/
//接收到文件名
void DevTranFileRecvName(void)
{
u32 len;
if (ctl.IsDoing==0)
{
return;
}
len = ctl.recvlen - 8; //得到文件名长度
ctl.pkg.Fdata; //文件名指针
//------------添加处理代码-----------------------------
//------------添加处理代码END--------------------------
ctl.filedataunm = 0;
printf("recv name\n");
DevTranFileRecvSendOK();
}
//处理接收到的数据
int DevTranFileRecvData(void)
{
u32 len;
u32 fdatacnt;
if (ctl.IsDoing==0)
{
return 0;
}
len = ctl.pkg.Filenum;
//文件传输结束
if(len == 0xffffffff)
{
return 0;
}
//得到第n包数据
fdatacnt = ctl.pkg.Filenum;
//包顺序不对,则要求重新传输
if (ctl.filedataunm + 1 != fdatacnt)
{
DevTranFileRecvSendReSend();
DevTranFileRecvErrDeal();
return 1;
}
ctl.filedataunm++;
len = ctl.recvlen - 8; //数据长度
ctl.pkg.Fdata; //文件数据指针
//------------添加处理代码-----------------------------
BspM25P16PageWrites256(ctl.pkg.Fdata,(ctl.filedataunm-1));
//------------添加处理代码END--------------------------
printf("recv data %d\n",ctl.pkg.Filenum);
DevTranFileRecvSendOK();
return 1;
}
//接收到结束符号
void DevTranFileRecvDataEnd(void)
{
//------------添加处理代码-----------------------------
//------------添加处理代码END--------------------------
printf("recv end");
DevTranFileRecvSendOK();
}
/*****************************************************************************************
应答主机
所有的应答都归位以下几种
*****************************************************************************************/
//向主机返回接收数据ok
void DevTranFileRecvSendOK(void)
{
ctl.pkg.Head = 0XAA;
ctl.pkg.Xor = 0xff;
ctl.pkg.To = 0x00;
ctl.pkg.Type = 1; //表明是文件传输
ctl.pkg.RetData[0] = 0xAA; //ok
ctl.pkg.Xor = MathXor(&ctl.pkg.Xor+1,3);
BspUart0Sends(&ctl.pkg.Head,5);
}
//向主机返回接收数据no ok
void DevTranFileRecvSendNOK(void)
{
ctl.pkg.Head = 0XAA;
ctl.pkg.Xor = 0xff;
ctl.pkg.To = 0x00;
ctl.pkg.Type = 1; //表明是文件传输
ctl.pkg.RetData[0] = 0x55; //主机将停止传输
ctl.pkg.Xor = MathXor(&ctl.pkg.Xor+1,3);
BspUart0Sends(&ctl.pkg.Head,5);
}
//向主机返回请求重新发送数据
void DevTranFileRecvSendReSend(void)
{
ctl.pkg.Head = 0XAA;
ctl.pkg.Xor = 0xff;
ctl.pkg.To = 0x00;
ctl.pkg.Type = 1; //表明是文件传输
ctl.pkg.RetData[0] = 0xA5; //no ok
ctl.pkg.Xor = MathXor(&ctl.pkg.Xor+1,3);
BspUart0Sends(&ctl.pkg.Head,5);
}
/*****************************************************************************************
对接收到的数据进行校验
针对本处的特点:从fdata[2]开始校验,flen 是指整个数据包的长度
*****************************************************************************************/
u8 DevTranFileRecvXor(u8 *fdata,u32 flen)
{
u8 xor;
if (fdata[0] != 0xAA)
{
return FALSE;
}
if (flen < 4)
{
return FALSE;
}
xor = MathXor((fdata+2),flen-2);
if(xor != *(fdata+1))
{
return FALSE;
}
return TRUE;
}