博客园  :: 首页  :: 新随笔  :: 联系 :: 订阅 订阅  :: 管理

  • 本系列博客学习由非官方人员 半颗心脏 潜心所力所写,不做开发板。仅仅做个人技术交流分享,不做任何商业用途。如有不对之处,请留言,本人及时更改。

1、 Esp8266之 搭建开发环境,开始一个“hellow world”串口打印。
2、 Esp8266之 利用GPIO开始使用按钮点亮你的“第一盏灯”。
3、 Esp8266之 利用 "软件定时器 " 定时0.5秒闪烁点亮一盏LED。
4 、Esp8266之 了解PWM,更为深入地用PWM控制一盏LED的亮度变化。
5 、Esp8266之 原生乐鑫SDK高级使用之封装Post与Get请求云端,拿到“天气预报信息”。
6 、Esp8266之 了解 SmartConfig与Airkiss一键配网,给8266配网上云端。无需把wifi名字密码写在固件里。
7 、Esp8266之 了解 softAP热点配网模式原理,仿“机智云”定义自己的热点配网模式协议。
8、 Esp8266之 你要找的8266作为UDP、TCP客户端或服务端的角色通讯,都在这了。
9、 Esp8266进阶之路: [小实战上篇]Windows系统搭建8266的本地Mqtt服务器,局域网点亮一盏LED灯。
10、 Esp8266进阶之路: [小实战下篇]Windows系统搭建8266的本地Mqtt服务器,局域网点亮一盏LED灯。
11、 Esp8266进阶之路: 8266接入阿里智能,点亮一盏LED灯,期待天猫精灵语音控制的不约而至!
12、 Esp8266进阶之路: 图文并茂学习阿里云主机搭建8266MQTT服务器,实现移动网络远程控制一盏LED。
13、 Esp8266进阶之路: 动手做个8266毕设小案例,smartConfig + MQTT协议轻松实现远程控制一盏LED。
14、 Esp8266进阶之路: esp8266的 FreeRtos系统学习的正确姿势 ------ 环境搭建、烧录。
15、 Esp8266进阶之路: esp8266的 物联网又一股清流,8266接入阿里云平台非阿里智能的SDS服务,点亮一盏LED灯。
16、 Esp8266进阶之路: esp8266的 基于Nonos移植红外线H1838,实现红外遥控器配网,远程控制一盏灯。
17、 Esp8266进阶之路: esp8266自研的快速上电开关五次 (开-关为一次) ,无需按键触发则8266进去一键配网模式。
18、 Esp8266进阶之路: esp8266 基于NONOS 实现 OTA 远程升级,实现无线“ 热修复 ”升级固件程序。
19、 Esp8266进阶之路esp8266驱动 ds18b20、dht11 温湿度传感器,采集温湿度传感器到服务器。
20、 Esp8266进阶之路深入学习esp8266的esp now模式,仿机智云做一个小网关,实现无需网络下轻松彼此连接通讯交互数据。
21、 Esp8266进阶之路浅谈 esp8266 如何在本地局域网网络情况下实现最大效率地和前端实现数据交互。
22、 Esp8266进阶之路esp8266的工程如何添加第三方静态库文件以及如何自定义文件夹,聊聊那些makeFile的事。。
23、 Esp8266进阶之路再来一波 esp8266 基于 freeRtos系统连接自己私有的服务器实现OTA远程升级,接触下 lwip的基本知识。。
24、 Esp8266进阶之路渗透学习回顾下esp8266的外置spi芯片25q系列,熟悉8266代码块在其的分布,得心应手放置图片或其他资料。
25、 Esp8266进阶之路深聊下esp8266的串口 Uart 通讯中断编程,为您准备好了 NONOS 版本 和 RTOS 系统的串口驱动文件。
26、 Esp8266进阶之路RTOS分析 MQTT 实现过程,实现移植 MQTT协议在 esp8266 rtos实时系统,可断线重连。
27、 Esp8266进阶之路跟紧脚步,用VisualStudio Code开发 esp8266 rtos SDK v3.0版本,全新的 idf 框架,节省内存模块化开发。
28、 Esp8266进阶之路教你轻松自如使用cJson在乐鑫 esp8266 如何解析一段json数据以及如何生成一段json数据。
29、 Esp8266进阶之路百万条消息免费之乐鑫esp8266使用TCP直连模式MQTT协议接入阿里云物联网平台,支持私家服务器对接支持阿里云规则引擎。
30、 Esp8266进阶之路乐鑫esp8266 SDK编程使用 IIC总线驱动 0.96寸的OLED显示屏,显示天气预报信息。
31、 Esp8266进阶之路当esp8266遇到 Html,该怎么内置网页控制设备,理清内置网页的实现过程,实现无需路由器手机也可以控制esp8266。
32、 Esp8266进阶之路细聊HmacMD5的加密方法带来的安全性,并实践在esp8266上,最大保障传输的过程的信息的安全性。
33、 Esp8266进阶之路如何优雅地像乐鑫原厂封装esp8266底层寄存器的逻辑思维,做成自己的静态库库文件,让第三方人使用?
34、 Esp8266进阶之路乐鑫esp8266 NONOS SDK 3.0编程使用 SPI 驱动基于Max7219芯片的八位数码管,显示日期信息。
35、 Esp8266进阶之路乐鑫esp8266芯片借助机智云平台做一个商业化的七彩RGB灯泡可调整体方案项目,炫彩夺目高大尚。
36、 Esp8266之rtos3.0笔记认识esp8266 Rtos 3.0 sdk 工程结构,esp8266如何向esp-idf工程靠近的,如何自定义头文件编译?
37、 Esp8266之rtos3.0笔记你要找的基本外设功能都在这里了,包括Gpio、Pwm 和 Uart 接口使用。
38、 Esp8266之rtos3.0笔记 一篇文章带你搞掂存储技术 NVS 的认识和使用,如何利用NVS保存整型、字符串、数组以及结构体。
39、 Esp8266之rtos3.0笔记 捋一捋微信公众号配网智能设备 esp8266 并绑定设备的过程,移植并成功实现在 esp8266 rtos3.1 。
40、 Esp8266之rtos3.0笔记 基于乐鑫idf框架,研究出超稳定、掉线重连、解决内存泄露问题的Mqtt框架!支持esp8266和esp32!
41、 Esp8266之rtos3.0笔记 esp8266-12模块基于rtos3.1版本ota功能远程空中升级固件,官网基础之上增加dns域名解析!
42、 Esp8266之rtos3.0笔记 我又来了,基于rtos3.0版本 SDK编程 SPI 驱动 ws2812b 七彩灯,代码全部开源奉献给你们!
43、 Esp8266之rtos3.0笔记 esp8266-12模块基于rtos3.0版本扫描周围获取附近可用的 Wi-Fi 热点路由器信息,同样适合esp32。
44、 Esp8266之rtos3.0笔记 整理分享那些我在项目中常用的esp8266 rtos3.0版本的常见驱动,Button按键长短按、PWM平滑调光等。
45、 Esp8266之rtos3.0笔记 内置仅1M的Esp8285,如何攻破最棘手的OTA问题,大大节省资源成本开发产品。
46、 Esp8266之rtos3.0笔记 详细分析Esp8266上电信息打印的数据,如何做到串口通讯上电不乱码打印。
47、 Esp8266之rtos3.0笔记 无需外网,如何实现在本地局域网与控制端做数据交换的一些开发经验。
48、 Esp8266之rtos3.0笔记 迟来的1024程序员祝福,开源分享一个驱动 ds18b20 获取温度的工程。
49、 Esp8266之rtos3.0笔记 aliyun sdk 直连接入阿里云物联网平台,实现天猫精灵找队友零配网功能和语音控制。
50、 Esp8266之rtos3.0笔记 esp 如何从外部读取 csv 文件的数据,比如从代码读取外部文件阿里云三元组。
-------- 学习笔记持续更新,欢迎关注我…

很多人怎么联系我一起学习进步,下面打个小小公告:
玩转esp8266带你飞、加群付费QQ群,提高门槛,不喜的朋友勿喷勿加:434878850
esp8266源代码免费学习汇总(持续更新,欢迎star):https://github.com/xuhongv/StudyInEsp8266
esp32源代码免费学习汇总(持续更新,欢迎star):https://github.com/xuhongv/StudyInEsp32


在这里插入图片描述

一、前言


    有时候的一个抉择并非如自己所决定,而是被迫与现有生活的无奈。

    现在的我,越来越发现,想要更多的自由,也要考虑日后的家里人的事情,男人啊!虽然年轻,还是有心里放不下的包袱,为了事业拼搏,但又不能抛下日后家庭的关爱,真难!!

    今天给大家分享一系列的量产方案的实施过程;

    我们都知道,开发wifi设备或者其他设备,连接到物联网平台,总要担心被别人抓包盗取了 服务器地址、连接的鉴权信息包括用户名字和密码,我们详尽设法提高安全性,比如阿里云物联网连接的三元组机制,京东微联的 feedID 机制,抑或是百度云的身份特征,无非就是提高设备的连接唯一性和安全性;

    做过阿里云物联网的朋友都知道,阿里云三元组,一个设备对应一个三元组连接服务器,量产起来是非常麻烦的,难道要为每个设备定制一个代码吗?那么如何保证每个设备里面的三元组是唯一的呢?

    对于这个问题,很多开发者选择动态注册,就是让设备http请求在云端注册一个设备,而不是手动在云端注册,这样的好处就是如果非法用户抓取到了动态注册的格式,那么就会他人在自己的平台注册设备,这时候,是非常危险的!

    那么,如何实现一机一密的量产方案呢?有些人会想通过串口通讯给esp产品传三元组数据,这样的确可行!但是,你要为此写一个串口通讯吗?

    上面的抛砖引玉引出阿里云三元组,是指这类 设备唯一凭证信息,当然了,你也可以指其他信息。


二、重认识 25qxx系列


    首先啰嗦一下,esp8266只是一个芯片,不带flash芯片,而常见的外挂flash芯片有 25q16、25q32 等华邦出产芯片,查看,比较详细地说到了里面地分布,大概地:我也总结如下:

  • ①、w25q系列生产的加工的商家很多,但是里面的分布和命名规则都是一样的。比如华邦的w25q64spi通讯接口,64就是指64Mbit也就是8M的容量。而我们平时的8266-12f32Mbit就是4M容量。

  • ②、w25q64为例,我分析下里面的存储分布。w25q648M容量分为了128块,每一块又分为16个扇区,而每个扇区占4K大小。由此可计算到,w25q6464Mbit / 8 * 1024 / 16 / 4 = 128 块 ,有128 * 16 = 2048 个扇区,此计算原理后面我会提到。

  • ③、w25q64为例,我们在擦除数据时候,最少擦除单位为一个扇区,也就是每次必须擦除 4K 字节。写数据也是一样,必须一个扇区一个扇区去写,所以有我们的esp8266文档提到为什么要4的倍数去写读一个数据。

  • ④、w25q64为例,我们在往某个地址写之前必须确保这个地址上的值是0xFF,否则说明这个地址以前被写过数据,还没有被擦除。w25q64擦除的最小单位是Sector也就是4k个字节,也就是说如果要想往某个地址写一个值,如果这个地址上的值不是0xFF,那么就要把整个扇区都擦除,然后在写。

  • ⑤、w25q64为例,给w25q64开辟一个4k的缓存,比如定义一个4k的数组,然后在写数据之前先判断如果这个地址上的数据不是0xFF,就先把这个地址所在的Sector里的数据全部保存在4k缓存中,再擦除这个扇区,再把缓存中对应的地址上的数据更新,再把这个4k缓存区的所有数据一次性的写入到这个Sector中。因此我们在esp8266操作存储时候,要注意先擦除再写数据。

  • ⑥、w25q64为例,一共是8M字节=810241024=8388608(Byte),分为128块(64K),每一块有分为16个扇区(4K),所以扇区的个数是:12816=2048(个),那么我们选择扇区的范围就是0-2047,假如要擦除第1000个的扇区,那么这个扇区的字节起始就是10004096=4096000,然后W25Q64就从4096000开始往下擦除4K大小的数据空间,计算地址的时候是使用字节来计算的。


  • 下面是我用心画的一个示意图,方便大家去了解下:

    • 这个多少块的计算公式的得来主要后面推导过来的,我们仔细发现,后面都是一个4K为一个扇区,16个扇区为一块,所以我们先将我们的64Mbit换算为64/8*1024= 8192k的容量去除于每个扇区的大小就是一共有多少块了!

这里写图片描述


三、esp8266代码在存储芯片25q系列的分布;


上面我们已经很清晰地了解了这个存储芯片的分布,那么我们的esp8266是怎么分布在里面的代码的呢?下面,我以esp8266-12f的支持OTArtos3.0 sdk 版本工程为例,详细讲解下:

3.1 支持ota的分区

     我们知道, rtos3.0 sdk 版本的ota分区是可以自定义的,根据官方文档,比如官方默认的支持OTA的分区表如下,其中主要的是 ota_0ota_1 2个应用,其中的 nvs 是非易性存储位置;

nvs,      data, nvs,     0x9000,  0x4000
otadata,  data, ota,     0xd000,  0x2000
phy_init, data, phy,     0xf000,  0x1000
ota_0,    0,    ota_0,   0x10000, 0xF0000
ota_1,    0,    ota_1,   0x110000,0xF0000

     那么,我们明显看到有2个应用程序,对应之前说法就是 user1user2 ,远程升级就是不断地从这2个程序跳转。


3.2 不支持ota的分区

     而不支持 ota 的应用分布,更加简单,分区文件如下:

nvs,      data, nvs,     0x9000,  0x6000,
phy_init, data, phy,     0xf000,  0x1000,
factory,  app,  factory, 0x10000, 0xF0000,

3.3 如何烧录

     上述的只是讲述了代码分布,但是烧录时候 ,是怎么烧录的呢?以支持 ota 为例,我们使用 downloadTools 工具时候,如下:

文件烧录位置作用
BootLoader.bin0程序引导
patitions.bin0x8000分区文件 cvs 配置文件
ota_0.bin0x10000应用程序

     也许你会问,前面2个bin文件如何生成的?第一个是引导文件,一般各个sdk版本不一样,默认生成,必须烧录,而分区文件是为了明确告诉系统 各个分区文件的分布;


四、如何把 cvs 文件编译成bin文件


     这里为什么要引进 cvs 文件?csv(逗号分隔值)是一种用来存储数据的纯文本文件,非常适合存储小型的纯文本数据,我们一般要外部引进数据也就是文本数据了,包括字符集、图片编码;

     其实,我们的分区文件也是 .csv 文件,在编译过程中,也是把它编译成bin文件,然后烧录进去;

     不啰嗦了,直接进去整体,首先,我们定义一个 userInfo.csv 文件,然后从代码读取其中的数值,文件内容如下:

key,type,encoding,value
user-info,namespace,,
Name,data,string,xuhong
Age,data,u8,18
Csdn,data,string,https://blog.csdn.net/xh870189248
GitHub,data,string,https://github.com/xuhongv

     可以看到有 NameAgeCsdnGitHub这几个字段,进一步画成表格如下:

类型
Namexuhong字符串
Age18uint8
Csdnhttps://blog.csdn.net/xh870189248字符串
GitHubhttps://github.com/xuhongv字符串

     如下操作,直接把 cvs 文件编译成bin文件了。

$IDF_PATH/components/nvs_flash/nvs_partition_generator/nvs_partition_gen.py --input userInfo.csv --output my_single_mfg.bin --size 0x4000

     这里,我给个截图:
在这里插入图片描述


五、自定义分区表


     既然我们的程序要引进读取外部的bin文件数据,所以我们必须重新自定义分区表,比如我这样:

nvs,      data, nvs,     0x9000,  0x4000
otadata,  data, ota,     0xd000,  0x2000
phy_init, data, phy,     0xf000,  0x1000
ota_0,    0,    ota_0,   0x10000, 0xF0000
fctry,    data, nvs,     0x100000,0x4000
ota_1,    0,    ota_1,   0x110000,0xF0000

     自定义分区表特别要注意和你的硬件相对应,没有那么大的头就别戴那么大的帽子,这里说的意思是:flash芯片的大小决定这个分区是否有效,否则有意想不到的事情发现。

     上面的分区表把 25q16 系列的 512个扇区全部用完了,怎么看?我教你一招,直接看最后一个文件存储位置 0x110000 ,这个数值除于 1000 就是第几个扇区了, 0x110000 / 1000 = 0x110 换成十进制就是272,而 0xF0000 / 1000 = 0xF0 十进制就是 240 , 您看,第272个扇区加上240恰好是 512

     你还会问为什么 25q16 是一共512个扇区?请看文章上面的总结;

     温馨提示:这个分区仅适合 25q16 flash芯片或更大容量,而 25q8是不适合的,平时的 esp8266-01s 就是典型的 25q8 flash;

     我再一步为大家写来了图,详细说明用这个分区文件编译之后的程序存储位置:

     烧录走起,下面仅仅给出是userInfo.csv 文件之后的bin文件, 位置是 0x100000,这个在自定义分区文件定义好了:
在这里插入图片描述


六、如何读取userInfo.csv文件


     前面我们已经把 userInfo.csv 文件编译成了bin二进制文件,下面就直接贴代码,如何从代码读取:

     特别注意2个参数,下面的宏定义 user-info 是在 userInfo.csv 文件,下面的宏定义 fctry 是在自定义分区文件里面

//这个宏的数值是从 自定义分区表获取
#define MFG_PARTITION_NAME "fctry"
//这个宏的数值是从 csv文件定义获取
#define NVS_PRODUCT "user-info"

/**
 * @description:  读取数据进去nvs里面的任务
 * @param {type} null
 * @return: 
 */
static void Task_NVS_Read(void *pvParameters)
{

    ESP_LOGI(TAG, "--------------------------- Start Task_NVS_Read  --------------------------");
    nvs_handle mHandleNvsRead;
    uint8_t nvs_i8 = 0;
    esp_err_t err;
    //初始化分区
    if ((err = nvs_flash_init_partition(MFG_PARTITION_NAME)) != ESP_OK)
    {
        ESP_LOGE(TAG, "NVS Flash init %s failed, Please check that you have flashed fctry partition!!!", MFG_PARTITION_NAME);
        vTaskDelete(NULL);
    }
    //NVS操作的句柄,类似于 rtos系统的任务创建返回的句柄!
    err = nvs_open_from_partition(MFG_PARTITION_NAME, NVS_PRODUCT, NVS_READONLY, &mHandleNvsRead);
    //打开数据库,打开一个数据库就相当于会返回一个句柄
    if (err != ESP_OK)
    {
        ESP_LOGE(TAG, "Open NVS Table fail");
        vTaskDelete(NULL);
    }
    else
    {
        ESP_LOGI(TAG, "Open NVS Table ok.");
    }

    //读取 字符串 --> 名字
    char data[65];
    uint32_t len = sizeof(data);
    err = nvs_get_str(mHandleNvsRead, "Name", data, &len);

    if (err == ESP_OK)
        ESP_LOGI(TAG, "get str data = %s ", data);
    else
        ESP_LOGI(TAG, "get str data error");

    //读取 u8 年龄
    err = nvs_get_u8(mHandleNvsRead, "Age", &nvs_i8);
    if (err == ESP_OK)
        ESP_LOGI(TAG, "get nvs_i8 = %d ", nvs_i8);
    else
        ESP_LOGI(TAG, "get nvs_i8 error");

    //读取 字符串 --> Csdn博客地址
    char Csdn[65];
    uint32_t lenCsdn = sizeof(Csdn);
    err = nvs_get_str(mHandleNvsRead, "Csdn", Csdn, &lenCsdn);

    if (err == ESP_OK)
        ESP_LOGI(TAG, "get str data = %s ", Csdn);
    else
        ESP_LOGI(TAG, "get Csdn data error");

    //读取 字符串 --> GitHub地址
    char GitHub[65];
    uint32_t lenGitHub = sizeof(GitHub);
    err = nvs_get_str(mHandleNvsRead, "GitHub", GitHub, &lenGitHub);

    if (err == ESP_OK)
        ESP_LOGI(TAG, "get GitHub data = %s ", GitHub);
    else
        ESP_LOGI(TAG, "get GitHub data error");

    //关闭数据库,关闭面板!
    nvs_close(mHandleNvsRead);

    ESP_LOGI(TAG, "--------------------------- End Task_NVS_Read  --------------------------");
    vTaskDelete(NULL);
}

七、其他


  • 看看我们的打印,确实如实打印出了自定义的 userInfo.csv 文件:在这里插入图片描述

  • 本博文对应的demo下载链接:点击我


另外,不要把我的博客作为学习标准,我的只是笔记,难有疏忽之处,如果有,请指出来,欢迎留言哈!也欢迎加群讨论!

  • 玩转esp8266带你飞、付费QQ群,不喜的朋友勿喷勿加:434878850
  • esp8266源代码学习汇总(持续更新,欢迎star):https://github.com/xuhongv/StudyInEsp8266
  • esp32源代码学习汇总(持续更新,欢迎star):https://github.com/xuhongv/StudyInEsp32
  • 关注下面微信公众号二维码,干货多多,第一时间推送!
    在这里插入图片描述