一种利用串口51单片机远程升级 OTA

发布者:温馨幸福最新更新时间:2020-02-22 来源: 51hei关键字:串口  51单片机  远程升级  OTA 手机看文章 扫描二维码
随时随地手机看文章

回馈网友的心态,发一篇关于OTA的贴,不喜勿喷,随着现在科技的发展,市面上出现很多带wifi,蓝牙等智能产品,为满足人们对产品可以不断完善,诞生了这种远程升级的技术。      


在此之前呢,做过一个stm32远程升级的项目,这种片子的代码地址偏移性很好,load程序和应用程序划分好就可以,后来就想51这种便宜的mcu,能不能也实现这个功能呢,这就有了这次的实验。

废话不多说,先说说原理,OTA主要就三部分,一个是load程序,一个是应用程序,还有带升级的程序,三个分别存储在不同地址,我以flash 32K为例。如下图

 
为什么要这样划分地址呢。主要是因为51单片机的中断地址不能发生偏移(至少我不知道怎么偏移),所以我运行的程序必须在起始地址0x0.吧bootload程序放在了0x6000的位置。

1,bootload程序设计,程序功能主要是判断有没有升级标志,有升级标志把APP2的文件拷贝到APP1,然后跳转到app1位置运行。如果没有升级标志直接跳转到app1.

keil中设置1,BL51 locate 启动文件 ?C_C51STARTUP(0x6100) 需要特殊放置,这样才能保证每次启动后跳转的位置准确;

设置2,target  EProm 0x6000;

 
 


这样编译出来的 hex文件  就是下面这个样子。

 


这个时候bootload程序算设计好了,可以直接烧录到MCU中。

2,应用程序 APP1设计,程序功能主要实现我们自己产品功能,以及接收保存远程发过来的程序。
keil中设置1,BL51 locate 启动文件 ?C_C51STARTUP(0x1000) 需要特殊放置,这样才能保证每次启动后跳转的位置准确;
         设置2,target  EProm 0x0;
 
 

这样就可以确保每次程序跳转正确。关键的在这里,因为每次要先运行bootload 所以需要在0x0 位置 跳转到bootload地址是0x6100,再有boot程序跳转到我们的0x1000 这样成正常运行,看起来很复杂,其中只有两个关键地址,0-->0x6100 -->0x1000 , 就这两步骤。

3,然后再来说说升级文件的打包制作,首先呢需要把 02 10 00  改成 02 61 00.
       在bin文件前面插入256个字节,升级文件信息。
        a,0-3字节 文件版本号
        b 4-7字节 文件长度
        c 8-11字节 文件类型
        d 12-13字节 文件的CRC校验(校验只对程序文件,不包括插入的信息)
        e 10-255  0xff

我这里用C#写了一个小工具和一个模拟云服务器发送的 工具。
 

 


这样就完成了51 远程升级的全部工作。不喜勿喷,附上代码仅供学习参考。

//-------------------------------bootload----------------------------------------
#include "hal_clock.h"
#include "hal_gpio.h"
#include "hal_pwm.h"
#include "hal_timer.h"
#include "hal_interrupt.h"
#include "hal_adc.h"
#include "hal_uart.h"
#include "WIFI_JD780.h"
#include "IR.h"
#include "Buzz.h"
#include "hal_ssp.h"
#include "stdio.h"

#define USAR_APP_ADDR   0x1000

typedef void (*boot_fun)(void) ;//= USAR_APP_ADDR;


int cnt_500ms;
char goto_flag;
int i;
char str[10];

char temp1,temp2;

void main(void)
{
    system_clock_set(0);
    _hal_gpio_init();
    _MCU_TIMER_Init();
    _mcu_uart1_init();

    EA = 0;

    uart1_send("boot run ..                        rn");
    uart1_send("boot addr 0x6000 main addr 0x6100..rn");
    uart1_send(__DATE__);
    uart1_send("rngo to app run addr:0x1000      rn");
    uart1_send("-----------------------------------rn");

//     Ssp_WriteByte(EEPOM_ADDR,0xaa,mFLASH);
        
        
     i = Read_FlashByte(EEPOM_ADDR);//检查是否有升级

     if(i==0xaa)
     {
        uart1_send("Updata......rn");

        for( i=0;i<10;i++)
        {
             Ssp_EraseBlock(APP_ADDR + i*0x400,mFLASH);
        } 


        uart1_send("EraseBlock  OK rn");
        for(i=0;i<0x2800;i++)
        {
            Ssp_WriteByte(i,Read_FlashByte(APP_BACK_ADDR+i),mFLASH);
        }
        uart1_send("WriteBlock  OK rn");
        Ssp_EraseBlock(EEPOM_ADDR,mFLASH);
        Ssp_WriteByte(EEPOM_ADDR,0,mFLASH);

        for(i=0;i<0x2800;i++)
        {
            temp1 = Read_FlashByte(APP_BACK_ADDR+i);
            temp2 = Read_FlashByte(APP_ADDR+i);

            if( temp1 != temp2)//APP_ADDR
            {


                uart1_send("index: ");
                sprintf(str,"%d",i);
                uart1_send(str);
                uart1_send("Updata Error.....rn");
                while(1);
            }
        }
     }


    ((void(code*)(void))USAR_APP_ADDR)();

    while(1);

}




//-----------------------app1---------------------------------------------------

#include "hal_clock.h"
#include "hal_gpio.h"
#include "hal_pwm.h"
#include "hal_timer.h"
#include "hal_interrupt.h"
#include "hal_adc.h"
#include "hal_uart.h"
#include "WIFI_JD780.h"
#include "IR.h"
#include "Buzz.h"
#include "hal_ssp.h"


//0x0000-0x27ff app      main 0x1000      10K
//0x2800-0x4fff app-back                  10K
//0x5000-0x5fff eerom                     2 k
//0x6000-0x7fff boot  main 0x6100         8 k

//?C_C51STARTUP(0x1000)


code unsigned char mcu_sf_ver[5] ="1.09";
code unsigned char mcu_hw_ver[5] ="1.00";

int send_time;

void main(void)
{
    system_clock_set(0);
    _hal_gpio_init(); 
    _MCU_PWM_Init(); 
    _MCU_TIMER_Init();
    _mcu_uart1_init();
    _MCU_IRQ_Init();
    _wifi_init();
    IR_ExtInit();
    _mcu_adc_init();
    BUZ_Init();
    BUZ_PLAY_OFF();

    EA = 0;

    uart1_send("-----------------------------------rn");
    uart1_send("welcome to app world ..............rn");
    uart1_send(__DATE__);
    uart1_send("-----------------------------------rn"); 
    uart1_send("software ver :");
    uart1_send(mcu_sf_ver);
    uart1_send("rn"); 

    EA = 1; 


    while(1)
    {
        _MCU_TIMER_Driver();
        if(F_10ms)
        {
            F_10ms =0;  
                                
            IR_Process();
            _user_wifi_data_drives();
                        
                        
            if(IR_KeyCode.bits.Power)
            {
                IR_KeyCode.bits.Power = 0;
                 BUZ_PLAY_KEY();
                 //SBUF = 'C';
                 SBUF = Read_FlashByte(0x2800);

                 Ssp_EraseBlock(0x2800,mFLASH);

                 SBUF = Read_FlashByte(0x2800);
            }
            if(IR_KeyCode.bits.Auto)
            {
                IR_KeyCode.bits.Auto = 0;
                 BUZ_PLAY_KEY();   

                 SBUF = 'W';
                 //ssp_write_flash_nbyte(APP_BACK_ADDR,"1234567890",10);
                 //ssp_write_flash_nbyte(APP_BACK_ADDR+20,"1234567890",10);
            }
            BUZ_Run();
            //ADC_GetAD_12bit(1);
        }  
    }
}

关键字:串口  51单片机  远程升级  OTA 引用地址:一种利用串口51单片机远程升级 OTA

上一篇:单片机串口控制步进电机的源程序
下一篇:用51单片机控制步进电机运动详解

推荐阅读最新更新时间:2024-11-10 08:18

彻底解决stm32F042串口下载配置flymcu
本文的初衷是解决一个问题,描述如下: 1.实验芯片:stm32f042f4p6 2.封装:TSSOP20 3. 实验目的:使用PA0--PA6(接段位); PA7 PA13,P14(接共阳极),点亮3位7段数码管,并显示数字 4.实验步骤 : ·1 编写代码点亮PA4 的led 灯,点灯测试cpu。用 jtag9 配置 SW模式 100k 下载,一切正常,测试成功 ·2 编写代码使用PA14,PA13 引脚。。。。。等引脚链接数码管,下载成功,运行有问题,修改代码,想重新下载,完蛋了!!!就是下载不进去 报 No Cortex-M SW Device Found ?????? 这是咋么回事呢?
[单片机]
彻底解决stm32F042<font color='red'>串口</font>下载配置flymcu
51单片机C语言教程(八) 表达式语句1
从第四课到第七课,学习了大部分的基本语法,这一课所要学习的各种基本语句的语法可以说是组成程序的灵魂。在前面的课程中的例子里,也简单理解过一些语句的用法,可以看出C语言是一种结构化的程序设计语言。C语言提供了相当丰富的程序控制语句。学习掌握这些语句的用法也是C语言学习中的重点。   表达式语句是最基本的一种语句。不同的程序设计语言都会有不一样的表达式语句,如VB就是在表达式后面加入回车就构成了VB的表达式语句,而在51 单片机 的C语言中则是加入分号 ; 构成表达式语句。举例如下:   b = b * 10;   Count++;   X = A;Y = B;   Page = (a+b)/a-1;   以上的都是合法的表达式语句。
[单片机]
<font color='red'>51单片机</font>C语言教程(八) 表达式语句1
51单片机矩阵键盘检测源代码(按键数码管显示0-F)
本程序所用的原理图下载: 点这里 ,单片机芯片使用的stc89c52;找到相应部分即可.这是一整个单片机开发板的电路图其他的忽略. hex文件及其工程文件下载:http://www.51hei.com/f/juzhen.rar 以下是通过测试的源代码: /* *功能:使用矩阵按键使得按键按下时数码管上显示各自对应的数字(0 ~ F); *日期:2013-05-03-17:51; *作者:徐冉 *特别说明:本程序代码已经通过调试,仅供学习使用; * */ /***********AT89C52-RC 单片机51hei 实验板***********/ /*****************51hei-开发板****************
[单片机]
MCS-51单片机串行口工作方式与波特率计算举例
1)方式0 方式0是外接串行移位寄存器方式。工作时,数据从RXD串行地输入/输出,TXD输出移位脉冲,使外部的移位寄存器移位。波特率固定为fosc/12(即,TXD每机器周期输出一个同位脉冲时,RXD接收或发送一位数据)。每当发送或接收完一个字节,硬件置TI=1或RI=1,申请中断,但必须用软件清除中断标志。 实际应用在串行I/O口与并行I/O口之间的转换。 2)方式1 方式1是点对点的通信方式。8位异步串行通信口,TXD为发送端,RXD为 接收端。一帧为10位,1位起始位、8位数据位(先低后高)、1位停止位。波特率由T1或T2的溢出率确定。 在发送或接收到一帧数据后,硬件置TI=1或RI=1,向CPU申请中断;但必
[单片机]
小米手表Color获得OTA升级:新增游泳模式
近日,小米手表Color获得OTA升级,最新版本号为V1.5.306,新版本增加了游泳模式,并且支持手表解锁小米手机、NFC解锁米家智能门锁。   小米手表Color号称是小米首款腕上潮品,售价799元。采用1.39英寸AMOLED圆形高清大屏,搭配经典双色不锈钢表框,内置110款更具个性的潮流表盘,并有6色多彩硅胶腕带及鳄鱼皮纹真皮腕带,可组合出1540多种潮流搭配。   该手表配备6个高精度传感器,支持户外跑步、户外骑行、越野、登山、室内跑步、室内单车、健走、自由训练、泳池游泳、开放水域游泳十大主流运动模式。   不仅如此,小米手表Color还能够进行身体能量监测,综合监测分析一天当中身体的各项数据,实时计算身体能量值,
[手机便携]
STM32F407使用USB作虚拟串口出现黄感叹号
最近因为工作需要使用到了STM32F407VET6的USB_OTG_FS作为虚拟串口。 之前用STM32 CubeMX生成过STM32F103C8T6的虚拟串口代码,感觉用起来很方便,于是这次的F407也用MX生产工程,奈何竟然遇到诸多难题,整整困扰了两天。 先说一下我的流程。 MX生成F407 USB虚拟串口工程操作流程 1,选择芯片 先是利用条件筛选选择自己的芯片,如下图: 2,配置管脚 配置RCC输入脚,SYS调试口以及USB_OTG_FS,USB_OTG_FS– Device Only– Comunication Device Class,个人喜欢使用FreeRTOS。配置如下图: 3,配置时钟 用的8M外部晶
[单片机]
8月OTA盘点:「手车互联」的春天又来了?
一转眼,又到了每月一次的OTA月报时间! 在过去的一个月里,又有多少幸运的车主们收到OTA更新了呢? 今天就让我们一起来看看吧! 从总体数量来看,车企们在8月份的OTA热情依然和气温一样高涨。 有近20家车企为旗下车型推送了进行了OTA更新,其中不乏捷达、奇瑞等品牌的燃油车型。 具体来看,在8月推送的OTA中,智能驾驶辅助依然是当仁不让的升级热点。 除领航辅助功能外,诸如智能泊车、遥控泊车、低速防碰撞等日常使用频率更高的功能,也成为了OTA内容中的常客。 此外,「手车互联」在最近几个月大有“卷土重来”之势! 通过新增HiCar和ICCOA协议,即可适配目前市面绝大部分的鸿
[汽车电子]
8月<font color='red'>OTA</font>盘点:「手车互联」的春天又来了?
STM32-串口超时判断方式接收未知长度数据
usart.c串口中断处理函数: void USART1_IRQHandler(void) { u8 res; if(USART1- SR&(1 5))//接收到数据 { res=USART1- DR; if(USART1_Recv_LenCV_LEN) //还可以接收数据 { TIM3- CNT=0; //计数器清空 if(Rec_Over_Flag==0)TIM3_Set(1); //使能定时器4的中断 USART1_RX_BUF =res; //记录接收到的值
[单片机]
小广播
设计资源 培训 开发板 精华推荐

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

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

换一换 更多 相关热搜器件
随便看看

 
EEWorld订阅号

 
EEWorld服务号

 
汽车开发圈

电子工程世界版权所有 京B2-20211791 京ICP备10001474号-1 电信业务审批[2006]字第258号函 京公网安备 11010802033920号 Copyright © 2005-2024 EEWORLD.com.cn, Inc. All rights reserved