物联网整体项目初始化
170.5物联网整体项目初始化
源码范围说明:本节完成的是机智云数据点设计和 STM32CubeMX 外设配置,视频没有开始编写应用层 C 代码。课程末尾只让 CubeMX 生成初始化文件,因此这里不把自动生成的 HAL 初始化函数或后面课程才加入的业务逻辑抄到标题下方。正文使用课程生成包中的数据点定义、初始
.ioc和后续完成工程进行核对,只整理本节实际配置的参数。
一、物联网整体项目初始化
本节开始搭建完整物联网项目。与前面的单一温湿度 Demo 相比,新项目要同时处理两组温湿度、光照、烟雾、灯和窗帘,并通过 ZigBee 链路连接 STM32 与另一块 51 单片机。
手机调试 App / 机智云
│ Wi-Fi
ESP8266 GAgent
│ USART2
STM32
┌──────┼─────────────┐
本地传感器/LED USART3
│
ZigBee 模组
··· 无线 ···
ZigBee 模组
│ UART
51 单片机
远端传感器/执行器
初始化工作分成两层:
- 在机智云平台定义产品能力,让平台生成与数据点一一对应的协议代码。
- 在 CubeMX 中为实际传感器、LED 和通信链路分配 STM32 外设与引脚。
这两层必须一致。平台定义了数据点但 MCU 不采集或不执行,App 只能看到空值;MCU 接好了传感器但平台没有相应数据点,生成协议也不知道怎样上报。
1.1 固件修改
课程提醒:ESP8266-01S 烧入机智云 GAgent 固件后,原来的安信可 AT 固件功能不再存在。这里应准确理解成“Flash 中的固件被替换”,而不是芯片从此无法恢复:
- GAgent 与 AT 固件是两套不同程序,不能在运行时用普通 AT 指令互相切换。
- 只要模组硬件正常、仍能进入串口下载模式,并且找到与模组 Flash 容量和布局匹配的固件,就可以擦除后重新烧入合适的 AT 固件。
- 重新购买一块模组只是课程给出的省事方案,不是技术上的唯一方案。
- 烧写前应备份需要保留的固件或配置,并核对启动脚、电源、下载地址与固件版本;错误镜像或错误偏移会让模组无法启动。
视频要求购买 ESP-01S,并强调不要把 ESP-01 当成同一型号。安信可官方资料也把 ESP-01、ESP-01S、ESP-01M 等列为不同产品,选购时应按课程载板、引脚和目标固件确认完整型号,不能只看“ESP8266”。课程并没有讲 ESP-01M,原笔记把它加进对比属于识别误差。
ESP-01S 官方规格还给出两个重要电气条件:供电范围为 3.0~3.6 V,持续发送时峰值电流可达约 300 mA。因此不能用 STM32 普通 GPIO 给模组供电,也不能直接接 5 V;应使用稳定的 3.3 V 电源并共地。课程开发板原理图的 ESP8266 插座也是 3.3 V 供电。
1.2 机智云平台设置
1.2.1 创建物联网项目
完整项目的数据点集合与上一节温湿度 Demo 不同,因此要在开发者中心新建产品,并基于新产品重新生成 MCU 代码包。课程操作为:
- 登录机智云开发者中心,创建新产品。
- 类别和自定义方案选择“其他”。
- 产品名称填写“物联网项目 test”(名称只用于识别,可按自己的项目调整)。
- 连接类型继续选择单品 Wi-Fi/ESP8266,并采用独立 MCU 方案。
- 创建数据点、应用配置后,再进入 MCU 开发生成 STM32F103C8x 代码包。
机智云代码生成器根据当前产品的数据点生成结构体字段、上下行协议、数值换算和控制事件。因此,每次新建产品或修改数据点后,都不能继续把旧产品的生成包当成完全兼容版本。平台与本地代码应保持同一产品、同一数据点版本。
1.2.2 编辑标识名
“标识名”和“显示名”用途不同:
- 标识名进入协议和生成的 C 成员,例如
temp1最终对应valuetemp1,应使用稳定的 ASCII 名称。 - 显示名供 App 界面阅读,可以写“客厅温度”“卧室湿度”等中文描述。
- 标识名修改后会影响生成代码,显示名修改通常只影响用户界面的含义和显示。
课程生成包可确认本项目共有 9 个数据点:
| 标识名 | 数据类型 | 范围/取值 | 读写类型 | 生成结构体成员 | 作用 |
|---|---|---|---|---|---|
temp1 | 数值 | 0~60,分辨率 1 | 只读 | valuetemp1 | 第 1 组温度 |
humi1 | 数值 | 0~100,分辨率 1 | 只读 | valuehumi1 | 第 1 组湿度 |
sun | 数值 | 0~100,分辨率 1 | 只读 | valuesun | 光照百分比 |
smoke | 布尔 | 0/1 | 只读 | valuesmoke | 烟雾数字状态 |
led1 | 布尔 | 0/1 | 可写 | valueled1 | App 下发的灯控制 |
temp2 | 数值 | 0~60,分辨率 1 | 只读 | valuetemp2 | 第 2 组温度 |
humi2 | 数值 | 0~100,分辨率 1 | 只读 | valuehumi2 | 第 2 组湿度 |
led2 | 布尔 | 0/1 | 只读 | valueled2 | 第 2 路灯状态上报 |
curtain | 布尔 | 0/1 | 可写 | valuecurtain | App 下发的窗帘控制 |
视频用“客厅”和“卧室”作为两组设备的显示区域。转写对个别中文显示名识别不稳定,复建项目时应按自己的实际房间命名;真正必须与课程生成源码保持一致的是上表中的标识名、类型、量程和读写方向。
1.2.3 灯的读写类型
课程把 led1 设置为“可写”布尔数据点,因为控制方向是 App/云端向 MCU 下发:
App 开关 → 机智云 → ESP8266 → STM32 → 实体 LED
可写不等于“只往下发、不上报”。MCU 收到命令后仍应执行硬件动作并维护当前状态,让 App 能看到实际结果。0 和 1 只是协议值,究竟哪一个代表实体灯亮,要结合业务定义和硬件电平判断。
本地生成协议只有 EVENT_led1 和 EVENT_curtain 两个下行控制事件,反向证明 led1 与 curtain 是可写项。led2 没有生成下行事件,说明视频确实把它保留成只读。若需求原本是让 App 控制第二盏灯,这个设置并不满足需求,应在平台把 led2 改成可写后重新生成代码;不能只在 C 文件中手工增加一个同名事件。
1.2.4 ZigBee通信
原笔记把 ZigBee 写成“单片机内部通信机制”,这是错误的。此项目中有两段不同链路:
STM32 USART3 ↔ 本端 ZigBee 串口模组 ···无线··· 远端 ZigBee 串口模组 ↔ 51 UART
- UART 是 STM32/51 与各自 ZigBee 模组之间的有线串行接口。
- ZigBee 是两个外部无线模组之间的通信链路,不是 STM32 或 51 内部自带的一段通信。
- 机智云只需要表示最终业务能力,例如远端温湿度、灯和窗帘;不必为“ZigBee 传输过程”额外创建一个数据点。
- ZigBee 与机智云在系统中并非完全无关:它不直接使用机智云协议,但它负责把远端数据送到 STM32,STM32 再映射到机智云数据点。
1.2.5 温湿度
第二组温湿度使用标识名 temp2、humi2,对应数值范围仍为 0~60 和 0~100,分辨率均为 1。课程用它们表示另一区域的温湿度,后续由 51 单片机采集并通过 ZigBee/UART 送给 STM32。
这里的“分辨率 1”表示机智云数据点按整数步进,并不等于传感器自身的精度、误差或真正分辨能力。范围也只是协议允许值;若传感器失败产生异常数据,应用代码仍需要判断,不能依靠平台范围替代传感器校验。
1.2.6 灯
课程新建 led2,显示为另一房间的灯,数据类型为布尔值。但视频没有把读写类型改成可写,生成包也确认它是只读数据点:它可以由设备上报状态,却不能像 led1 那样产生 App 下发控制事件。
这可能是课程刻意把第二路灯当状态项,也可能是配置时遗漏;在没有后续视频依据前,精教版只记录实际结果,不替课程擅自改成可写。设计自己的项目时,应先明确需求:
- 只展示灯的状态:只读合理。
- 要让 App 控灯:必须使用可写,并处理下发事件。
1.2.7 窗帘
窗帘标识名最终为 curtain,不是转写中的 CURT。它被设置为可写布尔数据点,因为 App 要向设备下发开/关动作。生成代码中的 EVENT_curtain 也验证了这个方向。
布尔值只能表达两种状态,适合课程中的“开/关”。若产品需要打开、停止、关闭三种命令,或者需要 0%~100% 开合度,布尔类型就不够,应改用枚举或数值数据点,并重新生成协议代码。
1.3 开发向导
数据点保存后,课程在开发向导中选择乐鑫(Espressif)模组信息,然后进入 MCU 开发。原笔记的“乐心”是语音识别错误。
生成流程的逻辑是:
保存数据点
↓
选择独立 MCU 方案和 STM32F103C8x 模板
↓
填写自己产品的生成凭据
↓
机智云按当前数据点生成专属代码包
生成包不是完整成品。它已完成机智云协议封装、数据点字段和控制事件框架,但不知道传感器接在哪个引脚,也没有本项目的 DHT11、光敏、烟雾、LED 和 ZigBee 业务实现。本节后半段的 CubeMX 配置只是补上硬件初始化,后续课程仍要加入应用逻辑。
1.4 添加密码和密钥
视频在 MCU 开发页面复制产品凭据后生成代码。课程口述的“密码和密钥”应理解为页面要求的 Product Key/Product Secret 等当前产品凭据,具体字段以平台页面为准。
- 每个学习者都应使用自己创建产品的值,不能复用课程作者的凭据。
- Product Key 用于标识产品;Product Secret 属于敏感鉴权信息,不应出现在公开截图、笔记或代码片段中。
- 若真实 Secret 已经提交到公开仓库,应到平台侧轮换或重新生成;只把本地文本打码不能撤销已泄露的凭据。
- 数据点发生变化后,应重新生成匹配的新包,而不是只换密钥字符串。
1.5 下载内容保存位置
课程新建本地文件夹保存下载的代码包,再解压并打开工程。文件夹名字只是个人组织方式,不是程序的固定要求。本仓库保存了两份便于对照的内容:
机智云初始代码包.zip:平台按 9 个数据点刚生成的基线。物联网32/:经过本节 CubeMX 配置以及后续课程继续开发后的完成工程。
原笔记的“使用 q 命令打开”是识别错误。应使用:
- Keil 打开
MDK-ARM/STM32F103C8x.uvprojx,用于编译和调试。 - STM32CubeMX 打开
STM32F103C8x.ioc,用于修改时钟、外设与引脚配置。
首次修改前先编译平台原始工程,可以建立一个可工作的基线;若修改后出错,就能判断问题来自原包还是新配置。不要直接在压缩包中编辑,也应避免把多个同名解压目录混在一起。
1.6 初始化需求
本节需求与 STM32 外设的对应关系为:
| 业务需求 | CubeMX 外设/引脚 | 本节用途 |
|---|---|---|
| 本地 DHT11 温湿度 | TIM1 | 为 DHT11 驱动提供微秒级延时基础 |
| 光敏电阻 | ADC1_IN1 / PA1 | 采集模拟电压 |
| 烟雾传感器 | PA4 GPIO Input | 读取数字告警输出 |
| 板载灯 | PB5 GPIO Output | 控制一只板载 LED |
| ESP8266 GAgent | USART2 / PA2、PA3 | 机智云运行时协议通信,9600 bit/s |
| 调试日志 | USART1 / PA9、PA10 | 日志串口,115200 bit/s |
| ZigBee 模组 | USART3 / PB10、PB11 | 与另一端节点收发数据,9600 bit/s |
1.6.1 温湿度初始化定时器
打开新下载包的 .ioc 后,课程先确认:
- 目标模板和已有外设没有异常。
- 系统时钟为 72 MHz。
- Project Manager → Code Generator 中勾选“为每个外设生成独立的
.c/.h文件”。初始生成包的ProjectManager.CoupleFile=false,修改后的工程为true。 - 确认正在编辑完整物联网新工程,而不是前一节的温湿度 Demo。
机智云模板选择的是 STM32F103C8Tx/LQFP48,而课程开发板原理图对应 STM32F103ZET6/LQFP144。与前两节相同,这只能作为课程模板和移植起点;正式工程应按真实 ZE 芯片重建并核对启动文件、容量宏、链接空间、下载算法与所有引脚,不能因系统同为 72 MHz 就忽略型号和封装差异。
1.6.2 初始化定时器一
原笔记中的“d11d9、71、655、35”等不是寄存器名,而是转写把界面参数粘在了一起。TIM1 的课程配置为:
| 参数 | 值 | 含义 |
|---|---|---|
| Clock Source | Internal Clock | 使用片内定时器时钟 |
| Prescaler | 71 | 实际分频为 71 + 1 = 72 |
| Counter Mode | Up | 向上计数 |
| Counter Period | 65535 | 16 位计数器最大周期 |
| Clock Division | DIV1 | 不再分割定时器时钟 |
| Repetition Counter | 0 | 不增加重复次数 |
| Auto-reload preload | Disable | ARR 不使用预装载缓冲 |
TIM1 时钟为 72 MHz,因此:
$ f_{CNT}=\frac{72\ \text{MHz}}{71+1}=1\ \text{MHz} $
每个计数约为 $1\ \mu s$,连续计满一圈约为 $65.536\ \text{ms}$,可供课程 DHT11 驱动构造微秒延时。Auto-reload preload=Disable 不等于“禁用 TIM1”或“只计数一次”;它只说明 ARR 更新不经过预装载缓冲。
1.6.3 光敏电阻初始化
USART2 已使用 PA2/PA3,所以不能再把 ADC1_IN2/IN3 分配到这些引脚。课程最终选择:
PA1 → ADC1_IN1;- Regular Conversion Rank 1;
- 采样时间
239.5 cycles; - 单通道转换。
视频口述把 Continuous Conversion Mode 打开,但仓库后续完成工程的 .ioc 和 adc.c 均为 DISABLE,应用代码采用每次 HAL_ADC_Start() 后轮询一次的方式。两者不是同一个概念:
- Scan Conversion 用于扫描多个规则通道;本项目此处只有一个通道,不需要扫描序列。
- Continuous Conversion 会在一次启动后不断转换。
- 单次模式则由应用每次需要数据时重新启动一次;后续完成工程采用的就是这种方式。
因此,复现本节视频画面时会看到教师尝试开启连续转换,但理解最终工程时应以 DISABLE + 软件触发单次采样 为准,不能把转写中的“连续扫描”当成既定最终参数。
采样时间不是越大越“高级”。ADC 内部采样电容需要通过外部信号源充电;光敏电阻分压网络的源阻抗可能较高,较长采样时间有助于电压稳定。完成工程使用 ADC 时钟 12 MHz、采样 239.5 周期,单次总转换时间约为:
$ t_{conv}=\frac{239.5+12.5}{12\ \text{MHz}}\approx21\ \mu s $
还必须保证 PA1 模拟电压位于 MCU 的允许输入范围内,不能把 5 V 模拟输出直接送入以 3.3 V 供电的 ADC。
烟雾传感器使用 PA4,模式为 GPIO Input,用户标签为 SMOKE。这说明课程读取的是传感器模块的数字输出,而不是模拟浓度值。最终工程将它配置为 No Pull,所以输入电平应由外部模块明确驱动;高电平还是低电平代表报警,必须查所用烟雾模块的原理图或实测,不能只看变量名猜测。
1.6.4 灯的初始化
课程查看 ZE 开发板原理图后,确认两只用户 LED 的 MCU 网络为:
| 原理图网络 | MCU 引脚 | 连接方式 | 有效电平 |
|---|---|---|---|
LED0 | PB5 | 3.3 V → LED/限流电阻 → PB5 | PB5 输出低电平时点亮 |
LED1 | PE5 | 3.3 V → LED/限流电阻 → PE5 | PE5 输出低电平时点亮 |
注意,原理图元件位号与网络名称并不完全相同,学习时应以 MCU 旁的 PB5 → LED0、PE5 → LED1 网络为准。课程 CubeMX 又把 PB5 的 User Label 命名为 LED1,这只是软件标签,并不改变板上 PB5 实际连到 LED0 网络的事实。
C8T6 的 LQFP48 封装没有 PE5,因此课程模板只能先配置 PB5:
- GPIO Output;
- Push-Pull;
- 初始电平 High;
- User Label 为
LED1。
因为板载 LED 为低电平点亮,初始化为高电平可以让 LED 上电默认熄灭。若改回正确的 ZE 工程,才可以按真实硬件继续配置 PE5;不能在 C8 工程中凭空定义一个封装不存在的 PE5。
1.6.5 ZigBee通信初始化
课程为 ZigBee 串口模组启用 USART3:
| 串口 | 引脚 | 波特率 | 帧格式 | 课程用途 |
|---|---|---|---|---|
| USART1 | PA9/TX、PA10/RX | 115200 | 8-N-1 | 调试日志 |
| USART2 | PA2/TX、PA3/RX | 9600 | 8-N-1 | STM32 ↔ ESP8266 GAgent |
| USART3 | PB10/TX、PB11/RX | 9600 | 8-N-1 | STM32 ↔ ZigBee 串口模组 |
原转写中的“801”应为常见的 8-N-1:8 个数据位、无校验、1 个停止位。要正确通信,STM32 USART3、两只 ZigBee 模组的串口侧以及 51 单片机 UART 都必须使用兼容的波特率和帧格式;两端还要 TX/RX 交叉连接并共地。仅仅都写成 9600,并不能保证无线信道、网络参数和自定义数据帧协议也一致。
这里还有一个视频未强调的引脚冲突:机智云初始 C8 模板把 KEY1 放在 PB10,而 USART3 默认也要使用 PB10 作为 TX。启用 USART3 后,PB10 不能同时继续当普通按键输入。后续完成工程已把 KEY1 移到 PC13;如果自己复现,也必须明确重映射按键、重映射串口或取消其中一个功能,并同步修改按键代码,不能让两个外设争用同一引脚。
配置 ADC 后 CubeMX 出现时钟警告,是因为 APB2 为 72 MHz 时,ADC 默认 /2 得到 36 MHz,超过 STM32F103x8/xB 数据手册规定的 14 MHz 上限;/4 得到 18 MHz,仍然过高。课程改成 /6 后:
$ f_{ADC}=\frac{72\ \text{MHz}}{6}=12\ \text{MHz}<14\ \text{MHz} $
这样才处于规格范围内。解决“小红叉”的依据不是界面不再报警,而是计算后的时钟满足芯片数据手册。
最后点击 Generate Code,只表示 CubeMX 根据 .ioc 生成或更新 ADC、TIM1、USART3 和 GPIO 初始化。它没有自动完成以下工作:
- DHT11 驱动与正确采样周期;
- ADC 启动、校准、读取和光照百分比换算;
- 烟雾有效电平与告警逻辑;
- ZigBee 收发中断、组帧、校验和超时;
- 机智云上下行数据点与实体硬件的映射。
这些才是后续课程要加入的应用代码。重新生成时还要留意 CubeMX 的 USER CODE BEGIN/END 区域,业务代码最好放在用户区或独立文件中,避免被生成器覆盖。
参考资料
- 机智云 MCU 代码自动生成器说明:核对数据点决定生成包、独立 MCU 方案、上下行处理位置和二次开发边界。
- 安信可 ESP8266 系列资料中心 与 ESP-01S 产品规格书:核对 ESP-01/ESP-01S 是独立型号、ESP-01S 的供电范围和峰值电流要求。
- ST:STM32F103x8/xB 数据手册:核对 ADC 时钟最高 14 MHz、ADC 时钟分频和转换时序。
- 本地课程配套 STM32F103ZE 开发板原理图:核对 PB5/PE5 板载 LED、低电平点亮和 ESP8266 的 3.3 V 供电。
- 本地 机智云初始代码包:核对 9 个数据点、初始 KEY1/PB10 与生成前的
.ioc配置。 - 本地后续完成工程 STM32F103C8x.ioc、gizwits_protocol.h、adc.c 与 usart.c:核对本节配置在完成工程中的落地结果及后续变化。