资讯动态

STM32+EC20通过AT指令对接ONENET MQTT实战指南

发布时间:2026/9/16 18:23:02 来源:尧图企业网站定制
简介本资源是一套基于STM32F与EC20 4G模块实现温湿度数据上云的完整嵌入式物联网开发工程面向嵌入式初学者、物联网开发者及高校课程实践者解决STM32端MQTT协议接入ONENET云平台的核心技术难点。压缩包含229个文件以64个C语言源码.c和52个头文件.h为主体辅以23个编译中间文件.o、23个依赖文件.d、22个链接映射文件.crf及Keil MDK工程配置.uvprojx、.uvoptx、.axf、.hex等总大小4.82MB结构完整覆盖硬件驱动、MQTT客户端移植、传感器数据采集与JSON封装、网络重连机制等关键模块。已有351人学习下载提供可直接编译运行的Keil工程含DHT/SHT系列传感器适配代码、EC20 AT指令交互逻辑、ONENET MQTT鉴权与主题发布实现并附带bat一键清理脚本与调试配置文件便于快速验证与二次开发。1. 用 STM32F103 EC20 模组走标准 MQTT 协议把 DHT22 温湿度数据稳定推到 ONENET——不是调库跑通就行而是要清楚 AT 指令链怎么断、MQTT 主题怎么构造、ONENET 设备鉴权怎么验很多工程师拿到“STM32F_EC20_MQTT提交温湿度数据到ONENET”这个需求第一反应是找现成例程改改 GPIO、填填 IP、塞进一个mqtt_publish()就完事。但真实产线场景中90% 的失败不是代码写错而是卡在 EC20 的 AT 指令状态机没对齐、ONENET 的 device_id 和 APIKey 混用、或 MQTT payload 格式被平台静默丢弃。本篇不讲 HAL 库封装技巧也不堆#define宏而是按一线嵌入式工程师调试真实模组的路径展开从 EC20 上电后第一条AT响应开始逐条验证网络附着、TCP 连接、MQTT 登录、主题订阅与发布四层状态重点拆解 ONENET 要求的 JSON 数据体结构含 timestamp 字段是否强制、value 字段类型限制、EC20 的ATQMTPUB指令参数含义尤其是 QoS1 时的重传窗口与超时判定以及 DHT22 读取后必须做的 CRC 校验与数值范围过滤——这些细节在 ONENET 文档里藏得深但在实际项目中决定设备上线率。适合已能点亮 LED、但第一次用 4G 模组对接云平台的 STM32 开发者也适合需要排查“数据发了但平台收不到”问题的固件工程师。2. EC20 模组初始化与网络附着用 AT 指令链确认 SIM 卡状态、信号强度与 PDP 上下文激活EC20 不是即插即用的 USB 网卡它是一台独立运行的 LTE 终端必须通过 AT 指令完成完整的协议栈初始化。常见误区是跳过ATCPIN?直接发ATCGATT?结果卡在 “CME ERROR: 10”SIM 未就绪。以下指令序列是经过量产验证的最小可靠流程每步必须收到OK或明确预期响应才执行下一步2.1 串口基础配置与模组唤醒EC20 默认波特率 115200但部分批次出厂为 9600首次通信前需先发三连AT探测AT AT AT若返回OK说明串口连通若无响应检查 STM32 的 USARTx 初始化是否启用USART_CR1_UE和USART_CR1_TE且 TX 引脚无上拉冲突。确认连通后关闭回显并设置波特率ATE0 # 关闭命令回显减少干扰 ATIPR115200 # 强制设为 115200避免速率不匹配提示ATE0必须在ATIPR前执行否则新波特率生效后旧串口会失联。若 STM32 使用 DMA 发送需在改波特率后重新初始化 UART 外设。2.2 SIM 卡与网络注册状态校验ATCPIN? # 检查 SIM 卡 PIN 状态返回 CPIN: READY 表示正常 ATCSQ # 查询信号质量格式为 CSQ: rssi,berrssi 值 ≥ 10 才可靠0~31 对应 -113dBm ~ -51dBm ATCREG? # 查看网络注册状态返回 CREG: 0,1 或 CREG: 0,5 表示已注册到 LTE 网络注意0,1 是 home network0,5 是 roaming均可用若ATCPIN?返回CPIN: SIM PIN需先解锁ATCPIN1234默认 PIN以 SIM 卡实际为准若ATCSQ中 rssi 5检查天线连接与金属屏蔽罩距离。2.3 PDP 上下文激活与 IP 获取ONENET 要求设备通过公网 IP 连接其 MQTT 服务器mqtt.heclouds.com:1883必须激活 PDP 上下文获取 IPv4 地址ATCGDCONT1,IP,CMNET # 设置 APN中国移动为 CMNET电信为 CTNET联通为 3GNET ATCGACT1,1 # 激活 PDP 上下文 1 ATCGPADDR1 # 查询分配的 IP返回 CGPADDR: 1,10.101.23.45注意ATCGDCONT的第三个参数是 APN 字符串必须与运营商一致。若返回ERROR检查 SIM 卡是否开通 4G 数据业务若ATCGPADDR返回空说明 PDP 未激活成功需重发ATCGACT1,1并等待 5 秒。3. MQTT 连接 ONENET解析 device_id、APIKey 与 CONNECT 报文构造逻辑ONENET 的 MQTT 接入不是标准用户名/密码模式而是基于设备标识与签名的鉴权机制。核心在于理解三个关键字段的来源与组合规则device_id设备唯一标识、api_key平台生成的密钥、timestamp时间戳单位秒有效期 180 秒。这三者共同参与 CONNECT 报文的username和password字段生成任何一环出错都会导致CONNACK 0x05Connection Refused, not authorized。3.1 在 ONENET 平台创建设备并获取必要凭证登录 ONENET 物联网平台https://open.iot.10086.cn/进入「开发管理」→「产品」→「设备管理」→「添加设备」选择「MQTT」协议填写设备名称如stm32_dht22_001系统自动生成device_id如789456123在「设备详情」页点击「生成 APIKey」选择「永久有效」或「365 天」复制生成的字符串如a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6记录该设备的product_id产品 ID用于构造 topic和device_id。提示api_key不是密码而是用于签名计算的密钥切勿在日志中明文打印。ONENET 要求username格式为device_id,product_id,timestamp三者用英文逗号分隔password为MD5(api_key timestamp)的 32 位小写十六进制字符串。3.2 在 STM32 上动态生成 CONNECT 凭证假设当前时间为17170234562024-05-30 14:57:36device_id789456123product_id123456api_keya1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6则username 789456123,123456,1717023456password MD5(a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p61717023456) e8f5a3b2c1d0e9f8a7b6c5d4e3f2a1b0在 STM32 固件中需实现轻量级 MD5推荐使用 TinyMD5 库仅 2KB 代码#include tinymd5.h char username[64], password[33]; uint32_t timestamp get_unix_timestamp(); // 自行实现获取 Unix 时间戳函数 sprintf(username, %s,%s,%lu, DEVICE_ID, PRODUCT_ID, timestamp); char md5_input[64]; sprintf(md5_input, %s%lu, API_KEY, timestamp); uint8_t hash[16]; md5((uint8_t*)md5_input, strlen(md5_input), hash); for(int i0; i16; i) { sprintf(password i*2, %02x, hash[i]); // 转为小写十六进制 }注意get_unix_timestamp()必须返回秒级时间戳不能是毫秒。若 STM32 无 RTC 或 NTP 同步可接受 ±30 秒误差但超过 180 秒 ONENET 会拒绝连接。3.3 EC20 发起 MQTT 连接指令EC20 使用ATQMTPCONNECT指令建立 MQTT 连接参数顺序严格ATQMTPCONNECT0,mqtt.heclouds.com,1883,60,789456123,123456,1717023456,e8f5a3b2c1d0e9f8a7b6c5d4e3f2a1b0其中0MQTT client ID 索引固定为 0mqtt.heclouds.comONENET MQTT 服务器域名不可用 IPEC20 DNS 解析依赖1883端口号60Keep Alive 时间秒ONENET 要求 ≥ 60第五、六参数为 username 和 password。成功返回QMTPCONNECT: 0,00 表示 client id0 表示 success失败返回QMTPCONNECT: 0,1认证失败或QMTPCONNECT: 0,2网络不可达。4. 构造温湿度数据并发布ONENET JSON 格式规范、DHT22 读取防错与 ATQMTPUB 参数详解数据发布不是简单拼接字符串ONENET 对 MQTT payload 有严格 JSON Schema 要求且 EC20 的ATQMTPUB指令对数据长度、QoS 级别、topic 格式均有硬性约束。常见错误是直接发{temp:25.3,humi:60.5}被平台丢弃或因 payload 超长触发 EC20 内存溢出。4.1 ONENET 要求的数据格式与 topic 规则ONENET MQTT topic 固定为$sys/{product_id}/{device_id}/thing/property/post例如$sys/123456/789456123/thing/property/postpayload 必须是 JSON 对象且必须包含data字段其值为数组每个元素为一个属性对象{ data: [ { id: temp, value: 25.3, time: 1717023456 }, { id: humi, value: 60.5, time: 1717023456 } ] }id属性标识符需与 ONENET 平台设备定义的属性 ID 一致在「设备详情」→「数据流」中配置value数值类型ONENET 严格区分number和string温湿度必须为 numbertime时间戳单位秒建议与 CONNECT 时的 timestamp 一致或更新。提示若平台未定义temp和humi属性数据会接收但不入库。务必在 ONENET 控制台提前创建这两个数据流类型选「数值型」。4.2 DHT22 读取与数据净化DHT22 易受电源波动影响单次读取可能返回无效值如temp-100,humi120。必须做两级过滤float temp, humi; if (DHT22_ReadData(temp, humi) SUCCESS) { // 假设已有驱动 // 第一级范围过滤DHT22 理论范围 -20~80℃, 0~100%RH if (temp -20.0f || temp 80.0f || humi 0.0f || humi 100.0f) { return ERROR; // 丢弃异常值 } // 第二级连续三次采样滑动平均防脉冲干扰 static float temp_buf[3] {0}, humi_buf[3] {0}; static uint8_t idx 0; temp_buf[idx] temp; humi_buf[idx] humi; idx (idx 1) % 3; temp (temp_buf[0] temp_buf[1] temp_buf[2]) / 3.0f; humi (humi_buf[0] humi_buf[1] humi_buf[2]) / 3.0f; }4.3 EC20 发布数据指令与参数避坑ATQMTPUB指令格式ATQMTPUB0,1,0,0,$sys/123456/789456123/thing/property/post,1230client id1QoS 级别0at most once, 1at least once0RETAIN 标志0false0消息 IDQoS0 时填 0QoS1 时需递增第五参数topic 字符串第六参数payload 长度字节。随后发送 payload注意必须紧跟提示符且不能换行{data:[{id:temp,value:25.3,time:1717023456},{id:humi,value:60.5,time:1717023456}]}注意EC20 对单条 payload 长度限制为 1024 字节上述 JSON 约 120 字节安全。若需发多属性确保总长 ≤ 1024。ATQMTPUB返回QMTPUB: 0,0表示发布成功QMTPUB: 0,1表示 topic 无效QMTPUB: 0,2表示 payload 长度超限。5. 实时验证与故障定位用 ONENET 数据流监控、EC20 日志抓取与 STM32 串口状态机调试发布成功不等于数据入库ONENET 控制台的「数据流」页面可能延迟 5~10 秒刷新而 EC20 的 AT 指令返回OK仅代表 MQTT 报文发出不代表服务器接收。必须建立三层验证闭环平台侧看数据、模组侧看连接状态、MCU 侧看指令时序。5.1 ONENET 平台侧实时监控技巧进入设备详情页 → 「数据流」→ 选择temp或humi→ 点击「实时数据」开启自动刷新若数据不出现点击右上角「查看原始数据」确认是否收到报文即使解析失败也会记录 raw data检查「设备日志」筛选MQTT类型查看CONNACK和PUBACK状态码关键指标PUBACK返回0x00表示服务器已确认接收0x80表示 topic 未授权。5.2 EC20 模组 AT 指令级调试当平台无数据时在 STM32 串口调试助手中输入ATQMTPSTAT? # 查询 MQTT 状态返回 QMTPSTAT: 0,1 表示已连接0client id, 1connected ATQMTPSUB? # 查询已订阅 topicONENET 不需订阅此项应为空 ATQMTRECV? # 查询待接收消息数通常为 0若ATQMTPSTAT?返回QMTPSTAT: 0,0说明连接已断开需检查ATCGATT?和ATCGPADDR?是否仍有效。5.3 STM32 固件状态机关键点检查表检查项正常值异常表现排查方法UART 发送缓冲区每次HAL_UART_Transmit()后huart-gState HAL_UART_STATE_READY卡在HAL_UART_STATE_BUSY_TX检查huart-hdmatx-State是否为HAL_DMA_STATE_READYDMA 未正确初始化会导致发送阻塞AT 指令响应超时HAL_UART_Receive()在 200ms 内收到\r\nOK\r\n返回HAL_TIMEOUT增加超时至 500msEC20 在 PDP 激活后首次 AT 响应可能达 300msDHT22 CRC 校验DHT22_ReadData()返回SUCCESS返回ERROR或TIMEOUT用示波器抓取 DHT22 DATA 线确认电平宽度符合协议80μs 低 80μs 高为 080μs 低 160μs 高为 1MQTT payload 长度strlen(json_payload)≤ 1024EC20 返回ERROR在ATQMTPUB前printf(len%d\n, strlen(json_payload))提示在ATQMTPUB指令后务必等待 EC20 返回提示符再发送 payload否则数据会被丢弃。可在 STM32 代码中加入while(!ec20_ready_flag);等待标志位。6. 进阶技巧降低功耗的 AT 指令休眠控制、批量属性更新与 ONENET 折线图快速配置量产设备需考虑续航与运维效率单纯“发一次数据”不够。本节提供三个经项目验证的实用技巧用 AT 指令让 EC20 进入深度休眠、一次发布多个传感器数据、以及在 ONENET 控制台 30 秒内配置折线图可视化。6.1 EC20 深度休眠指令降低整机功耗EC20 待机电流约 15mA通过ATQSCLK1可关闭射频时钟电流降至 1.2mAATQSCLK1 # 开启睡眠时钟模组保持 TCP 连接但暂停 RF ATQSCLK0 # 唤醒需重新发 AT 指令注意ATQSCLK1后所有 AT 指令仍有效但ATCSQ等射频相关指令返回CME ERROR: 4operation not supported。唤醒后需重新检查ATCGATT?状态。6.2 批量属性更新 JSON 构造模板若设备还接入光照、气压传感器可合并发布{ data: [ {id:temp,value:25.3,time:1717023456}, {id:humi,value:60.5,time:1717023456}, {id:lux,value:320,time:1717023456}, {id:press,value:1013.2,time:1717023456} ] }ONENET 支持单次最多 10 个属性JSON 总长仍需 ≤ 1024 字节。建议用 C 语言snprintf()动态拼接避免静态数组溢出。6.3 ONENET 折线图 30 秒配置法登录 ONENET 控制台 → 设备详情 → 「数据流」→ 点击temp→ 「图表配置」图表类型选「折线图」时间范围默认「最近 1 小时」Y 轴勾选「自动缩放」图例修改为「温度(℃)」保存后回到设备首页即可看到实时曲线。关键确保temp数据流的「数据类型」为「数值型」否则图表无法渲染。若显示空白检查数据流列表中该属性的「最新值」是否非空。在 ONENET 设备详情页右上角「更多」→ 「API 文档」→ 「MQTT 接入」可下载官方 JSON Schema 文件用jsonlint.com验证 payload 格式合法性——这是上线前必做的最后一步。本文还有配套的精品资源点击获取

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价