基于AVR-BootLoader,通过霜蝉远程串口可实现单片机的远程升级

最近一直利用业余时间写自己的“基于AVR-BootLoader”,启发是由于一次在ourAVR论坛看到了绍子阳的bootloader,联想到公司在用AVR MCU,但每次升级程序都要花费很大的力气车马劳顿的跑到工程现场,而且很多机器还安装在国外,为了升级一次程序发费了很多的人力物力财力,加上公司的机器目前大部分都配有远程监控系统,所以本人决定写一个具有自有产权的“AVR-BootLoader”。


特别说明:本“AVR-BootLoad”软件代码属上海霜蝉版权所有,在此贡献发布,仅限于个人免费使用不得用于商业用途,本人也不保证代码的严谨性,如在升级中出现任何问题与本人无关,本人已测试过Atmega64A与Atmega128。话不多说了上源代码,网友们和AVR爱好者可以拷贝到CodeWizardAVR V2.03.9编译器下编译。

需要讨论或有遇到BUG的网友们可以联系我:QQ:285247488  mail:shw@scicala.com 

上位机截图:


远程升级DTU:


远程升级连接云平台虚拟串口:


//          关于上海霜蝉-AVR_BootLoade_V1.00

// 1、软件版本V1.00 编译环境CodeWizardAVR V2.03.9 Standard;

// 2、支持本公司常用的三种AVR芯片;

// 3、支持标准Xmodem和扩展Xmodem_1K协议;

// 4、联机握手密码为"00",握手成功手的等待文件超时为1分钟;

// 5、默认复位等待3S退出boot到用户程序或循环运行boot;

// 6、支持1分钟以内的断网续传;

// 7、支持连续10帧以内数据错误的重传;

// 8、支持下载过程中的取消超作;

// 9、支持当收到包时,接收过程中每个字符的超时间隔为 1 秒;

// 10、支持所有的超时及错误事件至少重试 10 次;

// 11、支持数等待超时6S的请求;

// 12、Boot Loader - Size:1024words;

// 13、支持传输速度:38.400KB/S~2.400KB/S;

// 14、支持公司常用最多的三个型号ATMEGA32,64,128。

// 15、支持开门狗自定义开关,自定义时钟频率

/*****************************************************

This program was produced by the

CodeWizardAVR V2.03.9 Standard

Automatic Program Generator

?Copyright 1998-2008 Pavel Haiduc, HP InfoTech s.r.l.

http://www.hpinfotech.com

Project      : AVR_BootLoader

Version     : V1.00

Date         : 2014-7-19

Author      : Sui Hongwei

Company : SCICALA

Comments:

Chip type                   : ATmega64L

Program type             : Boot Loader - Size:1024words

AVR Core Clock frequency: 16.000000 MHz

Memory model            : Small

External RAM size       : 0

Data Stack size           : 1024

*****************************************************/

#include "AVR_boot.h"//头文件包含

//--------------------------------------------------//

//同步密码长度

#define CONNECTCNT         7

//同步密码

uchar KEY_Data[10] = {"SCICALA"};

// Declare your global variables here

//--------------------------------------------------//

//全局变量定义

ucharRX_buff[BUFSIZE];//数据拉收缓存

ucharFrame_State,SOH_Wait_cnt;//帧状态,帧头等待计数

uintTime_cnt,Error_cnt;//超时计数,连续帧错误计数

uintbuffptr,buffptr_old,buffptr_New;//数据缓存指针必须大于1024

ulongFlashAddr;// Flash地址

ucharUpdatedSta;//升级标志

//-----------------------------------------------//

//擦除(code=0x03)和写入(code=0x05)一个Flash页

voidboot_page_ew(ulongp_address,charcode)

{

#asm

    lddr26,y+1;R26LSB

    lddr27,y+2;R27MSB

#endasm

SPM_REG=code;//寄存器SPMCSR中为操作码

#asm

    movr30,r26

    movr31,r27

#endasm

#ifdef  ATMEGA128

    RAMPZ=(p_address>>16);// RAMPZ0 = 1: ELPM/SPM可以访问程序存储器地址$8000 - $FFFF (高64K字节)

#endif

#asm("spm");//对指定Flash页进行擦操作

}

//填充Flash缓冲页中的一个字

voidboot_page_fill(uintA_address,uintdata)

{

#asm

    LDDR30,Y+2;R30LSB

    LDDR31,Y+3;R31MSB

    LDR26,Y

    LDDR27,Y+1

    MOVR0,R26

    MOVR1,R27

    MOVR26,R30

    MOVR27,R31

    #endasm

    SPM_REG=0x01;//寄存器SPMCSR中为操作码

    #asm

    movr30,r26

    movr31,r27

    #endasm

    #asm("spm");//对指定Flash页进行擦操作

}

//等待一个Flash页的写完成

voidwait_page_rw_ok(void)

{

    while(SPM_REG&0x40)

    {

        while(SPM_REG&0x01);

        SPM_REG=0x11;

        #asm("spm");

        while(SPM_REG&0x01);

    }

}

//-----------------------------------------------//

//更新一个Flash页的完整处理

voidwrite_one_page(uchardata[])

{

uinti;

boot_page_ew(FlashAddr,0x03);//擦除一个Flash页

wait_page_rw_ok();//等待擦除完成

for(i=0;i

{

    boot_page_fill(i,(uint)data[i]+(data[i+1]<<8));

    wait_page_rw_ok();

}

boot_page_ew(FlashAddr,0x05);//将缓冲页数据写入一个Flash页

wait_page_rw_ok();//等待写入完成

}

//--------------------------------------------------//

//等待串口数据1S超时自动转为应答

unsignedcharWait1S_UART()

{

uchari=0;

do

{

#if WDGEn

Watchdog_Reset();//喂狗

#endif

if(TIFR&0x10)// OCF1A: T/C1输出比较A匹配标志位

{

TIFR|=0x10;//清除Time1定时器比较匹配标志

i++;

if(i>=4)//等待1S 250ms*4=1S

    {Frame_State=0x06;break;}//帧数据超时转为应答请求重发数据帧

}

if(UCSRAREG(COMPORTNo)&0x80)

{

UCSRAREG(COMPORTNo)|=0x80;//清除接收完成状态

    #if Run_LEDEn

    Run_LED;//运行LED闪烁

    #endif

    i=100;

returnUDRREG(COMPORTNo);//读取UDR0

}

}

while(100!=i);//等待数据||超时退出

}

//***************************************************//

//===================================================//

voidmain(void)

{

ucharpackNO,packNO_old;//包号、包号留存

uintcrc16;//接收CRC缓存

uintli;//帧计数

ucharch,cl;//包号

PORT_Init();//端口初始化

UART_Init();//串口初始化

Time1_Init();//定时器初始化250ms

#if WDGEn

WatchDog_Enable();//打开看门狗(2S)

#else

    WatchDog_Disenable();   //禁止看门狗

#endif

#if Wait_BootTime

Time_cnt=EEPROM_Read(EE_TimeAddr);//读取boot运行时间

#endif

#if SafeUpdated_En

UpdatedSta=EEPROM_Read(EE_SafeAddr);//读取升级成功标志

#endif

#asm("cli")//关总中断

#if Delay_En            //是否延时

for(li=0;li<5000;li++)

{#asm("nop")}

#endif

//-----------------------------------------------//

//等待"握手",否则退出Bootloader程序,从0x0000处执行应用程序

Time_cnt+=WiteTimeCnt;

cl=0;

while(1)

{

if(TIFR&0x10)// OCF1A: T/C1输出比较A匹配标志位

{

    TIFR|=0x10;//清除Time1定时器比较匹配标志

        #if Run_LEDEn

    Run_LED;//运行LED闪烁

        #endif

        Time_cnt--;

    if(Time_cnt==0)//等待握手超时

    {

        #if SafeUpdated_En

        if(UpdatedSta)//上次升级失败

            {while(1);}//复位boot

            else

            #endif

            {quit_boot();}//跳转到用户程序

        }

        if(UCSRAREG(COMPORTNo)&0x80)

        {

    ch=Wait_UART();

            if(ch==KEY_Data[cl])

    {cl++;}

    else

    {cl=0;}

            //WriteCom(ch);         //密码回传

        }

        if(cl==CONNECTCNT)break;

}

    #if WDGEn

    Watchdog_Reset();//喂狗

    #endif

}

//-----------------------------------------------//

//启动Xmodex CRC传数据=字符“C”,等待控制字〈soh〉

Time_cnt=TimeOutCntC;

while(1)

{

if(TIFR&0x10)// OCF1A: T/C1输出比较A匹配标志位

{

    TIFR|=0x10;//清除Time1定时器比较匹配标志

        #if Run_LEDEn

    Run_LED;//运行LED闪烁

        #endif

    Send_UART(XMODEM_RWC);//发送"C"

    Time_cnt--;

    if(Time_cnt==0)//等待文件超时

    {

        #if SafeUpdated_En

        if(UpdatedSta)//上次升级失败

            {while(1);}//复位boot

            else

            #endif

            {quit_boot();}//跳转到用户程序

        }//跳转到用户程序

}

if(UCSRAREG(COMPORTNo)&0x80)//串口有数据

{

    #ifdef  Xmodem

    if(Wait_UART()==XMODEM_SOH)//XMODEM命令开始0x01

        #else   // Xmodem_1K

        if(Wait_UART()==XMODEM_STX)//XMODEM命令开始0x02

        #endif

        break;

}

    #if WDGEn

    Watchdog_Reset();//喂狗

    #endif

}

//-----------------------------------------------//

//开始接收数据进入Xmodem协议接收文件

//帧的两个时间很重要:连续出错10次*最大帧请求间隔6S

//累计请求间隔10*6S=1min

packNO=1;// Xmodem起始为0x01

packNO_old=0;

buffptr=0;

buffptr_old=0;

Error_cnt=0;

FlashAddr=0;

Frame_State=0x01;//第一帧不判断帧头

while(1)

{

switch(Frame_State)//帧状态

{

    case0x00://接受状态帧头与停止信号判断

    {

        ch=XMODEM_NUL;//清除

            if(UCSRAREG(COMPORTNo)&0x80)//串口有数据

            {ch=Wait_UART();}//读取帧头或停止信号

            if(TIFR&0x10)// OCF1A: T/C1输出比较A匹配标志位

            {

            TIFR|=0x10;//清除Time1定时器比较匹配标志

            SOH_Wait_cnt++;//等待计时250ms

                if(SOH_Wait_cnt>=24)//等待帧超时请求数据(6S*10=1min)

                {

                Frame_State=0x06;//要求重发数据块

                    SOH_Wait_cnt=0;//帧请求计时

                    #if Run_LEDEn

    Run_LED;//运行LED闪烁

                    #endif

                }

            }

            //------------------------------

        if(ch==XMODEM_EOT)//发送结束

            {

            for(li=(buffptr_New-128);li

    {

    if((RX_buff[li++])!=0xff)break;//填充帧判断争强EOT抗干扰能力FF CF

                    {

                    if((RX_buff[li++])!=0xcf)break;//填充帧判断争强EOT抗干扰能力FF CF

    }

                }

                if(li==buffptr_New)

                {Send_UART(XMODEM_ACK);//最后一帧应答完成

                Frame_State=0x0ff;//转为退出boot

                }

                else

                {

                Frame_State=0x06;//要求重发数据块

                    SOH_Wait_cnt=0;//帧请求计时

                }

            }

            #ifdef  Xmodem

            if(ch==XMODEM_SOH)// Xmodem帧头判断

            #else   // Xmodem_1K

            if(ch==XMODEM_STX)// Xmodem_1K帧头判断

            #endif

            {

            Frame_State=0x01;//转为包号检查

                SOH_Wait_cnt=0;//清除帧头等待计时

            }

    }

    break;

    case0x01://包序号校验

    {

            ch=Wait1S_UART();//获取包序号

cl=~Wait1S_UART();

    if(ch==cl)//包号对比

            {Frame_State=0x02;

                packNO=ch;//正确保留包号

            }

            else

            {Frame_State=0x06;}//重发应答ANK

    }

    break;

    case0x02://进入二级CRC校验

    {

        for(li=0;li

    {

    RX_buff[buffptr++]=Wait1S_UART();//接收数据

                //帧数据接收超时1S退出for询环,再接收2个数据或超时1S+2S转为应答

                if(Frame_State==0x06)break;

    }

    crc16=Wait1S_UART();

            crc16=crc16<<8;

    crc16+=Wait1S_UART();//接收2个字节的CRC效验字

    if(CRC16_Word(&RX_buff[buffptr-BUFFER_SIZE],BUFFER_SIZE)==crc16)// CRC校验验证

    {

            if(packNO==packNO_old)//接收相同包不写flash

            {Frame_State=0x05;//正常应答ACK

                    buffptr=buffptr_old;

            }

                else

                {Frame_State=0x03;//正确应答

                    buffptr_New=buffptr;//记录当前数据指针

                }

            }

            else

            {Frame_State=0x06;//应答NAK

                buffptr=buffptr_old;//去掉错误数据的指针

            }

    }

    break;

    case0x03://校验通过,执行写入

    {

        if(FlashAddr

    {

                #if BUFFER_SIZE < SPM_PAGESIZE  // ---

                if(buffptr>=SPM_PAGESIZE)//缓冲区满,写入数据;否则继续接收

        {//接收多个帧,写入一页

        write_one_page(&RX_buff[0]);//写入缓冲区内容到Flash中

        FlashAddr+=SPM_PAGESIZE;//修改Flash页地址

        buffptr=0;

        }

                #else     //----------------------

                while(buffptr>0)//接收一帧,写入多个页面

        {

        write_one_page(&RX_buff[BUFSIZE-buffptr]);

        FlashAddr+=SPM_PAGESIZE;//修改Flash页地址

        buffptr-=SPM_PAGESIZE;

        }

                #endif//-----------------------

            }

    else//超过BootStart,忽略写操作

    {buffptr=0;}//重置接收指针

    Frame_State=0x04;

    }

    break;

    case0x04://读取写入的Flash内容并和下载的缓冲区比较

    {

        Frame_State=0x05;//转为应答状态

            buffptr_old=buffptr;//写入正常才记录数据指针

        }

    break;

    case0x05://正确应答ACK

    {

            packNO_old=packNO;//接收完整一帧保留本次包号

            Send_UART(XMODEM_ACK);//认可应答

            //WriteCom(packNO);         //测试

            //WriteCom(FlashAddr);      //测试

            //WriteCom(FlashAddr>>8);   //测试

            Error_cnt=0;//清除连续错误计数

            Frame_State=0x00;//转为帧接收(请求)状态

    }

    break;

    case0x06://错误=重发应答ANK

    {

            Send_UART(XMODEM_NAK);//要求重发数据块

    Error_cnt++;//连续错误计数

            Frame_State=0x00;//转为接收状态

    }

    break;

    default://升级完成退出处理

    {

        #if SafeUpdated_En

        EEPROM_Write(EE_SafeAddr,0);//写升级成功标志0

        #endif

        quit_boot();//退出Bootloader

        }

    break;

}// switch End

    if(Error_cnt>10)//连续出错10次退出升级(复位)

    {

        Send_UART(XMODEM_CAN);//撤销传送(无条件停止)

        #if SafeUpdated_En

        EEPROM_Write(EE_SafeAddr,1);//写升级失败标志1

        #endif

    while(1);//没有升级完成重新开始

    }

    #if WDGEn

    Watchdog_Reset();//喂狗

    #endif

}// while end

//-------------------------------------------------//

}// main end

//-----------------------------------------------//

#include "AVR_boot.h"//头文件包含

//-----------------------------------------------//

//----------初始化-------------------------------//

//输出端口初始化

voidPORT_Init()

{

//上电默认全为输入口

//输出口设置

#if Run_LEDEn

DDRREG(LEDPORT)|=(1<

#endif

}

//-----------------------------------------------//

//串口初始化

voidUART_Init()

{

#if RS485_En

DDRREG(RS485PORT)|=(1<

RX485DE_RX;//默认为接收

#endif

UCSRAREG(COMPORTNo)=0x00;

UCSRBREG(COMPORTNo)=0x18;// Enable Receiver and Transmitter

UCSRCREG(COMPORTNo)=0x0E;// Set frame. format: 8data, 2stop bit

//通信速率

UBRRHREG(COMPORTNo)=BAUD_H;// 0X00

UBRRLREG(COMPORTNo)=BAUD_L;// Set baud rate   16M 9600 0x0067

}

// 250ms定时器设置Time1

//-----------------------------------------------//

//使用定时器1:1024分频,CTC模式4,产生以毫秒为单位的时间

voidTime1_Init()

{

// Timer/Counter 1 initialization

// Clock source: System Clock

// Clock value: 16MHz

TCCR1A=0x00;// CTC4

TCCR1B=0x08;// CTC4

TCCR1B|=0x03;// clkI/O/64 (来自预分频器) 16M=4us

OCR1A=T1_TCNT;// 250MS

}

//-----------------------------------------------//

//看门狗初始化函数2s

voidWatchDog_Enable(void)

{

// Watchdog Timer initialization

// Watchdog Timer Prescaler: OSC/2048k

MCUCSR=0x00;//控制与状态寄存器

WDTCR=0x1F;//看门狗使能500ms(D)1.0S(E) 2.0S(F)

WDTCR=0x0F;

}

//禁止看门狗

voidWatchDog_Disenable(void)//禁止看门狗

{

MCUCSR=0x00;//控制与状态寄存器

WDTCR=0b00011111;//看门狗使能位修改使能(B4=1) 2.0S(F)

WDTCR=0b00000111;//禁止看门狗2.0S(7)

}

//喂狗

voidWatchdog_Reset(void)

{#asm("wdr")}//喂狗

//-----------------------------------------------//

//-------------子函数----------------------------//

//写入数据到串口

voidSend_UART(unsignedchardat)

{

uchari;

#if RS485_En

RX485DE_TX;//使能RS485发送

#endif

UDRREG(COMPORTNo)=dat;// UDR0

//等待数据发送完成

while(!(UCSRAREG(COMPORTNo)&0x40));//等待数据发送完成Bit 6 – TXC: USART发送结束

UCSRAREG(COMPORTNo)|=0x40;//清除发送完成状态

#if RS485_En

RX485DE_RX;//使能RS485接收

#endif

}

//-----------------------------------------------//

//等待串口数据(注意是”死等“)

unsignedcharWait_UART()

{

while(!(UCSRAREG(COMPORTNo)&0x80));//等等数据到来Bit 7 – RXC: USART接收结束

UCSRAREG(COMPORTNo)|=0x80;//清除接收完成状态

#if Run_LEDEn

Run_LED;//运行LED闪烁

#endif

returnUDRREG(COMPORTNo);

}

//-----------------------------------------------//

//计算CRC

intCRC16_Word(char*ptr,intcount)

{

intcrc=0;

chari;

while(--count>=0)

{

    crc=crc^(int)*ptr++<<8;

    i=8;

    do

    {

    if(crc&0x8000)

        crc=crc<<1^0x1021;

    else

        crc=crc<<1;

    }while(--i);

}

return(crc);

}

//-----------------------------------------------//

//退出Bootloader程序,从0x0000处执行应用程序

voidquit_boot(void)

{

    MCUCR=0x00;//当IVSEL为"0“时,中断向量位于Flash存储器的起始地址;

    #ifdef ATMEGA128

    RAMPZ=0x00;//0: ELPM/SPM可以访问程序存储器地址$0000 - $7FFF (低64K字节)

    #endif

    #asm("jmp 0x0000")//跳转到Flash的0x0000处,执行用户的应用程序

}

//-----------------------------------------------//

//读EEPROM一个字节

ucharEEPROM_Read(uintAddr)// EEPROM读1个字节操作0

{

while(EECR&0x02);//等待上一次写操作结束

EEAR=Addr;//设置地址寄存器

EECR|=0x01;//设置EERE以启动读操作b0

return(EEDR);//自数据寄存器返回数据

}

//写EEPROM一个字节

voidEEPROM_Write(uintAddr,charData)// EEPROM写1个字节操作

{

EEAR=Addr;//设置地址寄存器

EEDR=Data;//设置数据寄存器

//    #asm("cli")                     // EEMPE置1,EEPE1,这两步操作中间不能超过4个时钟周期

EECR|=0x04;//置位EEMWE            b2

EECR|=0x02;//置位EEWE以启动写操作b1

//#asm("sei")

}

//-----------------------------------------------//

//-------------------------------------------------------//

#ifndef _AVR_BOOT_H_

#define _AVR_BOOT_H_      1

//配置文件包含

#include "Config.h"

//------------------------------------------------------//

#ifdef    ATMEGA32

#include 

#endif

#ifdef  ATMEGA64

#include 

#endif

#ifdef  ATMEGA128

#include 

#endif

//---------------------------------------------------//

typedefsignedcharschar;

typedefsignedintsint;

typedefsignedlongslong;

typedefunsignedcharuchar;

typedefunsignedintuint;

typedefunsignedlongulong;

//--------------------------------------------------//

//函数申明

voidUART_Init();

voidPORT_Init();

voidTime1_Init();

voidSend_UART(unsignedchardat);

unsignedcharWait_UART();

unsignedcharWait1S_UART();

voidWatchDog_Disenable(void);

voidquit_boot(void);

intCRC16_Word(char*ptr,intcount);

voidwrite_one_page(uchardata[]);

voidWatchDog_Enable(void);

voidWatchdog_Reset(void);

ucharEEPROM_Read(uintAddr);

voidEEPROM_Write(uintAddr,charData);

//--------------------------------------------------//

//内部使用的宏定义

#define CONCAT(a, b)       a ## b

#define CONCAT3(a, b, c)   a ## b ## c

//端口以及位定义

#define PORTREG(No)        CONCAT(PORT, No)

#define PINREG(No)         CONCAT(PIN, No)

#define DDRREG(No)         CONCAT(DDR, No)

#define UDRREG(No)         CONCAT(UDR, No)

//串口初始化需要寄存器

#define UCSRAREG(No)       CONCAT3(UCSR, No, A)

#define UCSRBREG(No)       CONCAT3(UCSR, No, B)

#define UCSRCREG(No)       CONCAT3(UCSR, No, C)

#define UBRRHREG(No)       CONCAT3(UBRR, No, H)

#define UBRRLREG(No)       CONCAT3(UBRR, No, L)

//---------------------------------------------------//

//端口定义

#define     RX485DE_RX      PORTREG(RS485PORT)&=~(1 << RS485TXEn);  // SCI接收使能

#define     RX485DE_TX      PORTREG(RS485PORT)|=(1 << RS485TXEn);   // SCI发送使能

#define     Run_LED         PORTREG(LEDPORT)^= (1 << LEDPORTNo);    // boot运行LED

//---------------------------------------------------//

//定义Xmoden控制字符

#define XMODEM_NUL          0x00        // null

#define XMODEM_SOH          0x01        // Xmodem数据头

#define XMODEM_STX          0x02        // Xmodem_1K数据头

#define XMODEM_EOT          0x04        //发送结束

#define XMODEM_ACK          0x06        //认可响应

#define XMODEM_NAK          0x15        //不认可响应

#define XMODEM_CAN          0x18        //撤销传送

#define XMODEM_EOF          0x1A        //填充数据包

#define XMODEM_RWC          'C'         // CRC16-128

//-------------------------------------------------------//

#ifdef  Xmodem_1K

#define BUFFER_SIZE         1024

#else  // Xmodem

#define BUFFER_SIZE         128

#endif

//-----------------------------------------------------//

#ifdef  ATMEGA32

#define SPM_PAGESIZE        128         // SPM页大小

#define BootStart           0x3C00*2    //按字节

#define SPM_REG             SPMCR       // SPM寄存器

#endif

#ifdef  ATMEGA64

#define SPM_PAGESIZE        256         // SPM页大小

#define BootStart           0x7C00*2    //按字节

#define SPM_REG             SPMCSR      // SPM寄存器

#endif

#ifdef  ATMEGA128

#define SPM_PAGESIZE        256         // SPM页大小

#define BootStart           0xFC00*2    //按字节

#define SPM_REG             SPMCSR      // SPM寄存器

#endif

//接收缓冲区大小不能小于SPM_PAGESIZE

#if BUFFER_SIZE < SPM_PAGESIZE

#define BUFSIZE SPM_PAGESIZE            // UART数据缓存

#else

#define BUFSIZE BUFFER_SIZE             // UART数据缓存

#endif

//计算和定义波特率设置参数

#define BAUD_SETTING (unsigned char)((unsigned long)CRYSTAL/(16*(unsignedlong)BAUDRATE)-1)

#define BAUD_H ((unsigned char)(BAUD_SETTING>>8))

#define BAUD_L (unsigned char)BAUD_SETTING

//计算T1定时器设置参数

#define T1_TCNT (unsigned int)((unsigned long)CRYSTAL*250/(64*1000));

//--------------------------------------------------------//

#endif// _AVR_BOOT_H_

#ifndef _CONFIG_H_

#define _CONFIG_H_      1

//*********************************************************//

//关于上海霜蝉-AVR_bootV1.00

// 1、软件版本V1.00编译环境CodeWizardAVR V2.03.9 Standard;

// 2、支持本公司常用的三种AVR芯片;

// 3、支持标准Xmodem和扩展Xmodem_1K协议;

// 4、联机握手密码为"00",握手成功手的等待文件超时为1分钟;

// 5、默认复位等待3S退出boot到用户程序或循环运行boot;

// 6、支持1分钟以内的断网续传;

// 7、支持连续10帧以内数据错误的重传;

// 8、支持下载过程中的取消超作;

// 9、支持当收到包时,接收过程中每个字符的超时间隔为1秒;

// 10、支持所有的超时及错误事件至少重试10次;

// 11、支持数等待超时6S的请求;

// 12、Boot Loader - Size:1024words;

// 13、支持传输速度:38.400KB/S~2.400KB/S;

// 14、支持上海霜蝉常用最多的三个型号ATMEGA32,64,128。

// 15、支持开门狗自定义开关,自定义时钟频率

//*********************************************************//

//注意:修改编译器配置(char to int;char is unsigned)

//注意:填充数据必须大于两包(>=256)

//定义芯片型号

//芯片型号选择

//#define   ATMEGA32

#define ATMEGA64                //已测试Atmgea64L

//#define   ATMEGA128

//协议类型选择:Xmodem或Xmodem_1K

#define Xmodem             // Xmodex 128(CRC16)

//#define Xmodem_1K            // Xmodem 1024(CRC16)

//-----------------------------------------------//

//系统时钟MHz

#ifndef CRYSTAL

#define CRYSTAL            16000000         // 16M

#endif

//波特率38400~2400

#define BAUDRATE           9600

//等待密码的超时时间= WiteTimeCnt * 250ms

//超时次数

#define WiteTimeCnt        10               // 10=2.5s

//用户设置boot驻留等待握手时间(1=250ms)+2.5S(WiteTimeCnt)

#define Wait_BootTime      40               // (1=250ms)+2.5S

//等待文件的超时时间= TimeOutCntC * 250ms

//发送'C'的最大次数

#define TimeOutCntC        40               // 40=1min

//串口号(ATMEA32串口号为空)

#define COMPORTNo          0                // UART0

//看门狗使能

#define WDGEn              1                //使用看门狗

//使用485模式

#define RS485_En           1                //使用485使能脚

// 485控制端口和引脚

#define RS485PORT          E                // PORTE

#define RS485TXEn          2                // PORTE2

//使用LED指示状态

#define Run_LEDEn          1                //使能boot运行LED指示

// LED控制端口和引脚

#define LEDPORT            B                // PORTB

#define LEDPORTNo          6                // PORTB6

//延时用于解决串口数据出错

#define Delay_En           0

//用户设置boot驻留等待握手时间(1=250ms)+2.5S(WiteTimeCnt)

//使此功能需要设置EEPROM

#define Wait_BootTime      40               // (40*250ms)+2.5S

#define EE_TimeAddr         0               //使用EEPROM占用1个字节

//安全升级(升级不成功不进入用户区)

//使此功能需要设置EEPROM

#define SafeUpdated_En     1

#define EE_SafeAddr        1               //使用EEPROM占用1个字节

//-----------------------------------------------//

#endif// _CONFIG_H_

//End of file: bootcfg.h

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,117评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,328评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,839评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,007评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,384评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,629评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,880评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,593评论 0 198
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,313评论 1 243
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,575评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,066评论 1 260
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,392评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,052评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,082评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,844评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,662评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,575评论 2 270

推荐阅读更多精彩内容