06-STM32+ESP8266+AIR202远程升级方案-移植STM32+ESP8266实现利用http或https远程更新STM32程序到自己的项目(定时访问升级,备份升级)
<p><iframe name="ifd" src="https://mnifdv.cn/resource/cnblogs/ESA2GJK1DH1K_B/" frameborder="0" scrolling="auto" width="100%" height="1500"></iframe></p>
移植BootLoader
1.凡是和ESP8266类似,通过串口配置通信的模块都可参照此节移植.
如果做项目,请大家必须使用STM32F103CBT6 及其以上的Flash>=128KB的单片机.
2.用户移植的时候首先保证自己的程序已经可以控制模块实现TCP通信(模块作为客户端)
3.我准备了一份空模板
该模板只有一个定时器,延时,串口
因为每个人写的程序都不一样,我假设我的模板也实现了控制模块实现TCP通信.
然后现在我就想移植我写的程序到一个新的工程里面作为BootLoader引导程序.
4.我复制出来一份空模板作为BootLoader
5.把BootLoader移植文件里面的BootLoader和mem文件夹复制到自己的工程
6.把文件添加到工程,并包涵下.h路径
7.需要添加操作 flash的库
8.编译工程,打开第一个错误
9.添加上自己的延时1ms函数
10,接着看下面两个错误
下面两个地方是向模块发送get指令
11,我的8266模块配置上TCP连接Web服务器以后如果是透传模式下我直接往串口发送数据
数据就会被8266转发出去
如果不是透传模式下,https的时候模块就不支持透传,我需要先发送AT+CIPSEND=数据个数
然后等模块返回 < 以后我再发送数据
所以我的修改如下(假设我是用串口1和wifi模块通讯)
12,把 IAPTimerOut(); 函数放到1ms定时器中断函数里面
13, 在主程序里面写上以下程序
注:AutoConnectTCP()函数是控制模块连接web服务器的函数,客户需要根据自己的程序实现此功能
连接的IP地址为: IAPStructValue.IP(字符串形式) 连接的端口号为:IAPStructValue.Port
连接成功以后返回 1
上面的IP地址和端口号是根据固件程序地址解析出来的
还有一个参数 IAPStructValue.SSLEN ; 0:http 1:https
如果客户使用的也是8266,可以参考测试升级源码中的例子.
如果客户需要把字符串形式的IP地址转换为数组形式,可使用下面的转化函数
/**
*@brief 检查字符串地址是IP还是域名
*@param str 要转换的数据
*@param ip 转换后存储的位置
*@return 0:转换失败,可能是域名 1:转换成功
*@example UTILS_StrToIP("192.168.0.1", &ip) ip[0]=192;ip[1]=168;ip[2]=0;ip[3]=1;
*/
uint8 UTILS_StrToIP(const char* str, void *ip)
{
/* The count of the number of bytes processed. */
int i;
/* A pointer to the next digit to process. */
const char * start;
start = str;
for (i = 0; i < 4; i++) {
/* The digit being processed. */
char c;
/* The value of this byte. */
int n = 0;
while (1) {
c = * start;
start++;
if (c >= '0' && c <= '9') {
n *= 10;
n += c - '0';
}
/* We insist on stopping at "." if we are still parsing
the first, second, or third numbers. If we have reached
the end of the numbers, we will allow any character. */
else if ((i < 3 && c == '.') || i == 3) {
break;
}
else {
return 0;
}
}
if (n >= 256) {
return 0;
}
((uint8_t*)ip)[i] = n;
}
return 1;
}
14,把 IAPPutDataToLoopList(char Res); IAPHttpHead(char Res);
函数放到和模块通信的串口中断里面
15,如果模块不是透传模式,还需要修改接收数据部分
一般不是透传模式,模块接收每一条数据的开头都会携带着其它自己添加的信息
假设ESP8266在非透传模式下接收到123个数据,返回给单片机的数据为:
rn+IPD,123:真实数据
用户可以参考下面的剔除程序,修改为自己的剔除程序.
客户修改做的就是把真实数据写入环形队列.
16,设置下默认的固件程序下载地址(根据自己的服务器修改)
17,建议在BootLoader程序里面打开看门狗
可直接把我提供的升级源码中的看门狗复制过来
18,屏蔽掉BootLoader程序里面使用的中断
用户需要把自己的中断函数放到此处关闭!
19,关于日志打印口(必须有,便于查看Flash分配情况和更新过程)
所有的日志都是使用的printf函数打印
printf打印不得和控制网络模块的串口冲突!
printf打印最好加上缓存,中断发送方式(建议环形队列+中断)
如果用户用 USART_SendData(其它串口,c); 等类似的阻塞型的函数实现printf
请屏蔽以下部分
20,设置工程生成bin文件,然后编译下工程.
21,根据bin文件大小在 stmflash.h中调整下flash分配
STM32_FLASH_SIZE 根据自己的单片机容量调整
如果使用的是128KB Flash的单片机:
FLASH_IAP_SIZE XX 根据BootLoader生成的bin文件大小设置(该值需要大于生成的bin文件大小)
FLASH_UPDATE_SIZE 1 //存储更新相关数据所有FLASH大小,不需要改动.
FLASH_USERDATA_SIZE XX 如果用户存储的数据量比较大,增加该值即可
如果使用的是256KB及其以上 Flash的单片机:
FLASH_IAP_SIZE XX 根据BootLoader生成的bin文件大小设置(该值需要大于生成的bin文件大小,设置为4的倍数)
FLASH_UPDATE_SIZE 4 //存储更新相关数据所有FLASH大小,设置为4
FLASH_USERDATA_SIZE XX 如果用户存储的数据量比较大,增加该值即可(设置为4的倍数)
22,当前BootLoader程序已经移植完成
为防止意外情况,我提供的远程升级源码中增加了崩溃处理程序.
客户根据自己的情况参考移植使用!
重新设置URL
配置模块连接路由器
APUConfig配网
移植用户程序
1.我复制了一份空模板假设作为了用户程序
2.把BootLoader移植文件里面的BootLoader和mem文件夹复制到自己的工程
3.把文件添加到工程,并包涵下.h路径
4.需要添加操作 flash的库
5.打开 IAP.h文件 设置 IAPProgramSelect 为 IAPUserProgram
6.屏蔽掉下面部分
7.去掉屏蔽
8.修改型号和info.txt文件的下载地址(根据自己的情况修改)
9.编译下工程,打开下面的错误
10.把自己的延时函数放到此处
11.调整用户程序stmflash.h文件里面的配置
和BootLoader程序里面的保持一致
和BootLoader程序里面的保持一致!
和BootLoader程序里面的保持一致!
12.把BootLoader程序编译下,下载到单片机,根据打印的信息调整用户程序配置
SCB->VTOR = FLASH_BASE | 0xXXXX;
13,在主函数里面添加以下函数
14,自行增加使用get指令访问info.txt文件命令
连接的服务器的IP地址 IAPStructValue.IP(字符串) 端口号 IAPStructValue.Port
文件路径 IAPStructValue.Path
以上信息是由 IAPInfoPathInit();函数解析而来
连接访问参考原用户程序:
15,解析获取的文件信息
info.txt文件内容:
{"version":"0.0.1","size":15990,"url":"http://mnif.cn/ota/hardware/STM32ESP8266BK/user_crc.bin","info":"1.解决了部分BUG 2.优化了部分程序"}
判断版本号,本地版本号存储在 FirmwareVersion
如果版本还不一致,把固件程序大小和固件程序下载地址调用相应的函数存储
void IAPSetUpdateUrl(char* ch) //存储url
void IAPSetFileSize(u32 data) //存储size
然后设置更新标志,重启即可
IAPSetUpdateFlage();
IAPResetMCU();
16,至此用户程序也移植完成!
移植完成以后,用户按照我先前提供的测试流程测试.
由于我本人是当局者,可能会忽略到一些细节,
如果客户遇到什么问题,请联系我,我将根据客户的反馈完善此节文章.
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 【SpringBoot-3】Lombok使用详解
- 【JMeter系列-3】JMeter元件详解之配置元件
- 【JMeter-4】JMeter元件详解之逻辑控制器
- 【JMeter-4】JMeter关联:JMeter正则表达式提取器与JSON提取器
- 【JMeter系列-5】JMeter操作Mysql数据库
- 【JMeter系列-6】JMeter BeanShell Sampler与JMeter BeanShell断言
- 【JMeter系列-7】Linux下执行测试
- 【JMeter系列-8】JMeter自定义日志与日志分析
- 【JMeter系列-9】 JMeter常用内置对象
- 【JMeter系列-10】JMeter websocket接口测试
- [Mysql-2] 远程连接数据库错误:host 'xxx.xxx' is blocked
- Linux超能力BPF技术介绍及学习分享(技术创作101训练营)
- 已创建好的vue项目引入vuex
- 【Mysql学习之旅-2】经典sql面试题及答案分析
- 【Mysql-3】条件判断函数-CASE WHEN、IF、IFNULL详解