📄 download.c
字号:
#include <reg52.h>
//#include "upsd3300.h"
//#include "PSD_Register.h"
#include "ext_var.h"
#include "SerialPort.h"
#include "w29c040drv.h"
#include "download.h"
#include <stdio.h>
#include <string.h>
//串口接收结构
typedef struct
{
uchar Finish; //设定未接收完毕
uint Len; //已接收长度
uint CmdLen; //命令总长度
uchar Buffer[128+1]; //接收缓冲区
uchar Data[PAGE_SIZE+1]; //页数据
int DataLen; //页数据长度
}RS232_REC;
//文件信息结构
typedef struct
{
uint Pages; //总共要写页数
uint Addr; //写入起始地址
}FILE;
static RS232_REC Rec; //串口接收
static FILE File; //文件信息
/**********************************************************************
* 函 数 名: InitRec
* 功能描述: 初始化接收相关变量
* 函数说明:
* 调用函数:
* 全局变量:
* 输 入: 无
* 返 回: 无
* 设 计 者: wangyong 日期:2007-03-24
* 修 改 者: wangyong 日期:2007-03-30
* 版 本: WTFISCAL04 KEYBOARDV1.0D100
**********************************************************************/
void InitRec( void )
{
Rec.Finish=FALSE; //设定未接收完毕
Rec.Len=0; //已接收长度
Rec.CmdLen=0; //PC发给下位机的命令的总长度
Rec.DataLen=0; //页数据长度
}
/**********************************************************************
* 函 数 名: SendCmdStr
* 功能描述: 向PC发送命令字串
* 函数说明:
* 调用函数:
* 全局变量:
* 输 入: Cmd--命令字串
Len--命令字串长度
* 返 回: 无
* 设 计 者: wangyong 日期:2007-03-25
* 修 改 者: wangyong 日期:2007-03-30
* 版 本: WTFISCAL04 KEYBOARDV1.0D100
**********************************************************************/
void SendCmdStr(uchar *Cmd,uint Len)
{
uchar CS;
uchar cmdstr[20];
uint i;
uint cmdlen;
//命令头
cmdstr[0]=0x55;
cmdstr[1]=0xAA;
//LH + LL + /LH + /LL + CMD + DATA + CS相加的长度(除命令头外)
cmdlen=5+Len;
//长度
cmdstr[2]=cmdlen/256;
cmdstr[3]=cmdlen%256;
//长度取反
cmdstr[4]=~cmdstr[2];
cmdstr[5]=~cmdstr[3];
//保存命令字
//cmdstr[6]=Cmd;
memcpy(cmdstr+6,Cmd,Len);
//计算出抑或校验和CS
//cmdlen+1为完整命令长度减去CS长度(1字节)
CS=cmdstr[0];
for(i=1;i<cmdlen+1;i++)
{
CS=CS^cmdstr[i];
}
cmdstr[6+Len]=CS;
//串口发送命令
//cmdlen+2为完整命令长度
for(i=0;i<cmdlen+2;i++)
{
SerialPort_send(cmdstr[i]);
}
}
/**********************************************************************
* 函 数 名: VerifyCmdStr
* 功能描述: 验证命令串合法性并解析出命令字,数据,数据长度
* 函数说明:
* 调用函数: 无
* 全局变量:
* 输 入: *Cmd--命令字
*DataLen--数据长度
* 返 回: TRUE--通过合法性
FALSE--未通过合法性
* 设 计 者: wangyong 日期:2007-03-25
* 修 改 者: wangyong 日期:2007-03-25
* 版 本:
**********************************************************************/
bool VerifyCmdStr(uchar *Cmd,uint *DataLen)
{
uchar CS;
uint i;
//命令头错误
if(Rec.Buffer[0]!=0x55 || Rec.Buffer[1]!=0xaa) return FALSE;
//判断cs是否正确
CS=Rec.Buffer[0];
//计算异或和
for(i=1;i<Rec.Len-1;i++)
{
CS=CS^Rec.Buffer[i];
}
//校验位出错
if(CS!=Rec.Buffer[Rec.Len-1]) return FALSE;
//得到命令字
*Cmd=Rec.Buffer[6];
//数据长度
*DataLen=(Rec.Buffer[2]*256+Rec.Buffer[3])-5;
return TRUE;
}
/**********************************************************************
* 函 数 名: Download
* 功能描述: 下载处理
* 函数说明:
* 调用函数: 无
* 全局变量:
* 输 入: 无
* 返 回: 无
* 设 计 者: wangyong 日期:2007-03-24
* 修 改 者: wangyong 日期:2007-03-24
* 版 本:
**********************************************************************/
void Download( void )
{
uchar Cmd; //命令字
uint DataLen; //数据长度
uint TempLen;
bool CommOk; //命令通讯状态
//uint i;
//串口初始化
SerialPort_init();
restart:
//初始化串口接收结构体
InitRec();
//通讯状态
CommOk=FALSE;
while(1)
{
//命令接收完毕
if(Rec.Finish)
{
//验证命令合法性
if(!VerifyCmdStr(&Cmd,&DataLen))
{
Cmd=0x0f;
SendCmdStr(&Cmd,1);
goto restart;
}
//通讯状态
CommOk=FALSE;
//解析命令
switch(Cmd)
{
case 0x5a: //握手通讯
//返回握手成功的命令
SendCmdStr(&Cmd,1);
CommOk=TRUE;
break;
case 0x04: //发送文件页数
//文件页数
File.Pages=Rec.Buffer[7]*256+Rec.Buffer[8];
SendCmdStr(&Cmd,1);
CommOk=TRUE;
break;
case 0x05: //发送起始地址
//写入的起始地址
File.Addr=Rec.Buffer[7]*256+Rec.Buffer[8];
//返回OK
SendCmdStr(&Cmd,1);
CommOk=TRUE;
break;
case 0x06: //下载文件数据
//本次接收的数据长度, 6是 LH,LL,/LH,/LL,CMD,CS的长度
TempLen = Rec.Buffer[2]*256+Rec.Buffer[3]-6;
//暂存数据
memcpy(Rec.Data+Rec.DataLen,Rec.Buffer+7,TempLen);
//长度增加
Rec.DataLen+=TempLen;
//达到256字节
if(Rec.DataLen>=PAGE_SIZE)
{
/* //测试文件接收256字节后自动向PC发送256字节
SerialPort_send(0xdd);
SerialPort_send(0xdd);
SerialPort_send(0xdd);
SerialPort_send(0xdd);
for(i=0;i<Rec.DataLen;i++)
{
SerialPort_send(Rec.Data[i]);
}
i=0;
if(i==0) while(1);
*/
//写到W29C040存储器
if(!WritePage(0,0,0,Rec.Data))
{
//发送出错命令
Cmd=0x0f;
SendCmdStr(&Cmd,1);
//重新开始接收
goto restart;
}
else //页写flash成功
{
Rec.DataLen=0; //数据长度清0
}
}
//发送下载成功命令
SendCmdStr(&Cmd,1);
CommOk=TRUE;
break;
case 0x07: //下载完成
SendCmdStr(&Cmd,1);
CommOk=TRUE;
break;
default: //错误
//发送出错命令
Cmd=0x0f;
SendCmdStr(&Cmd,1);
//重新开始接收
goto restart;
break;
}
//命令接收正常
if(CommOk)
{
Rec.Finish=FALSE; //设定未接收完毕
Rec.Len=0; //已接收长度
Rec.CmdLen=0; //PC发给下位机的命令的总长度
}
}
}
}
/**********************************************************************
* 函 数 名: serial1
* 功能描述: 串口1中断处理
* 函数说明:
* 调用函数: 无
* 全局变量:
* 输 入: 无
* 返 回: 无
* 设 计 者: wangyong 日期:2007-03-24
* 修 改 者: wangyong 日期:2007-03-24
* 版 本:
**********************************************************************/
void serial1() interrupt 4
{
//接收
if(RI)
{
RI=0;
//还没接完
if(!Rec.Finish)
{
//放入数据
Rec.Buffer[Rec.Len++]=SBUF;
//若已接收了4个字节,则可以算出
//整个命令串的总长度
if(Rec.Len==4)
{
Rec.CmdLen=(uint)(Rec.Buffer[2]*16+Rec.Buffer[3])+2; //命令总长度
}
else if(Rec.Len>4) //判断是否全部接收完命令
{
//已接收完,做标志
if(Rec.Len==Rec.CmdLen) Rec.Finish=TRUE;
}
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -