搜索
bottom↓
回复: 37

实战ATMEGA16 使用在线升级Bootloader(主页HJJourAVR朋友的),已成功,稍有改动和补充

[复制链接]

出0入0汤圆

发表于 2007-1-8 00:51:27 | 显示全部楼层 |阅读模式
[硬件]

使用马老师的实验板(在armok处邮购的),ATMEGA16, 内部8M RC振荡器



[软件]

   AVR Studio ver 4.12 sp4   

+  winavr20060412(1.4.4)

+  windows xp sp2



[更新]

在HJJourAVR的BOOTLOADER基础上,改了熔丝位BOOTRST=1,波特率降为 9600bps, 选用内部8M RC振荡器,代码优化选-0s



[注意]

1. 对于初学者,最容易忽视的就是改makefile,一定要填加

LDFLAGS += -Wl,--section-start=.text=0x3800

这一句,为此不能直接使用AVR Studio中的makefile,而应该将AVR Studio自动生成的makefile复制一份,改名为makefile1 (也可以是别的名), 在选项中选Use External Makefile,然后选makefile1

2. 升级的程序,不能是HEX文件,因为HEX文件是内含格式且每行信息可以不等长的。对于这个BOOTLOADER升级程序,只能接收原始的二进制文件信息并覆写到相应的flash区内,因此只能使用BIN格式。将HEX转为BIN有一个小软件,在附件里有,转换过程的参数都选默认的(直接敲回车)。

3. 编译的优化选项如果选-00,可能会提示越界,即超出了ATMEGA16本身的flash范围,为此将优化选项选为-0s(最大代码优化), 实际编译,无越界提示,且可以正常运行。

4. 之所以将波特率降为9600bps(原为115200bps),是考虑到大多数的在线IAP远程升级功能,都不是很在意速度,而更重视可靠性。这就象我们刷新电脑主板的BIOS,宁愿花10分钟慢慢升级,也不愿花1分钟升级失败再抱着主板去电脑城修理。

以上有不当,请朋友们指教。



[源程序]

源程序如下,仅用于学习和讨论。

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

****      AVR BootLoader应用范例              ***

****                                               ***

**** 作者:  HJJourAVR                        ***

**** 编译器:WINAVR20050214                   ***

****                                         ***

****          www.OurAVR.com         2005.10.17          ***

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

//程序参考 马潮老师的M128 Boot_load应用的实例,ICCAVR版本

//Stephen更改:9600bps, MEGA16, 8M INTERNAL RC,BOOTSZ1=0, BOOTSZ0=0, BOOTRST=1

/*

本程序简单的示范了AVR ATMEGA16的IAP应用,实现智能升级

                Boot Loader

                XMODEM-CRC传输协议

                CRC16校验

               

出于简化程序考虑,各种数据没有对外输出,学习时建议使用JTAG ICE硬件仿真器。

熔丝位设置

BOOTSZ1=0

BOOTSZ0=0  Boot区为1K字(2K字节)大小。

BOOTRST=0  复位向量位于Boot区。//Stephen: 设BOOTRST=1,允许启动



makefile中的程序基地址偏移

LDFLAGS += -Wl,--section-start=.text=0x3800   //0x3800字节=0x1C00字



移植程序时,可根据实际大小设定Boot区,但要注意更改makefile和更改BootAdd常数,以及页写的大小分配;



采用115200bps的通讯速率,升级14KB程序需要耗时约5秒[上位机是WINDOWS 2000的超级终端]



疑问:

  1 用HEX文件烧录工作正常,但elf仿真有问题。

    用AVRstudio仿真elf(熔丝设定BOOTRST=0,程序基地址偏移=0x3800)时,所有SRAM变量丢失初始化,

          表现为put_s()的都是乱码或不可见字符。

    但如果改成应用程序(熔丝设定BOOTRST=1,没有程序基地址偏移),则put_s()可以正常显示

  

  2 XMODEM的结束应答(EOT/CAN)后需加 delay_ms(500)的延时(程序优化,统一写在跳转到用户程序前),

    否则在下面的情况将会无法正常结束XMODEM的传输,但其实程序已经升级成功

    特殊情况:用户程序里面使用了串口,而且波特率较低(如9600bps)且开机即发送大量数据



*/



#include <avr/io.h>

#include <util/delay.h>

//时钟定为外部晶体7.3728MHz,F_CPU=7372800 使用USART,115200bps

#include <avr/boot.h>

/*

boot_page_erase ( address )

        擦除FLASH 指定页,其中address 是以字节为单位的FLASH 地址

boot_page_fill ( address, data )

        填充BootLoader 缓冲页,address 为以字节为单位的缓冲页地址(对mega16 :0~128),

        而data 是长度为两个字节的字数据,因此调用前address 的增量应为2。

        此时data 的高字节写入到高地址,低字节写入到低地址。

boot_page_write ( address )

        boot_page_write 执行一次的SPM 指令,将缓冲页数据写入到FLASH 指定页。

boot_rww_enable ( )

        RWW 区读使能

       

        根据自编程的同时是否允许读FLASH 存储器,FLASH 存储器可分为两种类型:

可同时读写区( RWW Read-While-Write ) 和 非同时读写区( NRWW NotRead-While-Write)。

对于MEGA16 RWW 为前14K 字节 NRWW 为后2K 字节。

引导加载程序对RWW 区编程时MCU 仍可以从NRWW 区读取指令并执行,而对NRWW 区编程时MCU 处于挂起暂停状态。

在对RWW 区自编程(页写入或页擦除)时,由硬件锁定RWW 区 , RWW 区的读操作被禁止

在对RWW 区的编程结束后应当调用boot_rww_enable() 使RWW 区开放。

*/

#include <util/crc16.h>

/*

GCCAVR内置函数,可以不用头痛CRC16了

关于CRC的详细说明,可以查看一下网站:

http://www.nongnu.org/avr-libc/user-manual/group__avr__crc.html

函数原形

static __inline__ uint16_t _crc16_update(uint16_t __crc, uint8_t __data);

        多项式Polynomial: x^16 + x^15 + x^2 + 1 (0xa001)

        crc初始值Initial value: 0xffff

    通常用于磁盘控制器(disk-drive controllers)

static __inline__ uint16_t _crc_xmodem_update(uint16_t __crc, uint8_t __data);

        多项式Polynomial: x^16 + x^12 + x^5 + 1 (0x1021)

        crc初始值Initial value: 0x0

        专用于XMODEM通讯协议,等效于C写的

        uint16_t crc_xmodem_update (uint16_t crc, uint8_t data)

    {

        int i;

        crc = crc ^ ((uint16_t)data << 8);

        for (i=0; i<8; i++)

        {

            if (crc & 0x8000)

                crc = (crc << 1) ^ 0x1021;

            else

                crc <<= 1;

        }

        return crc;

    }

static __inline__ uint16_t _crc_ccitt_update (uint16_t __crc, uint8_t __data)

        多项式Polynomial: x^16 + x^12 + x^5 + 1 (0x8408)

        crc初始值Initial value: 0xffff

    专用于PPP和IrDA通讯协议

*/



//管脚定义

#define PIN_RXD                                0        //PD0

#define PIN_TXD                                1        //PD1



//常数定义

#define SPM_PAGESIZE                 128                                //M16的一个Flash页为128字节(64字)

#define DATA_BUFFER_SIZE         SPM_PAGESIZE        //定义接收缓冲区长度

#define BAUDRATE                        9600        //115200                        //波特率采用115200bps

//#define F_CPU                                7372800                        //系统时钟7.3728MHz



//定义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_WAIT_CHAR         'C'



//定义全局变量

struct str_XMODEM

{

    unsigned char SOH;                                                //起始字节

    unsigned char BlockNo;                                        //数据块编号

    unsigned char nBlockNo;                                        //数据块编号反码

    unsigned char Xdata[128];                                //数据128字节

    unsigned char CRC16hi;                                        //CRC16校验数据高位

    unsigned char CRC16lo;                                        //CRC16校验数据低位

}

strXMODEM;                                                                        //XMODEM的接收数据结构



unsigned long FlashAddress;                                        //FLASH地址

#define  BootAdd                         0x3800                        //Boot区的首地址(应用区的最高地址)

/*        GCC里面地址使用32位长度,适应所有AVR的容量*/



unsigned char BlockCount;                                        //数据块累计(仅8位,无须考虑溢出)



unsigned char STATUS;                                                //运行状态

#define ST_WAIT_START                 0x00                        //等待启动

#define ST_BLOCK_OK                 0x01                        //接收一个数据块成功

#define ST_BLOCK_FAIL                 0x02                        //接收一个数据块失败

#define ST_OK                                 0x03                        //完成





//长延时 max 65536ms

void delay_ms(unsigned int t)

{

    while(t--)

    {

        _delay_ms(1);

    }

}



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

void write_one_page(void)

{

    unsigned char i;

    unsigned char *buf;

    unsigned int  w;

    boot_page_erase(FlashAddress);                                //擦除一个Flash页

    boot_spm_busy_wait();                                                //等待页擦除完成

    buf=&strXMODEM.Xdata[0];

    for(i=0;i<SPM_PAGESIZE;i+=2)                                //将数据填入Flash缓冲页中

    {

        w =*buf++;

        w+=(*buf++)<<8;

        //boot_page_fill(FlashAddress+i, w);        //原句

        boot_page_fill(i, w);                                        //只是低7位(128字节/页)有效

    }

    boot_page_write(FlashAddress);                                //将缓冲页数据写入一个Flash页

    boot_spm_busy_wait();                                                //等待页编程完成

}



//发送采用查询方式

void put_c(unsigned char c) //发送采用查询方式

{

    loop_until_bit_is_set(UCSRA,UDRE);

    UDR=c;

}



//发送字符串

void put_s(unsigned char *ptr)

{

    while (*ptr)

    {

        put_c(*ptr++);

    }

    put_c(0x0D);

    put_c(0x0A);  //结尾发送回车换行

}





//接收指定字节数据(带超时控制,Timer0的1ms时基)

//        *ptr                数据缓冲区

//        len                        数据长度

//        timeout                超时设定,最长65.536S

//  返回值                已接收字节数目

unsigned char get_data(unsigned char *ptr,unsigned char len,unsigned int timeout)

{

    unsigned count=0;

    do

    {

        if (UCSRA & (1<<RXC))

        {

            *ptr++=UDR;                                //如果接收到数据,读出

            count++;

            if (count>=len)

            {

                break;                                //够了?退出

            }

        }

        if(TIFR & (1<<OCF0))                //T0溢出 1ms

        {

            TIFR|=(1<<OCF0);                //清除标志位

            timeout--;                                //倒计时

        }

    }

    while (timeout);

    return count;

}



//计算CRC16

unsigned int calcrc(unsigned char *ptr, unsigned char count)

{

    unsigned int crc = 0;

    while (count--)

    {

        crc =_crc_xmodem_update(crc,*ptr++);

    }

    return crc;

}



//主程序

//int main() __attribute__((section(".stephen_bootloader"))); //stephen_bootloader

int main()

{

    unsigned char c;

    unsigned char i;

    unsigned int crc;

//考虑到BootLoader可能由应用程序中跳转过来,所以所用到的模块需要全面初始化

    DDRA=0x00;

    DDRB=0x00;

    DDRC=0x00;

    PORTA=0xFF;                                                                        //不用的管脚使能内部上拉电阻。

    PORTB=0xFF;

    PORTC=0xFF;

    PORTD=0xFF;

    DDRD=(1<<PIN_TXD);                                                        //串口的输出

    GICR = (1<<IVCE);

    GICR = (0<<IVCE)|(1<<IVSEL);                                //将中断向量表迁移到Boot区头部

asm volatile("cli": : );                                                //关全局中断

    //这个BootLoader没有使用中断。



    //初始化USART 115200 8, n,1  PC上位机软件(超级终端)也要设成同样的设置才能通讯

    UCSRC = (1<<URSEL)|(1<<UCSZ1)|(1<<UCSZ0);        //异步,8位数据,无奇偶校验,一个停止位,无倍速

    UBRRL = (F_CPU/BAUDRATE/16-1)%256;                        //设定波特率

    UBRRH = (F_CPU/BAUDRATE/16-1)/256;

    UCSRA = 0x00;

    UCSRB = (1<<RXEN)|(1<<TXEN);                                //使能接收,使能发送

    //初始化T/C0,CTC模式,256分频,1ms自动重载

    OCR0 = 28;

    TCCR0 = (1<<WGM01)|(1<<CS02)|(0<<CS01)|(0<<CS00);

    //CTC模式下,溢出标志是输出比较匹配OCF0,对应的中断是输出比较匹配中断;



    //向PC机发送开始提示信息

    put_s("************************************************************");

    //put_s(" ");

    put_s("IC ATMega16 Firmware 智能升级引导程序(Bootloader)VER20070107");

    put_s("     使用Windows2000/xp 超级终端 串口发送 9600bps,8-N-1     ");

    put_s("如需更新用户程序,请在3秒钟内按下[d]键,否则3秒后运行用户程序 ");

        put_s(">");



    //3秒种等待PC下发“d”,否则退出Bootloader程序,从0x0000处执行应用程序

    c=0;

    get_data(&c,1,3000);                                                //限时3秒,接收一个数据

    if ((c=='d')||(c=='D'))

    {

        STATUS=ST_WAIT_START;                                        //并且数据='d'或'D',进入XMODEM

        put_s("请选择BIN文件,使用XMODEM协议传输,最大14KB");

    }

    else

    {

        STATUS=ST_OK;                                                        //退出Bootloader程序

    }



    //进入XMODEM模式

    FlashAddress=0x0000;

    BlockCount=0x01;

    while(STATUS!=ST_OK)                                                //循环接收,直到全部发完

    {

        if (STATUS==ST_WAIT_START)

        {//XMODEM未启动

            put_c(XMODEM_WAIT_CHAR);                        //发送请求XMODEM_WAIT_CHAR

        }

        i=get_data(&strXMODEM.SOH,133,1000);        //限时1秒,接收133字节数据

        if(i)

        {

            //分析数据包的第一个数据 SOH/EOT/CAN

            switch(strXMODEM.SOH)

            {

            case XMODEM_SOH:                                        //收到开始符SOH

                if (i>=133)

                {

                    STATUS=ST_BLOCK_OK;

                }

                else

                {

                    STATUS=ST_BLOCK_FAIL;                //如果数据不足,要求重发当前数据块

                    put_c(XMODEM_NAK);

                }

                break;

            case XMODEM_EOT:                                        //收到结束符EOT

                put_c(XMODEM_ACK);                                //通知PC机全部收到

                STATUS=ST_OK;

                                put_s("  用户程序升级成功!");

                break;

            case XMODEM_CAN:                                        //收到取消符CAN

                put_c(XMODEM_ACK);                                //回应PC机

                STATUS=ST_OK;

                                put_s("警告:用户取消升级,用户程序可能不完整");

                break;

            default:                                                        //起始字节错误

                put_c(XMODEM_NAK);                                //要求重发当前数据块

                STATUS=ST_BLOCK_FAIL;

                break;

            }

        }

        if (STATUS==ST_BLOCK_OK)                                //接收133字节OK,且起始字节正确

        {

            if (BlockCount != strXMODEM.BlockNo)//核对数据块编号正确

            {

                put_c(XMODEM_NAK);                                //数据块编号错误,要求重发当前数据块

                continue;

            }

            if (BlockCount !=(unsigned char)(~strXMODEM.nBlockNo))

            {

                put_c(XMODEM_NAK);                                //数据块编号反码错误,要求重发当前数据块

                continue;

            }

            crc=strXMODEM.CRC16hi<<8;

            crc+=strXMODEM.CRC16lo;

            //AVR的16位整数是低位在先,XMODEM的CRC16是高位在先

            if(calcrc(&strXMODEM.Xdata[0],128)!=crc)

            {

                put_c(XMODEM_NAK);                        //CRC错误,要求重发当前数据块

                continue;

            }

            //正确接收128个字节数据,刚好是M16的一页

            if (FlashAddress<(BootAdd-SPM_PAGESIZE))

            {                                                                        //如果地址在应用区内

                write_one_page();                   //将收到128字节写入一页Flash中

                FlashAddress+=SPM_PAGESIZE;         //Flash页加1

            }

            else

            {

                put_c(XMODEM_CAN);                             //程序已满,取消传送

                put_c(XMODEM_CAN);

                put_c(XMODEM_CAN);

                STATUS=ST_OK;

                put_s("  程序已满,取消传送!");

                break;

            }

            put_c(XMODEM_ACK);                                //回应已正确收到一个数据块

            BlockCount++;                                 //数据块累计加1

        }

    }



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

    put_s("退出Bootloader升级程序!");

    delay_ms(500);                                                                //很奇怪,见顶部的说明

    loop_until_bit_is_set(UCSRA,UDRE);                        //等待结束提示信息回送完成

    GICR = (1<<IVCE);

    GICR = (0<<IVCE)|(0<<IVSEL);                                //将中断向量表迁移到应用程序区头部

    /* 无论BootLoader是否使用中断,将中断向量表迁移到应用程序区头部,会增强程序的健壮性*/

    boot_rww_enable ();                                                        //RWW区读允许,否则无法马上执行用户的应用程序

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

}



/*

FLASH程序存储器的编程方法常见的有以下几种:



(1)传统的并行编程方法;

(2)通过串行口进行在线编程ISP(In System Programmability) 对器件或电路甚至整个系统进行现场升级或功能重构;

(3)在运行中,应用程序控制下的应用在线编程IAP (In Applocation Programing) 简单地说就是在某一个section中运行程序,同时对另一个section进行擦除、读取、写入等操作。

ISP方式相对于传统方式有了极大的进步,它不需要将芯片从电路板上卸下就可对芯片进行编程,减少了开发时间,简化了产品制造流程,并大大降低了现场升级的困难。

而IAP方式是对芯片的编程处于应用程序控制之下,对芯片的编程融入在通信系统当中,通过各种接口(UART/SPI/IIC 等)来升级指定目标芯片的软件。



BootLoader 功能介绍

        BootLoader 提供我们通常所说的IAP(In Applicaion Program)功能。

        多数Mega系列单片机具有片内引导程序自编程功能(BootLoader)。

        MCU 通过运行一个常驻FLASH 的BootLoader 程序,利用任何可用的数据接口读取代码后写入自身FLASH存储器中 ,实现自编程目的



基本设计思想(参考了马潮老师的文章)

1.        Boot Loader程序的设计要点

        Boot Loader程序的设计是实现IAP的关键,它必须能过通过一个通信接口,采用某种协议正确的接收数据,再将完整的数据写入到用户程序区中。本例Boot Loader程序的设计要点有:

        1 采用ATmega16的USART口实现与PC之间的简易RS232三线通信;

        2 采用Xmodem通信协议完成与PC机之间的数据交换;

        3 用户程序更新完成后自动转入用户程序执行;

2. Xmodem通信协议

        Xmodem协议是一种使用拨号调制解调器的个人计算机通信中广泛使用的异步文件运输协议。

        这种协议以128字节块的形式传输数据,并且每个块都使用一个校验和过程来进行错误检测。

        如果接收方关于一个块的校验和与它在发送方的校验和相同时,接收方就向发送方发送一个认可字节。

        为了便于读者阅读程序,下面简要说明该协议的主要特点,有关Xmoden的完整的协议请参考其它相关的资料。

        1 Xmodem的控制字符:<soh> 01H、<eot> 04H、<ack> 06H、<nak> 15H、<can> 18H、<eof> 1AH、'c' 43H。

        2 XMODEM有两种校验模式:

                一种是一字节的checksum校验模式,不常用。

                另一种是2字节的CRC16校验模式(X^16 + X^12 + X^5 + 1),纠错率高达99.9984%。

          两种模式的选择由接收端发送的启动控制符来决定,启动发送后不能切换。

                当发送端收到“NAK”控制字符时,它将会开始以checksum校验方式发送数据块。

                当发送端收到“C”控制字符时,它将会开始以CRC校验方式发送数据块。

        3 Xmodem-CRC传输数据块格式:“<soh> <BlockNO> <255-BlockNO> <…128个字节的数据块…> <checksum_crc16>”。

                其中<soh>为起始字节;

                <BlockNO>为数据块编号字节,每次加一;

                <255-BlockNO>是前一字节的反码;

                接下来是长度为128字节的数据块;

                最后的<checksum_crc16>是128字节数据的CRC校验码,长度为2个字节,crc16hi,crc16lo。

        5 接收端收到一个数据块并校验正确时,回送<ack>;接收错误回送<nak>;而回送<can>表示要发送端停止发送。

        6 BlockNO的初值为0x01,每发送一个新的数据块<BlockNO>加1,加到OxFF后下一个数据块的<BlockNO>为零,即8位无符号数。

        7 发送端收到<ack>后,可继续发送下一个数据块(BlockNO+1);而收到<nak>则可再次重发上一个数据块。

        8 发送端发送<eot>表示全部数据发送完成。如果最后需要发送的数据不足128个字节,用<eof>填满一个数据块。



*/



附件:

点击此处下载armok01140737.rar

出0入0汤圆

发表于 2007-1-8 10:43:31 | 显示全部楼层
谢谢了

出0入0汤圆

发表于 2007-1-8 15:11:43 | 显示全部楼层
请问楼主,你的BOOTLOADER下载16K的程序要多长的时间呢,

出0入0汤圆

发表于 2007-1-8 15:33:33 | 显示全部楼层
谢谢

出0入0汤圆

 楼主| 发表于 2007-1-8 21:54:26 | 显示全部楼层
9600bps下,发送14K程序(不包括BOOTLOADER占用的2K)需要20秒左右

出0入0汤圆

发表于 2007-1-9 10:31:32 | 显示全部楼层
我的BOOT下载11K,115200波特需8秒,我还嫌它慢,想把程序优化。但不知如何下手。我的BOOT没有使用CRC校验。通讯协议是自己定的。

出0入0汤圆

发表于 2007-1-9 10:52:44 | 显示全部楼层
不知道下载的极限速度是多少?

看起来比较慢.

出0入0汤圆

发表于 2007-1-9 15:22:48 | 显示全部楼层
谢谢

出0入0汤圆

 楼主| 发表于 2007-1-9 22:58:43 | 显示全部楼层
朋友们都觉得速度慢,的确是如此。用于研究可以尽可能提高速率,115200bps是可以的。



我想如果是做产品,通用性,稳定性是最重要的。若是因为快了升级失败,让客户投诉回来,可不是20秒钟的下载时间可以搞定的,要搭上老多时间和金钱。

做小批量的产品对20秒时间应该是不在乎。

对于大批量的消费类电子产品,在生产上一般就使用并行编程器或ISP等,会更快。
-----此内容被huasoft于2007-01-09,23:01:24编辑过

出0入0汤圆

发表于 2007-1-10 10:29:05 | 显示全部楼层
我的BOOT程序是自已用来调试程序用的,我的MEGA16第一次用并口下载BOOT程序后,应用程序都是用串口通过BOOT程序下到FLSH中,程序运行时的调试信息通过串口发给PC机。

出0入0汤圆

发表于 2007-2-1 09:33:56 | 显示全部楼层
我按照楼主的说明做了,加上了 LDFLAGS += -Wl,--section-start=.text=0x3800,可是编译出来的.HEX文件的首地址却不是在0X3800,还是从0X0000开始,这句有加与没加的效果是一样的,请问除了这个还有什么要注意的.

还有我发现我的MFILE.EXE

出0入0汤圆

发表于 2007-2-1 09:38:00 | 显示全部楼层
我按照楼主的说明做了,加上了 LDFLAGS += -Wl,--section-start=.text=0x3800,可是编译出来的.HEX文件的首地址却不是在0X3800,还是从0X0000开始,这句有加与没加的效果是一样的,请问除了这个还有什么要注意的.

  还有我发现我的MFILE.EXE 双击不能打开,会不会跟这个也有关系,而且重装后还是一样.这是什么原因.请各位大侠指教,小弟正在做一个有用到远程升级的,急着用到这方面的东西.



 

出0入0汤圆

发表于 2009-12-8 22:42:45 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-12-10 10:36:43 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-12-10 11:04:36 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-12-10 13:00:39 | 显示全部楼层
mark

出0入0汤圆

发表于 2009-12-10 15:45:41 | 显示全部楼层
//计算CRC16
unsigned int calcrc(unsigned char *ptr, unsigned char count)
{
    unsigned int crc = 0;
    while (count--)
    {
        crc =_crc_xmodem_update(crc,*ptr++);
    }
    return crc;
}

这段计算CRC16   是什么原理啊,很是疑惑

出0入0汤圆

发表于 2009-12-10 22:44:09 | 显示全部楼层
看看

出0入96汤圆

发表于 2010-5-12 13:19:58 | 显示全部楼层
记号

出0入0汤圆

发表于 2010-5-12 13:23:39 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-5-19 20:08:05 | 显示全部楼层
mark 正在搞,谢谢

出0入0汤圆

发表于 2010-5-19 21:55:01 | 显示全部楼层
mark

出0入0汤圆

发表于 2010-5-20 08:50:40 | 显示全部楼层
更新一页后会自动复位,不知道怎么回事,纠结中……

出0入0汤圆

发表于 2010-6-3 16:12:30 | 显示全部楼层

出0入0汤圆

发表于 2010-6-15 09:26:47 | 显示全部楼层
M16  BOOTLOADER
学习。。。。。。。。。

出0入0汤圆

发表于 2010-10-10 09:54:44 | 显示全部楼层
safdsfs
头像被屏蔽

出0入0汤圆

发表于 2010-12-23 22:14:45 | 显示全部楼层
回复【楼主位】huasoft
-----------------------------------------------------------------------

学习了,不知为什么我的BOOTLOADER下载完一次程序后,就不能用了,要重新ISP下载一次BOOT到M16才行.BOOT熔丝设置锁定了也是一样.总之就是我的BOOT能用,但一用就好像BOOT会改写掉!一次性,够环保....WHY?

出0入0汤圆

发表于 2010-12-24 20:44:37 | 显示全部楼层
收下!!

出0入0汤圆

发表于 2011-1-18 20:09:05 | 显示全部楼层
用串口中断收发数据+定时器 来设计 更容易调试成功!

出0入0汤圆

发表于 2011-1-19 15:32:33 | 显示全部楼层
M16  BOOTLOADER
学习。。。。。。。。。

出0入0汤圆

发表于 2011-1-19 19:30:15 | 显示全部楼层
mark

出0入0汤圆

发表于 2011-4-20 09:21:45 | 显示全部楼层
mark

出0入0汤圆

发表于 2012-2-10 15:24:22 | 显示全部楼层
回复【楼主位】huasoft
-----------------------------------------------------------------------

mark

出0入0汤圆

发表于 2012-8-6 18:55:01 | 显示全部楼层

出0入0汤圆

发表于 2012-8-15 10:54:34 | 显示全部楼层
good job !!!

出0入0汤圆

发表于 2012-8-18 09:13:54 | 显示全部楼层
正需要 学习啦!

出0入0汤圆

发表于 2012-9-6 16:41:22 | 显示全部楼层
学习,学习!

出0入0汤圆

发表于 2014-6-11 12:31:02 | 显示全部楼层
好东西!!!
回帖提示: 反政府言论将被立即封锁ID 在按“提交”前,请自问一下:我这样表达会给举报吗,会给自己惹麻烦吗? 另外:尽量不要使用Mark、顶等没有意义的回复。不得大量使用大字体和彩色字。【本论坛不允许直接上传手机拍摄图片,浪费大家下载带宽和论坛服务器空间,请压缩后(图片小于1兆)才上传。压缩方法可以在微信里面发给自己(不要勾选“原图),然后下载,就能得到压缩后的图片】。另外,手机版只能上传图片,要上传附件需要切换到电脑版(不需要使用电脑,手机上切换到电脑版就行,页面底部)。
您需要登录后才可以回帖 登录 | 注册

本版积分规则

手机版|Archiver|amobbs.com 阿莫电子技术论坛 ( 粤ICP备2022115958号, 版权所有:东莞阿莫电子贸易商行 创办于2004年 (公安交互式论坛备案:44190002001997 ) )

GMT+8, 2024-4-29 07:19

© Since 2004 www.amobbs.com, 原www.ourdev.cn, 原www.ouravr.com

快速回复 返回顶部 返回列表