该程序需要自己做上位机,思路是mega128复位后从Bootload区启动, 运行Bootload区的程序,判断串口有在规定时间内有没有收到升级指令,如果收到,则进入编程模式,否则跳到0x0000处执行应用程序。 ( 芯片从Bootload区启动,这个是要烧写芯片配置位的,因为新买的芯片好像是从0x0000处开处执行的,),
程序没有经过整理,比较乱,分两个文件,一个asm文件,一个C文件
asm文件
.text
SPMCR = 0x68 ;RWW区忙标志,读RWW区允许,允许写程序存储区
; void write_page (unsigned int adr, unsigned char function);
; bits 8:15 adr addresses the page...(must setup RAMPZ beforehand!!!)
_write_page::
XCALL __WAIT_SPMEN__
movw r30, r16 ;z pointer (R31 = ZH, R30 = ZL)
STS SPMCR, R18 ;argument 2 decides function
SPM ;perform pagewrite
RET
;-----------------------------------------
; void fill_temp_buffer (unsigned int data, unsigned int adr);
; bits 7:1 in adr addresses the word in the page... (2=first word, 4=second word etc..)
_fill_temp_buffer::
XCALL __WAIT_SPMEN__
movw r30, r18 ;move adress to z pointer (R31=ZH R30=ZL)
movw r0, r16 ;move data to reg 0 and 1
LDI R19, 0x01
STS SPMCR, R19
SPM ;Store program memory
RET
;-----------------------------------------
;unsigned char read_flash(unsigned int add);
_read_flash::
mov r31,r17
mov r30,r16
lpm r16,z
clr r17
ret
;unsigned int read_program_memory (unsigned int adr ,unsigned char cmd);
_read_program_memory::
movw r30, r16 ;move adress to z pointer
SBRC R18, 0 ;read lockbits? (second argument = 0x09)
STS SPMCR, R18 ;if so, place second argument in SPMEN register
LPM r16, Z+
LPM r17, Z
RET
;-----------------------------------------
_enableRWW::
XCALL __WAIT_SPMEN__
LDI R27,0x11
STS SPMCR,R27
SPM
RET
;-----------------------------------------
__WAIT_SPMEN__:
LDS R27,SPMCR ; load SPMCR to R27
SBRC R27,0 ; check SPMEN flag
RJMP __WAIT_SPMEN__ ; wait for SPMEN flag cleared
RET
;-----------------------------------------
C文件
asm头文件就没有贴了,就是函数定义
/******************************************************************************
bootload area : 1K BOOTSZ1=1,BOOTSZ0=0 (1表示未编程,0表示已编程)
配置: SUT0=0,SUT1=1()
CKSEL0=0,CKSEL0=1,CKSEL0=1,CKSEL0=1 (外部时钟)
/*****************************************************************************/
#include <macros.h>
#include "asm.h"
#include "iom128v.h"
//芯片类型
#define ChipType Atmega128
//*********************************************************
//选择BOOT区大小
#define BootSize Ɖ'
//1024
//选择BootLoad版本号
#define BootVer Ƈ'
//1.0版本
//**********************************************************
//7.3728时钟下的波特率设置
#define BAUDRATE 25 //51 9600 //12 38400 [url=]//7@57600[/url] [url=]//3@115200[/url]
//3#115200
//*****************************************************************************
#define PageByte 256
void FlashLoad (void);
unsigned char GetPageNumber (void);
void ExecCode (void);
char GetPage (void);
void WriteFlash (void);
char CheckFlash (void);
void SendChar (unsigned char c);
void delay (void); //1ms延时函数
unsigned char RecChar (void);
unsigned char PageBuffer[PageByte];
long PageAddress;
unsigned int nTimeOut; //接收超时计数器
/*****************************************************************************/
//Flash编程
/*****************************************************************************/
void FlashLoad(void)
{
SendChar('!');
while (1)
{
if(GetPageNumber()==0) return;//接收不超时则为1,超时为0
if (GetPage())
{
WriteFlash();
if (CheckFlash()) SendChar('!');
else SendChar('@');
}
else
{
SendChar('@');
return;
}
}
}
/*****************************************************************************/
unsigned char GetPageNumber(void)
{
unsigned char PageAddressH;
unsigned char PageAddressL;
unsigned int OUT;
nTimeOut=0;
PageAddressH = RecChar();
// PageAddressL = RecChar();
while(!(UCSR0A & 0x80))
{
nTimeOut++;
if(nTimeOut>60000)//接收第二个字节有超时限制
return 0;
}
PageAddressL=UDR0;
// PageAddressL=RecChar();
if (PageAddressH) RAMPZ = 1;
else RAMPZ = 0;
OUT=(int)((PageAddressH << 8) + PageAddressL);
if(OUT==0xffff) return 0; //判断如果页地址大于1FF则退出
PageAddress=((int)((PageAddressH << 8) + PageAddressL))<<8;
return 1;
}
/*****************************************************************************/
char GetPage(void)
{
unsigned int i;
unsigned char LocalCheckSum = 0;
unsigned char CheckSum = 0;
for (i=0;i<256;i++) //接收一个页面数据
{
while(!(UCSR0A & 0x80))
{
nTimeOut++;
if(nTimeOut>60000)//接收有超时限制
return 0;
}
PageBuffer=UDR0;
LocalCheckSum += PageBuffer;
}
CheckSum = RecChar();
// SendChar(CheckSum);
// SendChar(LocalCheckSum);
if (LocalCheckSum == CheckSum) return 1;
else return 0;
}
/*****************************************************************************/
//写一个页面
void WriteFlash(void)
{
unsigned int i;
unsigned int TempInt;
for (i=0;i<256;i+=2)
{
TempInt=PageBuffer+(PageBuffer[i+1]<<8);
fill_temp_buffer(TempInt,i);
}
write_page(PageAddress,0x03); //擦除页
write_page(PageAddress,0x05); //写页数据
enableRWW();
}
/****************************************************************************/
// 校验FLASH,
char CheckFlash(void)
{
unsigned int i;
unsigned int TempInt;
unsigned int TempInt2;
for (i=0;i<256;i+=2)
{
TempInt = read_program_memory(PageAddress + i,0x00);
TempInt2 = PageBuffer +(PageBuffer[i+1]<<8);
if (TempInt != TempInt2) return 1;
}
return 1;
}
/*****************************************************************************/
/* 字符输入函数 */
unsigned char RecChar(void)
{
while(!(UCSR0A & 0x80));
return UDR0;
}
/*****************************************************************************/
/* 字符输入函数带超时标志 */
unsigned char RecChar_T(void)
{
while(!(UCSR0A & 0x80))
{
nTimeOut++;
if(nTimeOut>10000)//
return 0;
}
return UDR0;
}
/*****************************************************************************/
void SendChar(unsigned char c)
{
while (!(UCSR0A&0x20));// wait for empty transmit buffer
UDR0=c;
}
void delay(void)
{
unsigned int i;
for (i=0;i<65530;i++);
}
/*****************************************************************************/
void ExecCode(void)
{
RAMPZ = 0; //选中前64K
MCUCR=0X01; //中断向量表移位允许
MCUCR=0X00; //中断向量指向应用程序区
asm("jmp 0x0000");
}
/********************************************************************
系统时钟8M的毫秒级延时函数
********************************************************************/
void Delay_1ms(void) //1ms延时函数
{
unsigned int i;
for (i=0;i<7680;i++);
}
void Delay_nms(unsigned int n) //N ms延时函数
{
unsigned int i=0;
for (i=0;i<n;i++)
{
Delay_1ms();
}
}
void main(void)
{
UCSR0C=0x86; //8位数据+1位停止
UCSR0B = 0x18; //允许串口发送和接收
UBRR0H = 0x00;
UBRR0L = BAUDRATE; //设置波特率
SendChar('>'); //通知PC机,BOOT下载准备就绪
delay(); //延时等待
while (1)
{
switch (RecChar_T()) //等待接收命令,时间需要修改
{
case 'W':
FlashLoad();
SendChar('K');
break;
case 'E':
SendChar('E'); //通知PC机,进入运用程序区
Delay_1ms();
ExecCode(); //退出bootloader
break;
case '<':
SendChar(ChipType);
SendChar(BootSize);
SendChar(BootVer);
break;
default :
break;
}
}
} |