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

📄 updater_f02x.c

📁 F020.rar
💻 C
字号:
/*
可用于用户程序的空间共为122个扇区共62464个字节(0x0000-0xF3FF)
引导程序占用四个扇区(0xF400-0xFBFF) 2048字节 
*/
#include <c8051f020.h>                 // SFR declarations
#include "crc.h"

//-----------------------------------------------------------------------------
// Global CONSTANTS
//-----------------------------------------------------------------------------
#define TRUE         1
#define FALSE        0

#define SYSCLK       22118400          // SYSCLK frequency in Hz
#define BAUDRATE     115200            // Baud rate of UART in bps

#define BINCELL_LEN  518               //数据段大小

sbit Run = P3^7;                       // LED='1' means ON

unsigned char xdata Rec_Buf[600];
unsigned char xdata Send_Buf[512];
unsigned int P_RecBuf=0;
//-----------------------------------------------------------------------------
// Function PROTOTYPES
//-----------------------------------------------------------------------------

void main (void);

// Initialization Subroutines
void SYSCLK_Init (void);
void PORT_Init (void);
void UART0_Init (void);


//-----------------------------------------------------------------------------
// Global VARIABLES
//-----------------------------------------------------------------------------

void (*f)();                           // function pointer declaration

bit code_erased = FALSE;               // flag used to indicate that the FLASH
                                       // erase operation is complete
bit f_valid = FALSE;                   // flag to indicate that the FLASH 
                                       // programming operation is complete
bit Need_Update=0;

unsigned char Update_Step=0;
//-----------------------------------------------------------------------------
// MAIN Routine
//-----------------------------------------------------------------------------

void DealRec();
void SendData(unsigned char *SendBuf,unsigned char SendLen);
void Erase_Flash(unsigned char Erase_Page);
void Write_Flash(unsigned char *Write_Buf,unsigned char Write_Page);
unsigned char Read_Flash(unsigned int Read_Address );

//延时1ms
void DelayMs(unsigned int TimeNum)
{
	unsigned int i,j;
	for(i=0;i<TimeNum;i++)
	{
		for(j=0;j<185;j++);
	}
}

void JumpToRun()
{
	 IE=0;
	 CKCON=0;
	 PCON=0;
	 TMOD=0;
	 SCON0=0;
	 TH1=0;
	 TL1=0;
	 TR1=0;
	 ((void(code *)(void))0xF400)();

}

void main (void) 
{
   unsigned int Update_OverTime=0;   

   WDTCN = 0xde;                       // disable watchdog timer
   WDTCN = 0xad;

   EA = 0;                             // disable interrupts (this statement
                                       // is needed because the device is not
                                       // neccesarily in a reset state prior 
                                       // to executing this code) 
   OSCXCN=0;


   PORT_Init ();                       // initialize crossbar and GPIO
   SYSCLK_Init ();                     // initialize oscillator
   UART0_Init ();                      // initialize UART0
   
   Run=0;
   
   DelayMs(100);
   Update_Step=1;
   Send_Buf[0]=0x55;
   Send_Buf[1]=0xAA;
   Send_Buf[2]=0xA1;
   SendData(Send_Buf,3);

   /*while(RI0==0)
   {
      if(Update_OverTime>60000) //如果升级超时,则进入正常程序
	  {
		  JumpToRun();

	  }
	  else
	  {
	     Update_OverTime++; 
	  }
   }
   Rec_Buf[P_RecBuf++]=SBUF0;
   RI0=0;
   Update_OverTime=0;*/

       
   while (1)
   {
	   while(RI0==0)
	   {
	      if(Need_Update==0)
	     {
             if(Update_OverTime>60000) //如果升级超时,则进入正常程序
	        {
		        JumpToRun();

	        }
	         else
	        {
	           Update_OverTime++; 
	        }
	     }
	   }

	   Rec_Buf[P_RecBuf++]=SBUF0;
	   RI0=0;
	   Update_OverTime=0;
	   DealRec();
   } // end while

} // end main

void SendData(unsigned char *SendBuf,unsigned char SendLen)
{
      unsigned char i;
	  for(i=0;i<SendLen;i++)
	  {
	      SBUF0=SendBuf[i];
		  while(TI0==0);
		  TI0=0;
	  }
}

void DealRec()
{
     unsigned int i;
	 unsigned int CRC;
	 unsigned char CRC_H;
	 unsigned char CRC_L;
	 unsigned int Cell_No;
	 bit Write_Error=0;
	 if(P_RecBuf>=3) //至少收到三个字节。
	 {
	     if(Rec_Buf[0]==0x55&&Rec_Buf[1]==0xAA)	//数据帧头有效
		 {
		     switch(Rec_Buf[2])
			 {
			      case 0xB1:		   //收到上位机应答升级请求的命令
				            if(Update_Step==1)
							{
							   Update_Step=2;
							   Need_Update=1;
							}
							P_RecBuf=0;
				            break;
				  case 0xC1:		   //收到上位机要求升级的指令
				            if(Update_Step==2)
							{
							  Update_Step=3;
							  Send_Buf[0]=0x55;
							  Send_Buf[1]=0xAA;
							  Send_Buf[2]=0xD1;
							  SendData(Send_Buf,3); //返回可以接收数据
				            }
							P_RecBuf=0;
							break;
				  case 0xE1:		   //收到上位机发送的数据帧
				            if(P_RecBuf<BINCELL_LEN) return;  //帧未收全则返回
				            if(Update_Step!=3) {P_RecBuf=0;return;}
							
							CRC=cal_crc(Rec_Buf+4,512);
							CRC_H=CRC>>8;
							CRC_L=CRC;
							if(Rec_Buf[516]==CRC_H&&Rec_Buf[517]==CRC_L)	//通过CRC校验,则写入数据
							{
							     Cell_No=Rec_Buf[3];     //取出当前是第几个数据块
								 if(Cell_No==0)			 //如果当前是第一条数据,进行处理
								 {
							         for(i=1;i<123;i++)
							        {
							            Erase_Flash(i);
							        }

								     //Erase_Flash(122);
									 Write_Flash(Rec_Buf+4,122);
									 Rec_Buf[5]=Read_Flash(1);
									 Rec_Buf[6]=Read_Flash(2);
									 Erase_Flash(0);
									 Write_Flash(Rec_Buf+4,0);
								 }
								 else if(Cell_No<=121)	 //收到的数据没有超出可写范围则写入
								 {
								     //Erase_Flash(Cell_No);
									 Write_Flash(Rec_Buf+4,Cell_No);
								 }
								 for(i=0;i<512;i++)
								{
								   if(Rec_Buf[4+i]!=Read_Flash(Cell_No*512+i))Write_Error=1;
								}
								 if(!Write_Error)
								 {
								    Send_Buf[0]=0x55;
							        Send_Buf[1]=0xAA;
							        Send_Buf[2]=0xD2;
							        SendData(Send_Buf,3); //返回可以接收下一条数据
								 }
								 else
								 {
							        Send_Buf[0]=0x55;
								    Send_Buf[1]=0xAA;
								    Send_Buf[2]=0xD4;
								    SendData(Send_Buf,3); //返回升级失败
								    
								 }
							}
							else
							{
							     Send_Buf[0]=0x55;
								 Send_Buf[1]=0xAA;
								 Send_Buf[2]=0xD4;
								 SendData(Send_Buf,3); //返回升级失败
							}
							P_RecBuf=0;
							break;
				   case 0xE2:		   //上位机给出升级成功指令,则开始运行正常程序
						    if(Update_Step!=3) {P_RecBuf=0;return;}
							P_RecBuf=0;
				            JumpToRun();
							break;
				   default :
				            P_RecBuf=0;
				            break;
			 }
		 }
		 else
		 {
		     P_RecBuf=0;   //帧头无效则清除接收缓存
		 }

	 }
}
//-----------------------------------------------------------------------------
// erase_flash
//-----------------------------------------------------------------------------
//
// This routine erases the first 8 pages of FLASH (0x0000 to 0x0FFF).
//
void Erase_Flash(unsigned char Erase_Page)
{
   char xdata* data pagePointer = 0;// a pointer to xdata located in data space
                                    // points to the first FLASH page that 
                                    // will be erased
      
   bit EA_state;                    // holds interrupt state

   EA_state = EA;                   // save interrupt state

   EA = 0;                          // disable interrupts
   FLSCL |= 0x01;                   // enable FLASH write/erase
   PSCTL  = 0x03;                   // MOVX erases FLASH
   
   // Erase the first 8 FLASH pages
   pagePointer=Erase_Page*512;
      *pagePointer = 0;             // initiate the erase
      
   PSCTL = 0x00;                    // MOVX writes target XRAM
   FLSCL &= ~0x01;                  // disable FLASH write/erase
   
   EA =  EA_state;                  // restore interrupt state

   f_valid = FALSE;                 // indicate that code is no longer valid
   code_erased = TRUE;              // indicate that FLASH has been erased
}

void Write_Flash(unsigned char *Write_Buf,unsigned char Write_Page)
{
	  char xdata* data pwrite;
	  unsigned int i;

      EA = 0;                             // disable interrupts (precautionary)   
      FLSCL |= 0x01;                      // enable FLASH write/erase
      PSCTL  = 0x01;                      // MOVX writes FLASH

      pwrite = Write_Page*512;      // initialize the write pointer
    
      // write the record into flash
      for( i = 0; i < 512; i++)
	  {
         *pwrite=Write_Buf[i];
		 pwrite++;
      }
      
      PSCTL = 0x00;                       // MOVX writes target XRAM
      FLSCL &= ~0x01;                     // disable FLASH write/erase
}

unsigned char Read_Flash(unsigned int Read_Address )
{
      char code* data pread; 
	  unsigned char ReadTemp;
	  pread =  (char code*)Read_Address;
	  ReadTemp=*pread;
	  return(ReadTemp);
}

//-----------------------------------------------------------------------------
// Initialization Subroutines
//-----------------------------------------------------------------------------

//-----------------------------------------------------------------------------
// SYSCLK_Init
//-----------------------------------------------------------------------------
//
// This routine initializes the system clock to use an 22.1184MHz crystal
// as its clock source.
//
void SYSCLK_Init (void)
{
   int i;                              // delay counter

   OSCXCN = 0x67;                      // start external oscillator with
                                       // 22.1184MHz crystal

   for (i=0; i < 256; i++) ;           // wait for osc to start

   while (!(OSCXCN & 0x80)) ;          // Wait for crystal osc. to settle

   OSCICN = 0x88;                      // select external oscillator as SYSCLK
                                       // source and enable missing clock
                                       // detector
}

//-----------------------------------------------------------------------------
// PORT_Init
//-----------------------------------------------------------------------------
//
// Configure the Crossbar and GPIO ports
//
void PORT_Init (void)
{
   XBR0    = 0x17;                     // Enable UART0,SPI,I2C,CEX0,CEX1
   XBR1    = 0x16;					   //使能两外部中断,TO输入口
   P0MDOUT=0x15;
   P1MDOUT=0x01;
   P2MDOUT=0xC0;
   P3MDOUT  = 0xC0;                    
   P74OUT   = 0x00;                    //P4~P7设为开漏输出
   EMI0CF   = 0x2B;                    //XRAM的访问方式为带块选择分片方式。输入输出端口使用P4~P7,地址复用方式;
   XBR2    = 0x44;                     // Enable crossbar and weak pull-ups	 ,UART1

}

//-----------------------------------------------------------------------------
// UART0_Init
//-----------------------------------------------------------------------------
//
// Configure the UART0 using Timer1, for <baudrate> and 8-N-1.
//
void UART0_Init (void)
{
   SCON0   = 0x50;                     // SCON0: mode 1, 8-bit UART, enable RX
   TMOD    = 0x20;                     // TMOD: timer 1, mode 2, 8-bit reload
   TH1    = -(SYSCLK/BAUDRATE/16);     // set Timer1 reload value for baudrate
   TR1    = 1;                         // start Timer1
   CKCON |= 0x10;                      // Timer1 uses SYSCLK as time base
   PCON  |= 0x80;                      // SMOD00 = 1
   ES0=0;
   TI0= 0;                       
   RI0=0;
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -