📄 w78e516b_iap.c
字号:
//5.1看门狗禁止以改写完毕。
#include <reg54.h>
#include <absacc.h>
#define PROMCSLOW DECD=1;DECC=0;DECB=1;DECA=0;
#define PROMCSHIGH DECD=0;DECC=0;DECB=0;DECA=0;
sbit DOUT=P1^5; //原系统的din/dout定义与datasheet相反。
sbit DIN=P1^4;
sbit SCLK=P1^6;
sbit LED1=P4^3;
sbit LED2=P4^2;
sbit A16=P1^7;
sbit PROMSO=P1^5;
sbit PROMSI=P1^4;
sbit PROMSCK=P1^6;
sfr CHPCON=0xBF; //在编程特殊寄存器定义;
sfr CHPENR=0xF6;
sfr SFRAL=0xC4;
sfr SFRAH=0xC5;
sfr SFRFD=0xC6;
sfr SFRCN=0xC7;
sbit DECA=P1^0; //DECODER ,译码器;
sbit DECB=P1^1;
sbit DECC=P1^2;
sbit DECD=P1^3;
unsigned char TLOW,THIGH; //在定时器0与各iap函数间传递定时参数;
unsigned char receiveflag=3; //在主函数与外部中断0之间传递数据接收完成标志; //3:接收程序数据低位,2:接收程序数据高位,1:数据0:接收完毕;
unsigned char sizelow,sizehigh; //下载程序大小高低位
unsigned int size; //下载程序总大小;
unsigned int cursor; // 下载数据存入外存地址,每次中断后保存,所以定义为全局变量;
unsigned char byt8(unsigned char tx) //向扩3100写入一个字节同时接收一个字节;
{
unsigned char i;
unsigned char mask;
unsigned char rx;
DOUT=1;
mask=0x80;
rx=0;
for(i=0;i<8;i++) //移位;
{
if(tx & mask)
DIN=1;
else
DIN=0;
SCLK=1;
mask=mask/2;
if(DOUT)
{
rx=rx*2;
rx=rx | 0x01;
}
else
rx=rx*2;
SCLK=0;
}
return(rx);
}
unsigned char utlk(unsigned char tx1,unsigned char tx2) //talk to uart;
{
unsigned char c;
EX0=0;
DECD=1; DECC=0; DECB=0; DECA=0;
c=byt8(tx1);
c=byt8(tx2);
DECD=0; DECC=0; DECB=0; DECA=0;
EX0=1;
return(c);
}
void WatchdogDisable() //此程序中延时全部从原函数中去掉了;
{
unsigned char i;
PROMSCK=0;
PROMCSLOW //WREN
for(i=0;i<5;i++) //"00000"
{
PROMSI=0;
PROMSCK=1; //时钟上升沿输入数据
PROMSCK=0;
}
for(i=0;i<2;i++) //"11"
{
PROMSI=1;
PROMSCK=1;
PROMSCK=0;
}
PROMSI=0; //"0"
PROMSCK=1;
PROMSCK=0;
PROMCSHIGH
PROMCSLOW //WRSR
for(i=0;i<7;i++) //"0000000"
{
PROMSI=0;
PROMSCK=1;
PROMSCK=0;
}
PROMSI=1; //"1";
PROMSCK=1;
PROMSCK=0;
PROMSI=0; //"0"
PROMSCK=1;
PROMSCK=0;
PROMSI=0; //"0"
PROMSCK=1;
PROMSCK=0;
//"11" for watchdog disable
PROMSI=1;
PROMSCK=1;
PROMSCK=0;
PROMSI=1;
PROMSCK=1;
PROMSCK=0;
for(i=0;i<4;i++) //"0000"
{
PROMSI=0;
PROMSCK=1;
PROMSCK=0;
}
PROMCSHIGH //看门狗片选为高,片外ram片选为低,选中;
}
void Flash() //指示灯1闪烁;
{
unsigned int i;
LED1=0;
for(i=0;i<30000;i++);
LED1=1;
for(i=0;i<30000;i++);
}
void Light() //两灯同步闪烁;
{
unsigned int i;
LED1=0;
LED2=0;
for(i=0;i<35000;i++);
LED1=1;
LED2=1;
for(i=0;i<35000;i++);
}
void Erase() //64flash擦除;
{
SFRCN=0x22;
TL0=0x3C;
TH0=0xB0;
TCON=0x10;
PCON=0x01;
}
bit BlankCheck() //64k flash 空白检查;
{
bit flag=1;
unsigned int index;
SFRCN=0x00;
SFRAH=0x00;
SFRAL=0x00;
TLOW=0xFB;
THIGH=0xFF;
for(index=0;index<0xFFFF;index++)
{
TR0=1;
PCON=0x01;
if(SFRFD!=0xFF)
{
flag=0;
break;
}
else
{
SFRAL++;
if(SFRAL==0)
SFRAH++;
}
}
return(flag);
}
void Program() //编程函数两分支共用,外存由A16区分,
{
unsigned int index;
SFRCN=0x21; //设定为写操作;
SFRAL=0x00;
SFRAH=0x00;
TLOW=0x5A; //iap时间设定; 比标准时间略长;
THIGH=0xFF;
for(index=0;index<0xFFFF;index++)
{
SFRFD=XBYTE[index];
TR0=1;
PCON=0x01;
SFRAL++;
if(SFRAL==0)
SFRAH++;
}
SFRAL=0x00; //第一个数据重新写过,否则出错,没搞懂;
SFRAH=0x00;
TLOW=0x5A; //iap时间设定; 比标准时间略长;
THIGH=0xFF;
SFRFD=XBYTE[0x00];
TR0=1;
PCON=0x01;
}
bit Verify() //编程数据验证;
{
bit flag=1;
unsigned int index;
SFRCN=0x00;
SFRAH=0x00;
SFRAL=0x00;
TLOW=0xFB;
THIGH=0xFF;
for(index=0;index<0xFFFF;index++)
{
TR0=1;
PCON=0x01;
if(SFRFD!=XBYTE[index])
{
flag=0;
break;
}
else
{
SFRAL++;
if(SFRAL==0)
SFRAH++;
}
}
return(flag);
}
void main()
{
bit iapokflag=0; //编程标志位;
unsigned int i; //情外存地址信息;
unsigned char pcon; //chpcon;
unsigned char times=3; //在编程失败重复次数;
unsigned j; //for test
WatchdogDisable(); //此函数出来,已选中片外ram
TCON=0x00;
TMOD=0x01;
IP=0x00;
IE=0x82;
CHPENR=0x87;
CHPENR=0x59;
pcon=CHPCON;
pcon=pcon&0x80;
for(j=0;j<60000;j++)
LED2=0;
LED2=1;
////////////////////////////////////////////////////////////////////////////
if(pcon==0)// not f04k boot mode;从主程序转来
{
Flash();
CHPENR=0;
//从64k 进入,数据已准备好在片外ram地址高端
A16=1;
while((iapokflag!=1)&&(times!=0))
{
Erase(); //擦除片内64k flash;
Flash();
if(BlankCheck()==0)
{
times--;
continue;
}
Flash();
Program();
Flash();
if(Verify()==0)
{
times--;
continue;
}
Flash();
iapokflag=1;
}
if(iapokflag==1) //在编程成功,软件重启,执行64k程序;
{
Flash();
Flash();
CHPENR=0x87;
CHPENR=0x59;
CHPCON=0x83;
}
while(1) //如果再编程未成功,等常闪;
Light();
}
///////////////////////////////////////////////以下为f04k boot mode 处理,硬启动处理;
else
{
A16=0; //选中片外ram低端;
for(i=0;i<0xFFFF;i++)
XBYTE[i]=0xFF;
Flash();
//外存清空,闪烁指示;
EX0=1; //中断设置;
SCLK=0;
utlk(0xC4,0x00); //下载串口3100初始化
sizelow=0;
sizehigh=0;
size=0;
cursor=0;
while(receiveflag!=0); //等所有数据接收完毕
EX0=0;
utlk(0x80,sizehigh); //数据接收完毕,返回数据长度;
utlk(0x80,sizelow);
CHPCON=0x03;
CHPENR=0x00;
//开始编程,数据位于片外ram低端;
while((iapokflag!=1)&&(times!=0))
{
Erase(); //擦除片内64k flash;
Flash();
if(BlankCheck()==0)
{
times--;
continue;
}
Flash();
//从串口再编程操作
Program();
Flash();
if(Verify()==0) //这个函数有问题!
{
times--;
continue;
}
Flash();
iapokflag=1;
}
if(iapokflag==1)
{
Flash();
Flash();
Flash();
while(1)
{
LED1=0; //两灯常亮,编程完毕;
LED2=0;
}
}
else
{
LED2=0; //一灯闪,一灯常亮,编程失败;
while(1)
Flash();
}
}
}
void DownLoad() interrupt 0 //下载串口中断服务程序;
{
unsigned char temp;
temp=utlk(0x00,0x00);
if(receiveflag==1)
{
XBYTE[cursor]=temp;
cursor++;
if(cursor==size) //程序数据扔到外存;
receiveflag=0; //所有数据接收完毕,置标志位为零;
return;
}
else
if(receiveflag==3)
{
sizelow=temp; //程序数据长度低位;
receiveflag--;
}
else
if(receiveflag==2)
{
sizehigh=temp;
receiveflag--;
size=sizehigh*256+sizelow;
}
}
void Timer0() interrupt 1 //定时器1中断服务程序;
{
TR0=0;
TL0=TLOW;
TH0=THIGH;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -