8-STM32物联网开发WIFI(ESP8266)+GPRS(Air202)系统方案升级篇(远程升级STM32单片机程序)

可以实现单片机升级了,现在是先记录一直东西,因为还没有优化好,唉,出门把钥匙锁家里了。。。。等着开锁的师傅来,看看人家是如何开锁的,学学。。哈哈哈

。。。测试好以后写使用教程吧

参考这个再看这篇文章

https://www.cnblogs.com/yangfengwu/p/6921832.html

整体协议:

APP通过MQTT把信息发给WIFI,WIFI转发给STM32
STM32把信息通过WIFI转发APP
WIFI模块的一个引脚和STM32的复位引脚相连接
该引脚一开始是低电平,WIFI程序运行后该引脚为高电平(STM32开始工作)


注:APP发送给WIFI '切换执行程序' 或者 '擦除所有用户程序' 消息时,WIFI先直接用引脚控制STM32复位重启,
STM32一开始执行IAP程序,IAP程序一开始默认发送:{"datemcu":"updata","status":"switch"}  接着看下文

/*********************IAP程序处理(没有更新状态标志位)************************/

IAP程序一启动STM32发送的消息如下:询问是不是需要切换执行程序
{"datemcu":"updata","status":"switch"}  此协议1S发送一次,总共发3次,超时执行对应的用户程序,如果对应的用户程序可运行
{"datemcu":"updata","status":"run1"}  或者  {"datemcu":"updata","status":"run2"} 该语句放在用户程序里面

WIFI接收到后回复:
             不需要切换                                 切换单片机程序                       擦除所有用户程序
{"datemcu":"updata","cmd":"noswitch"} 或 {"datemcu":"updata","cmd":"yesswitch"} 或 {"datemcu":"updata","cmd":"erase"}

第一个:不需要切换  
       如果对应的用户程序可运行,运行对应的用户程序

第二个:切换单片机程序 
       STM32接收到以后切换完执行程序的标志位发送:       
       {"datemcu":"updata","status":"switchok"}  此协议1S发送一次,发4次后复位重启
       WIFI接收到后:  复位单片机
        
第三个:擦除所有用户程序
       STM32接收到以后擦除所有用户程序 此协议1S发送一次,发送4次后复位重启
       {"datemcu":"updata","status":"eraseok"}
       WIFI接收到后:  复位单片机
    
    
    
/*******************************IAP程序实现更新的协议如下********************/

//APP发送获取设备型号
{"datemcu":"updata","cmd":"model"}

//STM32设备回复
{"datemcu":"updata","status":"model","model":"stm32test"}//假设现在的型号是stm32test


二,上位机根据型号http访问更新的信息
             实际用域名代替           "型号"
列如:"http://47.92.31.46/hardware/"+stm32test+"/"+"updatainfo.txt"



//APP发送给设备平台的版本号和更新文件的位置,该url由WIFI模块进行记录
{"datemcu":"updata","cmd":"info","version":"1.0.1","url":"http://47.92.31.46/hardware/stm32test"}


//STM32回复是不是和发给它的版号一致,并回复自己的版本号
{"datemcu":"updata","status":"unlike",version:XXXX} 或 {"datemcu":"updata","status":"alike",version:XXXX} 
或者 {"datemcu":"updata","status":"unlike","version":"error"} //单片机接收版本出错



//APP发送给设备升级指令
{"datemcu":"updata","cmd":"start"}    


//单片机接收到以后,写入需要更新的标志 然后回复
{"datemcu":"updata","status":"start"}  1S 1次 4次,然后复位重启
//WIFI接收到该信息直接用引脚控制STM32复位重启


/**********************IAP程序再次启动,检查到有更新标志*************************/

//单片机发送:{"datemcu":"updata","status":"start","file":"bin1"} 或者 {"datemcu":"updata","status":"start","file":"bin2"}
该指令总共发送两次
WIFI模块第一次接收到此命令,WIFI模块关掉MQTT接收的数据转发给STM32的功能,同时把该信息发给MQTT

在STM32发送第二次这个指令的时候 ,清理一下链表,启动超时定时器,允许串口接收的数据写入Flash

WIFI模块第二次接收到此命令,根据bin1或者bin2访问对应的bin文件,把云端程序通过串口发给STM32


STM32接收完数据  或者  接收出错
第一种:
        切换单片机程序的标志位,记录好该执行那一份程序的地址,写入更新完成标志,用新的版本号替换掉旧的版本号,复位重启
        复位重启以后,检测到更新完成标志,发送{"datemcu":"updata","status":"finish"}  1S 1次 发送3次  然后清除该标志
第二种: 写入更新失败标志,复位重启
        复位重启以后发送{"datemcu":"updata","status":"error"} 1S 1次 发送3次  然后清除该标志

清除更新成功或者失败标志以后,执行最上面的发信息给WIFI模块询问是不是需要切换执行运行的用户程序
{"datemcu":"updata","status":"switch"}    
        

        

        
/***********************用户程序********************/
/*
假设用户程序正常运行,用户本身知道单片机是不是正常运行,如果运行不正常,用户可以发送 '切换执行程序' 或者 '擦除所有用户程序'
擦除所有用户程序以后,单片机只运行IAP程序,用户可以重新操作单片机进行更新
*/

//APP发送获取设备型号
{"datemcu":"updata","cmd":"model"}

//STM32设备回复
{"datemcu":"updata","status":"model","model":"stm32test"}//假设现在的型号是stm32test


二,上位机根据型号http访问更新的信息
             实际用域名代替           "型号"
列如:"http://47.92.31.46/hardware/"+stm32test+"/"+"updatainfo.txt"



//APP发送给设备平台的版本号和更新文件的位置,该url由WIFI模块进行记录
{"datemcu":"updata","cmd":"info","version":"1.0.1","url":"http://47.92.31.46/hardware/stm32test"}
//WIFI接收到此信息以后去掉后面的url的json部分

//STM32回复是不是和发给它的版号一致,并回复自己的版本号
{"datemcu":"updata","status":"unlike",version:XXXX} 或 {"datemcu":"updata","status":"alike",version:XXXX} 
或者 {"datemcu":"updata","status":"unlike","version":"error"} //单片机接收版本出错


//APP发送给设备升级指令
{"datemcu":"updata","cmd":"start"}    

//单片机接收到以后,写入需要更新的标志 然后回复
{"datemcu":"updata","status":"start"}  1S 1次 4次,然后复位重启
//WIFI接收到该信息直接用引脚控制STM32复位重启
    
        
        
        
更新过程中设备发送更新进度--由于更新时间太短...暂不考虑
{"datemcu":"updata","status":"starting","percent":"百分比"} 百分比为数字 


注:

由于STM32的各个型号不一致,内存和Flash也不一致
STM32接收统一采用环形队列,边接收边写入
Flash不一致问题(主要是1024和2048),提供两套程序支持

升级程序文件和关于升级的内容(内容里面含有版本号)放在云平台
APP或者wed或者上位机通过http获取关于升级的内容

WIFI通过http获取bin文件,然后通过串口发给单片机

 IAP程序中的Flash文件,用户根据自己的程序调整,64KB的一般不需要改动,除非用户需要存储的用户数据很多

 

 首先下载IAP程序,IAP程序不需要对软件做任何配置,直接下载即可

 

 

 

  稍微看一下用户程序1的一些主要程序和配置

 

 协议部分请参见最上面的协议

        if(StartUpdateFlage)
        {
            if(Time2UpdateCnt>=100)
            {
              Time2UpdateCnt = 0;
                printf("%s",UpdateStart);
                SendDateCnt++;
            }
            if(SendDateCnt>=3)
            {
              Reset_MCU();//ÖØÆô
            }
        }
        
        
        if(Usart1ReadFlage)//´®¿Ú½ÓÊܵ½Êý¾Ý
        {
            Usart1ReadFlage = 0;
            
            /*************Ô¶³Ì¸üÐÂÏà¹ØStop***************/
            if(strstr(Usart1ReadBuff,"{\"datemcu\":\"updata\",\"cmd\":\"model\"}"))//ѯÎÊÉ豸ÐͺÅ
            {
                printf("{\"datemcu\":\"updata\",\"status\":\"model\",\"model\":\"%s\"}",model);
            }
            else if(strstr(Usart1ReadBuff,"{\"datemcu\":\"updata\",\"cmd\":\"info\",\"version\""))//APP·¢¹ýÀ´³ÌÐò°æ±¾
            {
                if(Usart1ReadBuff[34]=='v' && Usart1ReadBuff[37]=='s' && Usart1ReadBuff[40]=='n' && Usart1ReadBuff[42]==':' && Usart1ReadBuff[49]=='\"')
                {
                    Version1[0] = Usart1ReadBuff[44];
                    Version1[1] = Usart1ReadBuff[45];
                    Version1[2] = Usart1ReadBuff[46];
                    Version1[3] = Usart1ReadBuff[47];
                    Version1[4] = Usart1ReadBuff[48];
                    SetVersion1(Version1);//ÉèÖÃÔƶ˰汾
                    
                    if(strstr(Version1,Version2))//°æ±¾Ò»Ñù
                    {
                        printf("{\"datemcu\":\"updata\",\"status\":\"alike\",\"version\":\"%s\"}",Version2);
                    }
                    else
                    {
                        printf("{\"datemcu\":\"updata\",\"status\":\"unlike\",\"version\":\"%s\"}",Version2);
                    }
                }
                else//°æ±¾½âÎöʧ°Ü
                {
                    printf("{\"datemcu\":\"updata\",\"status\":\"unlike\",\"version\":\"error\"}");
                }
            }
            else if(strstr(Usart1ReadBuff,"{\"datemcu\":\"updata\",\"cmd\":\"start\"}"))//APP·¢¹ýÀ´É豸Éý¼¶Ö¸Áî
            {
                SetUpdateFlage();//дÈëÉý¼¶±êÖ¾
                printf("%s",UpdateStart);
                SendDateCnt = 0;
                Time2UpdateCnt = 0;
                StartUpdateFlage = 1;
            }
            /*************Ô¶³Ì¸üÐÂÏà¹ØStop***************/

告诉IDE,我的程序从8004000开始运行,给我分配5C00大小的Flash   = 23KB = 23552个字节

E:\MDK5\ARM\ARMCC\bin\fromelf.exe  --bin -o  .\Progect\Progect.bin  ..\Progect\output\Progect.axf

帮我生成bin文件

 然后根据协议把用户程序1,通过串口发给

{"datemcu":"updata","cmd":"model"}
{"datemcu":"updata","cmd":"info","version":"0.0.1"}
{"datemcu":"updata","cmd":"start"}

 

 现在再把用户程序2更新进去

 

 

 

 E:\MDK5\ARM\ARMCC\bin\fromelf.exe  --bin -o  .\Progect\Progect.bin  ..\Progect\output\Progect.axf

 

 切换文件执行:

因为切换文件是WIFI模块先复位单片机,我手动模拟复位单片机

 

 清除程序

 

 OK,单片机这端测试没有问题了,小容量的单片机就是麻烦,还是用的环形队列一边接收一遍写入

 

猜你喜欢

转载自www.cnblogs.com/yangfengwu/p/10817228.html