物联网整体项目初始化

Tutorial: 卓越工程师 Category: 嵌入式 Published: 2026-10-23 11:05:29 Views: 0 Likes: 0 Comments: 0

170.5物联网整体项目初始化

源码范围说明:本节完成的是机智云数据点设计和 STM32CubeMX 外设配置,视频没有开始编写应用层 C 代码。课程末尾只让 CubeMX 生成初始化文件,因此这里不把自动生成的 HAL 初始化函数或后面课程才加入的业务逻辑抄到标题下方。正文使用课程生成包中的数据点定义、初始 .ioc 和后续完成工程进行核对,只整理本节实际配置的参数。

一、物联网整体项目初始化

本节开始搭建完整物联网项目。与前面的单一温湿度 Demo 相比,新项目要同时处理两组温湿度、光照、烟雾、灯和窗帘,并通过 ZigBee 链路连接 STM32 与另一块 51 单片机。

手机调试 App / 机智云
          │ Wi-Fi
     ESP8266 GAgent
          │ USART2
        STM32
   ┌──────┼─────────────┐
本地传感器/LED       USART3
                     │
                ZigBee 模组
                     ··· 无线 ···
                ZigBee 模组
                     │ UART
                  51 单片机
               远端传感器/执行器

初始化工作分成两层:

  1. 在机智云平台定义产品能力,让平台生成与数据点一一对应的协议代码。
  2. 在 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 代码包。课程操作为:

  1. 登录机智云开发者中心,创建新产品。
  2. 类别和自定义方案选择“其他”。
  3. 产品名称填写“物联网项目 test”(名称只用于识别,可按自己的项目调整)。
  4. 连接类型继续选择单品 Wi-Fi/ESP8266,并采用独立 MCU 方案。
  5. 创建数据点、应用配置后,再进入 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可写valueled1App 下发的灯控制
temp2数值0~60,分辨率 1只读valuetemp2第 2 组温度
humi2数值0~100,分辨率 1只读valuehumi2第 2 组湿度
led2布尔0/1只读valueled2第 2 路灯状态上报
curtain布尔0/1可写valuecurtainApp 下发的窗帘控制

视频用“客厅”和“卧室”作为两组设备的显示区域。转写对个别中文显示名识别不稳定,复建项目时应按自己的实际房间命名;真正必须与课程生成源码保持一致的是上表中的标识名、类型、量程和读写方向。

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 GAgentUSART2 / PA2、PA3机智云运行时协议通信,9600 bit/s
调试日志USART1 / PA9、PA10日志串口,115200 bit/s
ZigBee 模组USART3 / PB10、PB11与另一端节点收发数据,9600 bit/s
1.6.1 温湿度初始化定时器

打开新下载包的 .ioc 后,课程先确认:

  1. 目标模板和已有外设没有异常。
  2. 系统时钟为 72 MHz。
  3. Project Manager → Code Generator 中勾选“为每个外设生成独立的 .c/.h 文件”。初始生成包的 ProjectManager.CoupleFile=false,修改后的工程为 true。
  4. 确认正在编辑完整物联网新工程,而不是前一节的温湿度 Demo。

机智云模板选择的是 STM32F103C8Tx/LQFP48,而课程开发板原理图对应 STM32F103ZET6/LQFP144。与前两节相同,这只能作为课程模板和移植起点;正式工程应按真实 ZE 芯片重建并核对启动文件、容量宏、链接空间、下载算法与所有引脚,不能因系统同为 72 MHz 就忽略型号和封装差异。

1.6.2 初始化定时器一

原笔记中的“d11d9、71、655、35”等不是寄存器名,而是转写把界面参数粘在了一起。TIM1 的课程配置为:

参数值含义
Clock SourceInternal Clock使用片内定时器时钟
Prescaler71实际分频为 71 + 1 = 72
Counter ModeUp向上计数
Counter Period6553516 位计数器最大周期
Clock DivisionDIV1不再分割定时器时钟
Repetition Counter0不增加重复次数
Auto-reload preloadDisableARR 不使用预装载缓冲

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 引脚连接方式有效电平
LED0PB53.3 V → LED/限流电阻 → PB5PB5 输出低电平时点亮
LED1PE53.3 V → LED/限流电阻 → PE5PE5 输出低电平时点亮

注意,原理图元件位号与网络名称并不完全相同,学习时应以 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:

串口引脚波特率帧格式课程用途
USART1PA9/TX、PA10/RX1152008-N-1调试日志
USART2PA2/TX、PA3/RX96008-N-1STM32 ↔ ESP8266 GAgent
USART3PB10/TX、PB11/RX96008-N-1STM32 ↔ 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 区域,业务代码最好放在用户区或独立文件中,避免被生成器覆盖。

参考资料