⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 w78e516b_iap.c

📁 W78E516B 从4k Flash对64k主空间编程的完整程序
💻 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 + -