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

📄 newmain.c

📁 单片机MEGA128的BOOTLOADER程序。
💻 C
字号:

#include <macros.h>
#include <iom128v.h>
#include <eeprom.h>
#include <string.h>
#define SPM_PAGESIZE 256              //M128的一个Flash页为256字节(128字) 
#define DATA_BUFFER_SIZE SPM_PAGESIZE
//定义at45db161 控制I/O 
#define CS     4      //PB4   at45db161 片选
#define BUSY   5      //PB5   at45db161 忙
#define WP     6      //PB6   at45db161 写
#define RESET  7      //PB7   at45db161 复位


//定义全局变量 

char data[DATA_BUFFER_SIZE]; 
unsigned char Senddata[30];
long  Filelength;
long address = 0; 
unsigned int page_counter_rd;
unsigned int page_offset_rd;

unsigned char lengthbak1,lengthbak2;
int timenum;
int length;length1;
unsigned char ROK_flag,Num;
//延时
void delay_us(int time)
	 {     
  	  do
	  	{
		 time--;
		}	
  	  while (time!=0);
	 }	  


//擦除(code=0x03)和写入(code=0x05)一个Flash页 
void boot_page_ew(long p_address,char code) 
{ 
    asm("mov r30,r16\n" 
        "mov r31,r17\n" 
        "out 0x3b,r18\n");            //将页地址放入Z寄存器和RAMPZ的Bit0中 
    SPMCSR = code;                //寄存器SPMCSR中为操作码 
    asm("spm\n");                    //对指定Flash页进行操作 
}         
//填充Flash缓冲页中的一个字 
void boot_page_fill(unsigned int address,int data) 
{ 
    asm("mov r30,r16\n" 
        "mov r31,r17\n"             //Z寄存器中为填冲页内地址 
        "mov r0,r18\n" 
        "mov r1,r19\n");            //R0R1中为一个指令字 
    SPMCSR = 0x01; 
    asm("spm\n"); 
} 
//等待一个Flash页的写完成 
void wait_page_rw_ok(void) 
{ 
      while(SPMCSR & 0x40) 
     { 
         while(SPMCSR & 0x01); 
         SPMCSR = 0x11; 
         asm("spm\n"); 
     } 
} 
//更新一个Flash页的完整处理 
void write_one_page(void) 
{ 
    int i; 
    boot_page_ew(address,0x03);                    //擦除一个Flash页 
    wait_page_rw_ok();                            //等待擦除完成 
    for(i=0;i<SPM_PAGESIZE;i+=2)  //jia
	  { 
        boot_page_fill(i, data[i]+(data[i+1]<<8)); 
    } 
    boot_page_ew(address,0x05);                    //将缓冲页数据写入一个Flash页 
    wait_page_rw_ok();                            //等待写入完成 
}         

//退出Bootloader程序,从0x0000处执行应用程序 
void quit(void) 
{     
 	 MCUCR = 0x01; 
     MCUCR = 0x00;                    //将中断向量表迁移到应用程序区头部 
     RAMPZ = 0x00;                    //RAMPZ清零初始化 
     asm("jmp 0x0000\n");                //跳转到Flash的0x0000处,执行用户的应用程序 
} 
//初始化I/O
void Init_mag128(void)
{
 PORTA = 0x00;
 DDRA  = 0x00;
 PORTB = 0xd7;
 DDRB  = 0xd7;
 PORTC = 0xff; //m103 output only
 DDRC  = 0x00;
 PORTD = 0x01;
 DDRD  = 0xf1;
 PORTE = 0x02;
 DDRE  = 0x02;
 PORTF = 0x00;
 DDRF  = 0x00;
 PORTG = 0x0;
 DDRG  = 0x0;
}
//初始化 SPI
void Init_SPI(void)
{
 SPCR = 0x5e; //setup SPI
 SPSR = 0x00; //setup SPI
}

/*	  		    毫秒级延时程序			*/	 
void delay_ms(unsigned int time)
	 {
	  while(time!=0)
	  	  {		
		   delay_us(1850);
		   time--;
		    if(PORTD&0x01==1)PORTD=PORTD&0xfe;
  			else PORTD=PORTD|0x1;
		  }
	 }	
void clr_dog(void)
{
if(PORTD&0x01==1)PORTD=PORTD&0xfe;
else PORTD=PORTD|0x1;
}
//spi模式3
//flash复位
void df_reset(void)
{
PORTB&=~(1<<RESET);  
delay_us(500);
PORTB|=1<<RESET;
}
//主模式下发送一个字节或接收一个字节
unsigned char SPI_TranByte(unsigned char cData)
{
SPDR=cData;
while(!(SPSR&0x80));
return SPDR;
}

void Read_Testfile(char *File ,int len )
{
unsigned char i,j;
while(!(PINB&0x20));
PORTB&=~(1<<CS);//使能 at45
SPI_TranByte(0x3);
SPI_TranByte((char)(page_counter_rd>>6));//页地址PA11-PA6
SPI_TranByte((char)((page_counter_rd<<2)|(page_offset_rd>>8)));////页地址PA5-PA0
SPI_TranByte((char)page_offset_rd);
 while(len)
  {
  SPDR=0;
  while(!(SPSR&0x80));
  *File=SPDR;
  File++; 
  len--;
  page_offset_rd++;
  if(page_offset_rd>=528)
       {
	   page_offset_rd=0;
	   page_counter_rd++;
	   if(page_counter_rd>=4096){quit();page_counter_rd=3849;}
	   }
	   
  }
PORTB|=1<<CS; 
}
//UART1 initialize
// desired baud rate:57600
// actual baud rate:57599 (0.0%)
// char size: 8 bit
// parity: Disabled
void uart1_init(void)
{
 UCSR1B = 0x00; //disable while setting baud rate
 UCSR1A = 0x00;
 UCSR1C = 0x06;
 UBRR1L = 0x0B; //set baud rate lo
 UBRR1H = 0x00; //set baud rate hi
 UCSR1B = 0x18;
}
/*//UART1 initialize
// desired baud rate:19200
// actual baud rate:19200 (0.0%)
// char size: 8 bit
// parity: Disabled
void uart1_init(void)
{
 UCSR1B = 0x00; //disable while setting baud rate
 UCSR1A = 0x00;
 UCSR1C = 0x06;
 UBRR1L = 0x23; //set baud rate lo
 UBRR1H = 0x00; //set baud rate hi
 UCSR1B = 0x18;
}*/
unsigned char RecChar(void)
  {
      timenum=0;
     do{
	   timenum++;
	   if(timenum>50000){timenum=0;clr_dog();}
       }while(!(UCSR1A & 0x80));
     return UDR1;
  }		
/*unsigned char RecChar(void)
  {
       timenum=0;
     do{
	   timenum++;
	   clr_dog();
       }while((!(UCSR0A & 0x80))&&(timenum<10000000));
     return UDR0;
  }		 */ 
  
 /*  		字符输出函数 		 */
void  Send_ByteUART1(char  ch)
	{	
	 UDR1=ch;
     while (!(UCSR1A&(1<<UDRE1)));          //UCSRA USART 控制状态寄存器A  UDRE=TI
	} 
	
void send232(unsigned char *s,unsigned char l)
{
unsigned char i;
for(i=0;i<l;i++)
Send_ByteUART1(*(s+i));
}	 
void sendok(void)
{
unsigned char i=0;
Senddata[0]='!'; 
Senddata[5]=1;
Senddata[6]=0xd;
Senddata[7]=0xa;
send232(Senddata,8);
}  
void senderror(void)
{
unsigned char i=0;
Senddata[0]='!';
Senddata[5]=0;
Senddata[6]=0xd;
Senddata[7]=0xa;
send232(Senddata,8);
}   
void uart0_rx(void)
{
char flag,jym,jym1;
int i;
flag=0;
do{
  
  if(data[0]!='!')data[0]=RecChar();   
  else
	 {
	  Senddata[1]=RecChar();
	  Senddata[2]=RecChar();
	  Senddata[3]=RecChar();
	  Senddata[4]=RecChar();
	  
	  for(i=0;i<256;i++)
      data[i]=RecChar();		  
	  jym=RecChar();	   
	  jym1=0;	  
	  for(i=0;i<256;i++)jym1=jym1^data[i];
	  if(jym!=jym1)
	  senderror();	
	  else if((lengthbak1==Senddata[3])&&(lengthbak2==Senddata[4]))sendok(); 
	  else if((Senddata[1]==Senddata[3])&&(Senddata[2]==Senddata[4]))
	  {
	  ROK_flag=1;
	  flag=1;
	  }
	  else  {lengthbak1=Senddata[3];lengthbak2=Senddata[4];flag=1;}	  
	 }
 // else senderror();
  }while(flag==0); 
}	 
//主程序 
void main(void)
  {
    unsigned char BootFlag,i; 
	int page_num,byte_num;	
    Init_mag128();
	uart1_init();
	//PORTD&=~(1<<7);//GSM关机
	PORTD|=(1<<7);
	Init_SPI();	
	df_reset();
	
	delay_ms(1000);
	EEPROM_READ(0x7ff,BootFlag);	
	delay_ms(2);
	if(BootFlag==0)quit();
	else if(BootFlag!=1)
	   {     
	         for(i=0;i<12;i++)
             data[i]=RecChar();	         
			 if((data[0]=='B')&&(data[1]=='o'))
			 {
			  delay_ms(200);
			  sendok();
	     	 do{ 
		   	   uart0_rx();  
	       	   write_one_page();            //收到256字节写入一页Flash中 
           	   address += SPM_PAGESIZE;     //Flash页加1  	
			   sendok();
			   delay_ms(1);	   
		  	   }while(ROK_flag==0);		 
		      delay_ms(20);
			  BootFlag=0;
			  EEPROM_WRITE(0x7ff,BootFlag);	
			  delay_ms(2000);
			  quit();
			  }
			else quit();
	   }
	else 
	{  
	   page_counter_rd=3849;//128k;
	   page_offset_rd=0;
	   delay_ms(2);
	   Read_Testfile(data ,4 );	
	   delay_ms(2);
	   Filelength=0;
	   Filelength=data[2];
	   Filelength=Filelength*0x100+data[3];
	   delay_ms(1000);
	   address=0;
	    while (Filelength>SPM_PAGESIZE)
		   {
		   delay_ms(2);
		   page_num=page_counter_rd;
	       byte_num=page_offset_rd;  
		   memset(data,0xff,SPM_PAGESIZE); 	
	   	   Read_Testfile(data ,SPM_PAGESIZE );
		   
		   delay_ms(10);
		   
		   write_one_page();            //收到256字节写入一页Flash中 
           address += SPM_PAGESIZE;    //Flash页加1 
		   Filelength=Filelength-SPM_PAGESIZE;		  
		   }
		 if(Filelength>0)
		       {
			    delay_ms(2);
			    memset(data,0xff,SPM_PAGESIZE); 
			    Read_Testfile(data ,Filelength );				    
		   		write_one_page();
				clr_dog();
		   		BootFlag=0;
				EEPROM_WRITE(0x7ff,BootFlag);	
				EEPROM_WRITE(0x600,BootFlag);	 
		        quit();
		       }
		else
			   {
			   delay_ms(2);
			   BootFlag=0;
			   EEPROM_WRITE(0x7ff,BootFlag);	
			   EEPROM_WRITE(0x600,BootFlag); 
		       quit();
			   }  
		}
  }

⌨️ 快捷键说明

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