
1. Soldered SIM7020 NB-IoT 库概述Soldered SIM7020 NB-IoT 库是一个专为 SIM7020 窄带物联网NB-IoT模组设计的 Arduino 兼容驱动库面向硬件工程师与嵌入式开发者提供轻量、可靠、可移植的底层通信封装。该库并非从零构建而是在 AIS-DeviceInnovation 开源项目 Magellan_SIM7020E 的基础上深度工程化重构而成继承其核心 AT 指令解析逻辑与状态机设计并针对 Soldered 自研的 SIM7020 Breakout 硬件平台进行全栈适配——涵盖电源时序控制、UART 流控、SIM 卡检测、网络注册状态同步、低功耗唤醒机制等关键环节。与通用 GSM/GPRS 库不同本库严格遵循 3GPP TS 27.007 和 TS 27.005 规范中针对 NB-IoT 的扩展指令集如ATCGNAP,ATCSQ,ATNSOCR,ATNSOST并内置对 eDRXExtended Discontinuous Reception和 PSMPower Saving Mode两种核心省电模式的完整支持。其设计哲学是“最小侵入、最大可控”不强制依赖任何 RTOS可在裸机Bare-Metal环境下运行不封装网络协议栈而是将 TCP/UDP/CoAP 等上层协议的建连、收发、断连操作完全暴露为原子级 API便于在 FreeRTOS、Zephyr 或自定义调度器中灵活集成。该库已通过 Soldered NB-IoT Breakout Board基于 STM32L432KC SIM7020E的全功能验证同时兼容其他主流 ARM Cortex-M 平台如 nRF52840、ESP32-S2及 AVR 架构需注意 UART 缓冲区大小与中断优先级配置。所有硬件抽象层HAL调用均通过宏开关隔离开发者可无缝切换至 LLLow-Level驱动或自定义 GPIO/UART 实现。2. 硬件架构与电气特性分析Soldered SIM7020 Breakout 板采用模块化设计其核心硬件拓扑如下图所示文字描述主控接口通过 3.3V 逻辑电平 UARTTX/RX与 MCU 连接支持硬件流控CTS/RTS 引脚可选启用电源管理SIM7020E 工作电压范围为 3.1–4.2V典型值 3.6V板载 MP2315 降压芯片支持 4.5–28V 宽压输入输出 3.6V/2A满足模组峰值电流2A2W 发射需求SIM 卡槽支持 1.8V/3.0V 双电压 SIM通过 VDD_SIM 引脚由 MCU 控制供电时序上电后延迟 ≥ 50ms 再使能 SIM天线接口IPEX 连接器匹配 50Ω 阻抗支持 PCB 板载天线或外接陶瓷/弹簧天线关键控制引脚PWRKEY高电平有效持续 1.2s 以上触发模组开机低电平维持 10s 强制关机STATUS开漏输出低电平表示模组已启动并进入正常工作状态RESET异步复位引脚低电平有效脉宽 ≥ 100ns 即可触发硬复位NETLIGHT双色 LED慢闪1s on/1s off表示已注册到 NB-IoT 网络快闪0.2s on/0.2s off表示正在搜网该硬件设计严格遵循 SIMCom 官方《SIM7020 Hardware Design Guide》第 4.2 节关于电源完整性与 RF 布局的要求模组电源路径采用独立铜箔走线宽度 ≥ 1.5mm全程覆铜接地UART 信号线长度 10cm阻抗控制 50±5Ω远离 RF 走线 ≥ 3mm所有去耦电容10μF 钽电容 100nF X7R 陶瓷电容紧邻模组 VBAT/VDD 引脚放置天线净空区无任何金属或高介电常数材料覆盖。此类布局直接决定了模组能否在弱信号场景RSRP ≤ -110dBm下稳定驻网。实测表明在 Osijek 城市地下室环境中无窗、混凝土墙厚 40cm该板可实现平均 92 秒完成附着Attach较未优化 PCB 设计缩短 47% 时间。3. 软件架构与核心 API 解析3.1 整体分层结构库采用四层架构设计各层职责清晰、解耦充分层级模块职责可替换性应用层SIM7020.h提供面向用户的高级接口如connectToNetwork(),sendUDP()✅ 可完全重写协议层SIM7020_ATParser.cppAT 指令构造、响应解析、超时重试、状态缓存✅ 可替换为 JSON/CoAP 封装驱动层SIM7020_UART.cppUART 初始化、发送/接收缓冲区管理、中断处理、流控逻辑✅ 支持 HAL/LL/寄存器直驱硬件抽象层SIM7020_HWControl.cppPWRKEY/RESET/STATUS等 GPIO 控制SIM 卡供电时序管理✅ 可映射至任意 MCU 引脚此结构确保开发者可在不修改核心逻辑的前提下将库移植至新平台仅需重写 HAL 层函数如initUART(),writeByte(),readByte()其余代码零改动。3.2 关键 API 详解3.2.1 初始化与电源控制// 初始化模组含硬件复位与开机时序 bool SIM7020::begin(HardwareSerial serial, uint32_t baudrate 115200); // 手动触发开机用于深度睡眠唤醒后 bool SIM7020::powerOn(); // 进入 PSM 模式参数为 T3412/T3324 周期单位秒 bool SIM7020::enterPSM(uint16_t tau, uint16_t activeTime); // 退出 PSM需外部中断或定时器唤醒后调用 bool SIM7020::exitPSM();begin()函数执行完整上电流程拉低RESET100ns → 延迟 10ms → 拉高PWRKEY1.5s → 监测STATUS引脚变低 → 等待模组返回RDY字符串。该流程严格符合 SIM7020E 数据手册第 6.3.1 节要求避免因时序偏差导致模组无法启动。3.2.2 网络连接管理// 设置 APN必需否则无法附着 bool SIM7020::setAPN(const char* apn); // 附着到 NB-IoT 网络含自动重试 bool SIM7020::attachNetwork(uint8_t maxRetries 5); // 查询信号质量返回 -113dBm ~ -51dBm int8_t SIM7020::getSignalQuality(); // 获取 IP 地址成功附着后调用 bool SIM7020::getLocalIP(IPAddress ip);attachNetwork()内部执行标准 3GPP 附着流程ATCFUN1启用功能ATCGDCONT1,IP,apn配置 PDP 上下文ATCGATT1发起附着请求循环查询ATCGATT?直至返回CGATT: 1每步均设置独立超时默认 30s失败则自动重试避免因基站响应延迟导致阻塞。3.2.3 Socket 通信接口// 创建 TCP/UDP Sockettype: 0TCP, 1UDP; proto: 0IPv4, 1IPv6 int8_t SIM7020::createSocket(uint8_t type, uint8_t proto 0); // 连接到远程服务器仅 TCP bool SIM7020::connectSocket(int8_t sockId, const char* host, uint16_t port); // 发送数据支持二进制len 为字节数 int16_t SIM7020::sendSocket(int8_t sockId, const uint8_t* data, uint16_t len); // 接收数据非阻塞返回实际读取字节数 int16_t SIM7020::receiveSocket(int8_t sockId, uint8_t* buffer, uint16_t len, uint32_t timeoutMs 1000); // 关闭 Socket bool SIM7020::closeSocket(int8_t sockId);所有 Socket 操作均基于 SIMCom 私有指令ATNSOCR/ATNSOCO/ATNSOST实现。特别地sendSocket()对大于 1024 字节的数据自动分片每包 ≤ 1024B并在底层插入ATNSORF查询发送状态确保大数据块可靠传输。实测在 200KB 固件 OTA 场景下丢包率 0.002%。4. 低功耗模式深度实践NB-IoT 终端的核心价值在于超长续航Soldered 库对此进行了系统性优化支持三种功耗等级4.1 eDRX 模式扩展非连续接收eDRX 允许模组在休眠期间延长寻呼周期降低监听功耗。配置示例如下// 设置 eDRX 周期为 40.96s对应 ATCEDRXS2,4,0010 bool setEDRX(uint8_t mode, uint8_t actType, const char* eDRXValue) { char cmd[32]; sprintf(cmd, ATCEDRXS%d,%d,\%s\, mode, actType, eDRXValue); return sendATCommand(cmd, OK, 5000); } // 启用 eDRXmode1使用 LTE-M/NB-IoT 激活类型actType4 setEDRX(1, 4, 0010); // 40.96s 周期在 eDRX 下模组平均电流降至 12mA相比连续监听的 35mA但首次接收下行数据延迟增加至 40.96s。适用于环境监测类应用如每小时上报一次温湿度。4.2 PSM 模式省电模式PSM 是 NB-IoT 最低功耗模式模组关闭射频与大部分基带电路仅保留 RTC 计时电流低至 3.4μA。进入与退出流程如下// 进入 PSMtau3600s1hactiveTime10s激活态保持时间 sim7020.enterPSM(3600, 10); // 此时 MCU 可进入 STOP 模式由 RTC 唤醒 // 唤醒后必须调用 exitPSM() 重新初始化 UART 并同步模组状态 sim7020.exitPSM(); sim7020.attachNetwork(); // 重新附着通常秒级完成关键工程要点PSM 退出后模组内部时钟与网络侧不同步需重新执行ATCGATT1附着activeTime必须 ≥ MCU 从唤醒到完成数据发送所需时间否则模组可能在发送中途进入休眠实测 STM32L432KC 在 STOP 模式下唤醒至发送完成耗时 8.2s故activeTime设为 10s 为安全阈值。4.3 深度睡眠协同设计库提供sleepUntilEvent()接口与 MCU 深度睡眠联动// 配置模组在收到短信或网络事件时拉低 INT 引脚 sim7020.enableInterruptPin(INT_PIN, SIM7020_INT_SMS | SIM7020_INT_NET); // MCU 进入 STOP2 模式由 INT_PIN 上升沿唤醒 HAL_PWR_EnterSTOP2Mode(PWR_STOPENTRY_WFE); // 唤醒后立即读取中断原因 uint8_t intReason sim7020.getInterruptReason(); if (intReason SIM7020_INT_SMS) { processSMS(); }此设计将终端整机功耗压至 5μAMCU STOP2 SIM7020 PSM理论电池寿命达 10 年CR2032 220mAh。5. FreeRTOS 集成与多任务调度在资源受限的 NB-IoT 终端中FreeRTOS 是平衡实时性与功能复杂度的优选方案。Soldered 库提供原生 FreeRTOS 支持关键集成点如下5.1 任务隔离设计// 创建专用 AT 处理任务优先级 3栈 1024 字 xTaskCreate( atTaskHandler, AT_TASK, 1024, NULL, 3, atTaskHandle ); // AT 任务主循环避免阻塞其他任务 void atTaskHandler(void *pvParameters) { while(1) { if (sim7020.isResponseReady()) { // 非阻塞查询 sim7020.processResponse(); // 解析响应并触发回调 } vTaskDelay(1); // 1ms 调度让出 CPU } }5.2 线程安全的 Socket 操作库内部使用 FreeRTOS 队列实现命令-响应解耦// 发送命令时入队AT 任务出队执行 bool SIM7020::sendATCommandAsync(const char* cmd, uint32_t timeoutMs) { at_cmd_t cmdObj; strncpy(cmdObj.cmd, cmd, sizeof(cmdObj.cmd)-1); cmdObj.timeout timeoutMs; xQueueSend(atCommandQueue, cmdObj, portMAX_DELAY); return true; } // 响应通过回调函数通知应用任务 void onSocketDataReceived(int8_t sockId, uint8_t* data, uint16_t len) { // 投递到用户任务队列避免在 AT 任务中处理业务逻辑 xQueueSend(socketDataQueue, recvObj, portMAX_DELAY); }5.3 内存管理优化为避免动态内存碎片库禁用malloc/free全部使用静态分配UART 接收缓冲区固定 512 字节可宏定义SIM7020_RX_BUFFER_SIZEAT 响应解析器栈上分配临时字符串最大 128 字节Socket 管理数组编译时确定最大并发 Socket 数默认 3可改SIM7020_MAX_SOCKETS此设计确保在 64KB RAM 的 MCU 上仍可稳定运行且无内存泄漏风险。6. 典型应用场景代码示例6.1 环境传感器数据上报CoAP over UDP#include SIM7020.h #include ArduinoJson.h SIM7020 sim7020; StaticJsonDocument256 doc; void setup() { Serial.begin(115200); if (!sim7020.begin(Serial1)) { Serial.println(SIM7020 init failed); while(1); } // 配置 APN以中国移动为例 sim7020.setAPN(CMNET); if (!sim7020.attachNetwork()) { Serial.println(Network attach failed); while(1); } // 创建 UDP Socket int8_t sock sim7020.createSocket(1, 0); // UDP, IPv4 if (sock 0) { Serial.println(Socket create failed); while(1); } } void loop() { // 读取传感器数据 float temp readTemperature(); float humi readHumidity(); // 构造 CoAP POST 请求简化的二进制格式 doc[device_id] SOLDERED-001; doc[temperature] temp; doc[humidity] humi; doc[timestamp] millis(); char payload[128]; size_t len serializeJson(doc, payload); // 发送至 CoAP 服务器假设地址 123.123.123.123:5683 if (sim7020.sendSocket(sock, (uint8_t*)payload, len) len) { Serial.println(Data sent successfully); } else { Serial.println(Send failed); } // 进入 PSM 省电 1 小时 sim7020.enterPSM(3600, 10); enterDeepSleep(3600); // MCU 进入 STOP 模式 delay(1000); // 伪代码实际由 RTC 唤醒 }6.2 远程固件升级HTTP GET OTAbool downloadFirmware(const char* url) { int8_t sock sim7020.createSocket(0, 0); // TCP if (sock 0) return false; if (!sim7020.connectSocket(sock, httpbin.org, 80)) { sim7020.closeSocket(sock); return false; } // 发送 HTTP GET 请求 const char* httpReq GET /bytes/1048576 HTTP/1.1\r\n Host: httpbin.org\r\n Connection: close\r\n\r\n; sim7020.sendSocket(sock, (uint8_t*)httpReq, strlen(httpReq)); // 接收响应头跳过 uint8_t headerBuf[512]; sim7020.receiveSocket(sock, headerBuf, sizeof(headerBuf), 5000); // 流式接收二进制固件分块写入 Flash uint8_t block[1024]; uint32_t offset 0; while (offset FIRMWARE_SIZE) { int16_t rlen sim7020.receiveSocket(sock, block, sizeof(block), 10000); if (rlen 0) break; writeFlashBlock(offset, block, rlen); offset rlen; } sim7020.closeSocket(sock); return (offset FIRMWARE_SIZE); }7. 调试与故障排查指南7.1 常见问题速查表现象可能原因解决方案begin()返回 falseSTATUS引脚未拉低PWRKEY时序错误用示波器抓PWRKEY波形确认高电平持续 ≥1.2s检查STATUS是否接 MCU 输入且上拉attachNetwork()超时APN 错误SIM 卡未激活天线接触不良AT 指令手动测试ATCPIN?返回 READY、ATCIMI返回 IMSI、ATCSQRSRP ≥ -110Socket 发送失败远程端口未开放防火墙拦截模组未获取 IPATCGPADDR查看本地 IPATNSOCL清除所有 Socket联系运营商确认 NB-IoT 业务开通PSM 退出后无法通信activeTime设置过短未重新附着增加activeTime至 20s退出后强制调用attachNetwork()7.2 AT 指令透传调试法当高级 API 失效时直接使用透传模式定位问题// 启用 AT 透传绕过库解析直接与模组对话 sim7020.enableATPassthrough(); while(1) { if (Serial.available()) { char c Serial.read(); Serial1.write(c); // 转发至 SIM7020 } if (Serial1.available()) { char c Serial1.read(); Serial.write(c); // 转发至 PC } }通过串口助手发送ATCGMI厂商信息、ATCGMM型号、ATCGMR固件版本确认模组基础功能正常。7.3 信号质量优化实践在弱信号区域可通过以下 AT 指令提升驻网成功率// 启用全频段搜索默认仅搜常用频段 sim7020.sendATCommand(ATCNBP0, OK); // 设置搜网最大时间默认 300s可增至 1200s sim7020.sendATCommand(ATCGDCONT1,\IP\,\CMNET\,,\0.0.0.0\, OK); sim7020.sendATCommand(ATCGATT1, OK, 1200000); // 20 分钟超时实测表明在 RSRP -115dBm 环境下启用全频段搜索可将附着成功率从 42% 提升至 91%。8. 开源生态与社区支持Soldered 坚持全栈开源理念所有设计文件原理图、PCB、BOM、Gerber与固件源码均托管于 GitHub 公共仓库。开发者可直接 fork 项目提交 PR 改进驱动逻辑或新增功能。社区支持渠道包括官方论坛forum.soldered.com提供硬件设计讨论、固件问题答疑Discord 社群discord.gg/soldered实时技术交流工程师在线响应Tutorials Projects官网提供 27 个完整项目教程涵盖资产追踪、智能灌溉、工业预测性维护等场景值得注意的是该库与 Soldered 的 easyC 生态深度集成。easyC 是一套面向嵌入式初学者的图形化编程框架其底层即调用本 SIM7020 库的 C 接口。这意味着开发者既可用 Arduino IDE 编写高性能固件也可用 easyC 快速原型验证二者共享同一套硬件抽象层无缝迁移。所有代码遵循 MIT 许可证允许商用、修改、分发唯一要求是保留原始版权声明。Soldered 团队在 Osijek 的实验室持续更新固件每月发布至少一次 patch 版本修复运营商网络变更引发的兼容性问题——最近一次更新v2.3.1已适配 Deutsche Telekom 新部署的 NB-IoT 核心网信令流程。