📄 main._c
字号:
/******************************************************************************
Atmega系列单片机 BootLoader程序
日 期:2007年4月
作 者:likeeavr
版权所有:avrvi论坛 www.avrvi.com bbs.avrvi.com
说明:当前版本只针对本论坛M16开发板
上位机借用了冯建辉的程序。
/*****************************************************************************/
#include <macros.h>
#include "assembly.h"
#define ChipType Atmega16
//*********************************************************
//选择BOOT区大小 此必须与ICC options中的选项相对应
//#define BootSize 'a' //128
//#define BootSize 'b' //256
//#define BootSize 'c' //512
#define BootSize 'd' //1024
//选择BootLoad版本号
#define BootVer 'f' //1.0版本
//**********************************************************
#define Atmega16 0x31
//*****************************************************************************
#define InteClk //是否使用内部时钟
#define OscAddress 0x1fff //时钟校准值存储地址
//*****************************************************************************
//7.3728M时钟下的波特率为19200的设置,此设置可根据ICC生成,选对芯片,时钟,波特率既可
//由此语句调用UBRR = BAU;
#define BAU 23 // 7.3728M 19200
//#define BAU 191 // 7.3728M 2400
//#define BAU 95 // 7.3728M 4800
//#define BAU 47 // 7.3728M 9600
//#define BAU 31 // 7.3728M 14400
//#define BAU 23 // 7.3728M 19200
//#define BAU 15 // 7.3728M 28800
//#define BAU 38 // 12M 19200
//*****************************************************************************
#include <iom16v.h>
#define PageByte 128
#define AddressShift 7
#define INTVECREG GICR
void FlashLoad (void);
void GetPageNumber (void);
void ExecCode (void);
char GetPage (void);
void WriteFlash (void);
char CheckFlash (void);
unsigned char IsChar (void);
void SendChar (unsigned char c);
void delay (void); //1ms延时函数
unsigned char RecChar (void);
unsigned char PageBuffer[PageByte];
unsigned int RealPageAddress;
unsigned int PageAddress;
/*****************************************************************************/
//Flash编程
/*****************************************************************************/
void FlashLoad(void)
{
SendChar('!');
while (1)
{
GetPageNumber();
if (RealPageAddress == 0xffff)
return;
if (GetPage())
{
WriteFlash();
if (CheckFlash())
SendChar('!');
else
SendChar('@');
}
else
SendChar('@');
}
}
/*****************************************************************************/
void GetPageNumber(void)
{
unsigned char PageAddressH;
unsigned char PageAddressL;
PageAddressH = RecChar();
PageAddressL = RecChar();
RealPageAddress=(int)((PageAddressH << 8) + PageAddressL);
PageAddress=RealPageAddress<<AddressShift;
#ifdef RAMPZ_FLAG
if (PageAddressH)
RAMPZ = 1;
else
RAMPZ = 0;
#endif
}
/*****************************************************************************/
char GetPage(void)
{
unsigned char i;
unsigned char LocalCheckSum = 0;
unsigned char CheckSum = 0;
for (i=0;i<PageByte/2;i++)
{
while(!IsChar());
PageBuffer[i]=RecChar();
LocalCheckSum ^= PageBuffer[i];
}
for (i=0;i<PageByte/2;i++)
{
while(!IsChar());
PageBuffer[i+PageByte/2]=RecChar();
LocalCheckSum ^= PageBuffer[i+PageByte/2];
}
CheckSum = RecChar();
if (LocalCheckSum == CheckSum)
return 1;
else
return 0;
}
/*****************************************************************************/
void WriteFlash(void)
{
unsigned int i;
unsigned int TempInt;
for (i=0;i<PageByte;i+=2)
{
TempInt=PageBuffer[i]+(PageBuffer[i+1]<<8);
fill_temp_buffer(TempInt,i); //call asm routine.
}
write_page(PageAddress,0x03); //擦除页
write_page(PageAddress,0x05); //写页数据
enableRWW();
}
/*****************************************************************************/
char CheckFlash(void)
{
unsigned char i;
unsigned int TempInt;
unsigned int TempInt2;
for (i=0;i<PageByte;i+=2)
{
TempInt = read_program_memory(PageAddress + i,0x00);
TempInt2 = PageBuffer[i] +(PageBuffer[i+1]<<8);
if (TempInt != TempInt2)
return 0;
}
return 1;
}
/*****************************************************************************/
/* Serial Port Code */
/*****************************************************************************/
unsigned char IsChar(void)
{
if(UCSRA & 0x80)
return 1;
else
return 0;
}
/*****************************************************************************/
/* 字符输入函数 */
unsigned char RecChar(void)
{
while(!(UCSRA & 0x80));
return UDR;
}
/*****************************************************************************/
void SendChar(unsigned char c)
{
while (!(UCSRA&(1<<UDRE)));
UDR=c;
}
void delay(void)
{
unsigned int i;
for (i=0;i<65530;i++);
}
/*****************************************************************************/
void ExecCode(void)
{
#ifdef RAMPZ_FLAG
RAMPZ = 0;
#endif
INTVECREG=0x01; //中断向量表移位允许
INTVECREG=0x00; //中断向量指向应用程序区
asm("jmp 0x0000");
}
void main(void)
{
unsigned char BootFlag;
#ifdef InteClk //如果使用内部时钟,读取时钟校准值
OSCCAL=read_flash(OscAddress);
#endif
UCSRC=(1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0); //8位数据+1位停止
UCSRB = (1<<RXEN)|(1<<TXEN); //允许串口发送和接收
UBRR = BAU;
SendChar('>'); //通知PC机,BOOT下载准备就绪
delay(); //延时等待PC机响应
delay();
delay();
delay();
delay();
delay();
delay();
delay();
BootFlag=UDR;
if (BootFlag == '<')
{
SendChar(ChipType);
while (RecChar()!='N');
SendChar(BootSize);
while (RecChar()!='N');
SendChar(BootVer);
while (1)
{
switch (RecChar())
{
case 'W': FlashLoad(); break;
case 'E': {
SendChar('E'); //通知PC机,进入运用程序区
while (RecChar()!='N');
ExecCode();
} break;
default : break;
}
}
}
SendChar('E'); //通知PC机,进入运用程序区
//while (RecChar()!='N');
delay();
delay();
delay();
delay();
ExecCode();
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -