AVR_M8 BootLoader应用范例

发布者:beta13最新更新时间:2016-08-16 来源: eefocus关键字:AVR  BootLoader 手机看文章 扫描二维码
随时随地手机看文章
//meg8 bootloader 
//BOOTSZ1 BOOTSZ0=00 
//meg8 bootloader 
//BOOTSZ1 BOOTSZ0=00 
#include   
#define SPM_PAGESIZE 64              //M8的一个Flash页为64字节(32字)  

#define BAUD 38400                //波特率采用38400bps  
#define CRYSTAL 8000000            //系统时钟8MHz  
//计算和定义M128的波特率设置参数  
#define BAUD_SETTING (unsigned char)((unsigned long)CRYSTAL/(16*(unsigned long)BAUD)-1)  
#define BAUD_H (unsigned char)(BAUD_SETTING>>8)  
#define BAUD_L (unsigned char)BAUD_SETTING  

#define DATA_BUFFER_SIZE 128        //定义接收缓冲区长度  
//定义Xmoden控制字符  
#define XMODEM_NUL 0x00  
#define XMODEM_SOH 0x01  
#define XMODEM_STX 0x02  
#define XMODEM_EOT 0x04  
#define XMODEM_ACK 0x06  
#define XMODEM_NAK 0x15  
#define XMODEM_CAN 0x18  
#define XMODEM_EOF 0x1A  
#define XMODEM_RECIEVING_WAIT_CHAR 'C'  
//定义全局变量  
const char startupString[]="Type 'd' download, Others run app.\n\r\0";  
const char loadString[]="download over\n\r\0";  
char data[DATA_BUFFER_SIZE];  
unsigned int address = 0;  
//擦除(code=0x03)和写入(code=0x05)一个Flash页  
void boot_page_ew(unsigned int p_address,char code)  
{  
    asm("mov r30,r16\n"  
        "mov r31,r17\n"  
      //  "out 0x3b,r18\n");      
     );       //将页地址放入Z寄存器和RAMPZ的Bit0中  
    SPMCR = 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中为一个指令字  
    SPMCR = 0x01;  
    asm("spm\n");  
}  
//等待一个Flash页的写完成  
void wait_page_rw_ok(void)  
{  
      while(SPMCR & 0x40)  
     {  
         while(SPMCR & 0x01);  
         SPMCR = 0x11;  
         asm("spm\n");  
     }  
}  
//更新一个Flash页的完整处理  
void write_two_page(void)  
{  
   //128字节分两页 
    int i;  
    boot_page_ew(address,0x03);                    //擦除一个Flash页  
    wait_page_rw_ok();                            //等待擦除完成  
    for(i=0;i     {  
        boot_page_fill(i, data[i]+(data[i+1]<<8));  
    }  
    boot_page_ew(address,0x05);                    //将缓冲页数据写入一个Flash页  
    wait_page_rw_ok();                            //等待写入完成  
    
   //写第2页 
   address += SPM_PAGESIZE;    //Flash页加1  
    boot_page_ew(address,0x03);                    //擦除一个Flash页  
    wait_page_rw_ok();                            //等待擦除完成  
    for(i=0;i     {  
        boot_page_fill(i, data[SPM_PAGESIZE+i]+(data[SPM_PAGESIZE+i+1]<<8));  
    }  
    
    boot_page_ew(address,0x05);                    //将缓冲页数据写入一个Flash页  
    wait_page_rw_ok();                            //等待写入完成  
    
}          
//从RS232发送一个字节  
void uart_putchar(char c)  
{  
    while(!(UCSRA & 0x20));  
    UDR = c;  
}  
//从RS232接收一个字节  
int uart_getchar(void)  
{  
    unsigned char status,res;  
    if(!(UCSRA & 0x80)) return -1;        //no data to be received  
    status = UCSRA;  
    res = UDR;  
    if (status & 0x1c) return -1;        // If error, return -1  
    return res;  
}  
//等待从RS232接收一个有效的字节  
char uart_waitchar(void)  
{  
    int c;  
    while((c=uart_getchar())==-1);  
    return (char)c;  
}  
//计算CRC  
int calcrc(char *ptr, int count)  
{  
    int crc = 0;  
    char i;  
      
    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处执行应用程序  
void quit(void)  
{  
     uart_putchar('O');uart_putchar('K');  
     uart_putchar(0x0d);uart_putchar(0x0a);  
    uart_putchar(0x0d);uart_putchar(0x0a);  
     while(!(UCSRA & 0x20));            //等待结束提示信息回送完成  
     MCUCR = 0x01;  
    MCUCR = 0x00;                    //将中断向量表迁移到应用程序区头部  
   //  RAMPZ = 0x00;                    //RAMPZ清零初始化  
     asm("jmp 0x0000\n");                //跳转到Flash的0x0000处,执行用户的应用程序  
}  
//主程序  
void main(void)  
{  
    int i = 0;  
    unsigned char timercount = 0;  
    unsigned char packNO = 1;  
    int bufferPoint = 0;  
    unsigned int crc;  
//初始化M128的USART0  
    UBRRH = BAUD_H;      
    UBRRL = BAUD_L;            //Set baud rate  
    UCSRB = 0x18;            //Enable Receiver and Transmitter  
  //  UCSRC = 0x06;            //Set frame format: 8data, 2stop bit  
   UCSRC=0x8e;//8位数据+2位STOP位,m8与m128的URSEL不同 
   //UCSRC=0x86;//8位数据+1位STOP位,m8与m128的URSEL不同 
//初始化M8的T/C2,15ms自动重载  
  OCR2 = 0xEA;   
  TCCR2 = 0x0F;      
//向PC机发送开始提示信息  
    while(startupString[i]!='\0')  
    {  
        uart_putchar(startupString[i]);  
        i++;  
    }  
//3秒种等待PC下发“d”,否则退出Bootloader程序,从0x0000处执行应用程序  
  
   while(1)  
    {  
        if(uart_getchar()== 'd') break;  
        if (TIFR & 0x80)                        //timer2 over flow  
        {  
              if (++timercount > 200) quit();        //200*15ms = 3s  
            TIFR = TIFR|0x80;  
        }  
    }  
    //每秒向PC机发送一个控制字符“C”,等待控制字〈soh〉  
    while(uart_getchar()!=XMODEM_SOH)        //receive the start of Xmodem  
    {  
         if(TIFR & 0x80)                    //timer2 over flow  
        {  
            if(++timercount > 67)                        //wait about 1 second  
            {  
                uart_putchar(XMODEM_RECIEVING_WAIT_CHAR);    //send a "C"  
                timercount=0;  
            }  
            TIFR=TIFR | 0x80;  
        }  
    }  
    //开始接收数据块  
    do  
    {  
        if ((packNO == uart_waitchar()) && (packNO ==(~uart_waitchar())))  
        {    //核对数据块编号正确  
      //SPM_PAGESIZEW 
            for(i=0;i<128;i++)                //接收128个字节数据  
            {  
                data[bufferPoint]= uart_waitchar();  
                bufferPoint++;      
            }  
            crc = (uart_waitchar()<<8);  
            crc += uart_waitchar();            //接收2个字节的CRC效验字  
            if(calcrc(&data[bufferPoint-128],128)==crc)    //CRC校验验证  
            {    //正确接收128个字节数据  
             while(bufferPoint >= SPM_PAGESIZE)  
          //  while(bufferPoint >= 64) //(m8每页64字节) 
                {    //正确接受128个字节的数据  
                                       //收到128字节写入2页Flash中  
               write_two_page(); 

                address += SPM_PAGESIZE; 
                    bufferPoint = 0;  
                }      
                uart_putchar(XMODEM_ACK);        //正确收到一个数据块  
                packNO++;                        //数据块编号加1  
            }  
            else  
            {  
                uart_putchar(XMODEM_NAK);        //要求重发数据块  
            }  
        }  
        else  
        {  
            uart_putchar(XMODEM_NAK);                //要求重发数据块  
        }  
    }while(uart_waitchar()!=XMODEM_EOT);                //循环接收,直到全部发完  
    uart_putchar(XMODEM_ACK);                        //通知PC机全部收到  
   i=0; 
    while(loadString[i]!='\0')  
    {  
        uart_putchar(loadString[i]);  
        i++;  
    }  

    quit();                      //退出Bootloader程序,从0x0000处执行应用程序  
    
}  
关键字:AVR  BootLoader 引用地址:AVR_M8 BootLoader应用范例

上一篇:AVR单片机EEPROM的操作
下一篇:AVR单片机atmega16串口中断接收和发送程序

推荐阅读最新更新时间:2024-03-16 15:05

linux 下面avr开发环境的安装
(1)安装开发工具链 yum install avr-* 会安装以下的工具 avr-gcc-4.7.2-1.fc17.i686 avr-libc-1.8.0-2.fc17.noarch avr-binutils-2.23.1-1.fc17.i686 avr-gcc-c++-4.7.2-1.fc17.i686 avr-gdb-7.1-4.fc17.i686 avr-libc-doc-1.8.0-2.fc17.noarch (2)安装(usbkey boot loader) yum install dfu-programmer (3)安装(avrdude) yum install avrdude (4)安装调试工具硬件驱动()
[单片机]
AVR程序里配置熔丝位
初学者对熔丝经常不解,AVR芯片使用熔丝来设定时钟、启动时间、一些功能的使能、BOOT区设定、当然还有最让初学者头疼的保密位,设不好锁了芯片很麻烦。要想使MCU功耗最小也要了解一些位的设定。 1:未编程 0:编程 1.BOD(Brown-out Detection) 掉电检测电路 BODLEVEL(BOD电平选择): 1: 2.7V电平; 0:4.0V电平 BODEN(BOD功能控制): 1:BOD功能禁止;0:BOD功能允许 使用方法:如果BODEN使能(复选框选中)启动掉电检测,则检测电平由BODLEVEL决定。一旦VCC下降到触发电平(2.7v或4.0v)以下,MCU复位;当VCC电平大于触发电平后,经过tTOUT
[单片机]
AVR的SD卡接口程序
/************************************************************/ /* SD Code for M32L */ /* By pasyong */ /* 2006-4 */ /* Base I CC 6.31A */ /************************************************************/ #include iom32v.h #include macros.h #include 1011.h #define uchar unsigned char
[单片机]
Atmel推出全新8位mega168 AVR MCU
加快低功耗应用的开发速度,新一代megaAVR为各级设计人员开发的智能联网设计提供低功耗特性、更多模拟功能和引脚兼容性 全球微控制器(MCU)及触控技术解决方案商Atmel公司 (NASDAQ:ATML)近日在2014慕尼黑国际电子展上推出了新一代8位megaAVR® MCU系列,配备4KB至16KB闪存,并提供新一代增强特性,其中包括更多模拟功能以及面向最新的低功耗消费、工业、白色家电和物联网应用的特性。 自mega168系列于2002年推出以来,Atmel已售出了近10亿件该系列MCU,该系列已成为当今市场上最受欢迎的Atmel 8位AVR MCU。8位megaAVR MCU适用于从爱好者、DIY和创
[单片机]
I2c程序 51系列及 AVR系列
keil c编译 51 #define uchar unsigned char #define uint unsigned int #include reg51.h #include intrins.h sbit Scl=P3^3; //串行时钟 sbit Sda=P3^4; //串行数据 /*发送起始条件*/ void Start(void) /*起始条件*/ { Sda=1; Scl=1; _nop_ (); _nop_ (); _nop_ (); _nop_ (); Sda=0; _nop_ (); _nop_ (); _nop_
[单片机]
51单片机与PIC单片机和AVR单片机的性能对比分析
八位单片机由于内部构造简单,体积小,成本低廉,在一些较简单的控制器中应用很广。即便到了本世纪,在单片机应用中,仍占有相当的份额。由于八位单片机种类繁多,本文仅将常用的几种在性能上作一个简单的比较,供读者在使用时作参考。 1. 51系列 应用最广泛的八位单片机首推Intel的51系列,由于产品硬件结构合理,指令系统规范,加之生产历史“悠久”,有先入为主的优势。世界有许多著名的芯片公司都购买了51芯片的核心专利技术,并在其基础上进行性能上的扩充,使得芯片得到进一步的完善,形成了一个庞大的体系,直到现在仍在不断翻新,把单片机世界炒得沸沸扬扬。有人推测,51芯片可能最终形成事实上的标准MCU芯片。 51系列优点之一是它从内部的硬件
[单片机]
51单片机与PIC单片机和<font color='red'>AVR</font>单片机的性能对比分析
基于AVR单片机的灭火机器人设计与实现
摘要:根据灭火机器人的竞赛规则,给出了灭火机器人的硬件结构设计方案和软件设计流程。所用的机器人处理器为AVR单片机,主要利用红外传感器、光敏传感器对环境进行检测,使机器人在场地中按照预定的方案寻找火源并扑灭。 关键词:灭火机器人;传感器;ATmega32 1 引言 机器人竞赛是近年来迅速开展起来的一种对抗活动,它涉及人工智能、机械、电子、传感器、精密机械等诸多领域。通过竞赛可以培养学生的创新意识、动手能力、团队写作能力等。其中灭火比赛是开展范围最广、影响最大的机器人竞赛项目之一。 比赛规则为模仿生活中消防员灭火,机器人从H点出发,在四个房间内寻找任意摆放的蜡烛,并且设法将其灭掉。比赛场地的墙壁高33cm,材质为木板,颜色为
[工业控制]
基于<font color='red'>AVR</font>单片机的灭火机器人设计与实现
AVR PCF8591 程序
/********************************************************************* 目 的: 建立PCF8591操作库 目标系统: 基于AVR单片机 应用软件: ICCAVR *********************************************************************/ /*01010101010101010101010101010101010101010101010101010101010101010
[单片机]
小广播
添点儿料...
无论热点新闻、行业分析、技术干货……
设计资源 培训 开发板 精华推荐

最新单片机文章
何立民专栏 单片机及嵌入式宝典

北京航空航天大学教授,20余年来致力于单片机与嵌入式系统推广工作。

换一换 更多 相关热搜器件
随便看看
电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved