历史上的今天
今天是:2025年03月30日(星期日)
2020年03月30日 | 基于AVR-BootLoader,通过霜蝉远程串口可实现单片机的远程升级
2020-03-30 来源:eefocus
最近一直利用业余时间写自己的“基于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
//--------------------------------------------------//
// 全局变量定义
uchar RX_buff[BUFSIZE]; // 数据拉收缓存
uchar Frame_State,SOH_Wait_cnt; // 帧状态,帧头等待计数
uint Time_cnt,Error_cnt; // 超时计数,连续帧错误计数
uint buffptr,buffptr_old,buffptr_New; // 数据缓存指针必须大于1024
ulong FlashAddr; // Flash地址
uchar UpdatedSta; // 升级标志
//-----------------------------------------------//
//擦除(code=0x03)和写入(code=0x05)一个Flash页
void boot_page_ew(ulong p_address,char code)
{
#asm
ldd r26,y+1 ; R26 LSB
ldd r27,y+2 ; R27 MSB
#endasm
SPM_REG = code; // 寄存器SPMCSR中为操作码
#asm
mov r30,r26
mov r31,r27
#endasm
#ifdef ATMEGA128
RAMPZ=(p_address>>16); // RAMPZ0 = 1: ELPM/SPM 可以访问程序存储器地址$8000 - $FFFF ( 高64K 字节)
#endif
#asm("spm"); // 对指定Flash页进行擦操作
}
//填充Flash缓冲页中的一个字
void boot_page_fill(uint A_address,uint data)
{
#asm
LDD R30,Y+2 ; R30 LSB
LDD R31,Y+3 ; R31 MSB
LD R26,Y
LDD R27,Y+1
MOV R0,R26
MOV R1,R27
MOV R26,R30
MOV R27,R31
#endasm
SPM_REG =0x01; //寄存器SPMCSR中为操作码
#asm
mov r30,r26
mov r31,r27
#endasm
#asm("spm"); //对指定Flash页进行擦操作
}
//等待一个Flash页的写完成
void wait_page_rw_ok(void)
{
while(SPM_REG & 0x40)
{
while(SPM_REG & 0x01);
SPM_REG = 0x11;
#asm("spm");
while(SPM_REG & 0x01);
}
}
//-----------------------------------------------//
//更新一个Flash页的完整处理
void write_one_page(uchar data[])
{
uint i;
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超时自动转为应答 unsigned char Wait1S_UART() { uchar i=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; return UDRREG(COMPORTNo); // 读取UDR0 } } while(100!=i); // 等待数据||超时退出 } //***************************************************// //===================================================// void main(void) { uchar packNO,packNO_old; // 包号、包号留存 uint crc16; // 接收CRC缓存 uint li; // 帧计数 uchar ch, 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
史海拾趣
|
职业生涯规划是针对决定个人职业选择的主观和客观因素进行分析和测定,确定个人的奋斗目标并选择符合这一目标的职业。职业生涯规划要求你根据自身的兴趣、特点,将自己定位在一个最能发挥自己长处的位置,选择最适合自己能力的事业,下面从四个方面 ...… 查看全部问答> |
|
10月10日,国内最大的太阳能电池封装玻璃生产线在博爱县建成投产。 据介绍,河南裕华高白玻璃有限公司年产10万吨太阳能光伏玻璃项目三期工程是国家工业国债项目、河南省50家高成长型企业之一。到今年年底,这家位于焦作市博爱县的国内最大的 ...… 查看全部问答> |
|
1.W-CDMA协议概观(25.201) 2.传输信道和物理信道映射(25.211) 3.信道复用与信道编码(25.212) 4.扩频与调制模式(25.213) 5.物理层处理机制(25.214) 6.物理层测试规范(25.215) … 查看全部问答> |
|
本人第一次写USB 程序,网上很多都是USB设备(模拟一个USB设备),但任务是USB主机驱动,即驱动开发板驱动一个USB设备,先期是HID类 有哪位高手给一个资源,给点指导郁闷很长时间了。(1.JUNGO的USBWare要钱,很贵,有免费的吗) nxp LPC 24xx 以 ...… 查看全部问答> |
|
要使得TOUT1的输出频率是25MHZ,作了如下配置: //step1 s2440IOP->rGPBCON &=~(3rTCMPB1 = ?? ; //step5 s2440PWM->rTCON &= (~(0xf… 查看全部问答> |
|
BOOL ret; ret = EnumPrinterDrivers(NULL, NULL, 1, NULL, 0, &dwNeeded, &dwReturned); 返回值是1,但是dwNeeded却为0,dwReturned也为0 & ...… 查看全部问答> |
|
VS2005的MFC智能设备程序 我继承了 CPropertySheet类CMyPropSheet,然后在它的OnInitialDialog()中使用SetActivePage()就会出错,请问这是什么原因啊??… 查看全部问答> |
|
终于把Jennic的产品先拿回来试试了,按照步骤运行Flash Programmer,选中目标bin文件,选择串口,连接好串口电缆,打开目标板电源,点击program按钮(这一步是要把程序写入板子),可是到这一步就跳出个对话框:无法读取处理器ID寄存器,请检查电缆 ...… 查看全部问答> |




