美文网首页我爱编程
基于AVR-BootLoader,通过霜蝉远程串口可实现单片机的

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

作者: 这一程_2509 | 来源:发表于2018-07-09 20:43 被阅读0次

    最近一直利用业余时间写自己的“基于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

    相关文章

      网友评论

        本文标题:基于AVR-BootLoader,通过霜蝉远程串口可实现单片机的

        本文链接:https://www.haomeiwen.com/subject/vdtxpftx.html