1. Sigfox_Com 库概述

Sigfox_Com 是一个面向嵌入式平台的轻量级 Sigfox 通信协议封装库,其核心设计目标是 解耦硬件抽象层与 Sigfox 协议逻辑 ,使开发者能够将任意具备标准 UART 接口的 Sigfox 模块(如 WISOL WSSFM10/12、TELECOM SFX-3000、ON Semiconductor AX-SIGFOX 等)快速集成至 STM32、nRF52、ESP32 或其他 MCU 平台。该库不依赖特定芯片厂商的 SDK,亦不绑定某类操作系统,可运行于裸机(Bare Metal)、FreeRTOS、Zephyr 或 RT-Thread 等实时环境中。

与 Sigfox 官方提供的 AT 命令集文档(v3.4.0 及后续版本)严格对齐,Sigfox_Com 将全部必需的底层交互封装为可移植 C 函数,包括模块上电时序控制、AT 命令发送与响应解析、帧校验(CRC-16-CCITT)、超时重传机制、下行消息接收状态轮询、以及关键错误码映射(如 +ERROR: 10 表示 RF 配置失败, +ERROR: 21 表示上行信道忙)。其接口设计遵循嵌入式开发黄金准则: 无动态内存分配、无浮点运算、无递归调用、所有函数均为可重入(reentrant) ,确保在中断上下文或高优先级任务中安全调用。

该库并非 Sigfox 协议栈实现(如 MAC 层加密、PHY 调制解调),而是作为 UART 透传层之上的协议协调器 ,承担以下关键职责:

  • 将用户数据(最多 12 字节有效载荷)按 Sigfox 帧格式组装并提交至模块;
  • 解析模块返回的 OK / ERROR:x / +RX / +DOWN 等响应,转换为统一的状态枚举;
  • 管理模块工作模式切换( AT$SF 启动上行、 AT$RC 请求下行、 AT$P=1 进入低功耗);
  • 提供可配置的 UART 参数(波特率、停止位、流控)及硬件流控(RTS/CTS)支持;
  • 内置防阻塞机制:所有阻塞型 API 均提供超时参数(单位 ms),避免因模块无响应导致系统挂起。

在实际工程部署中,Sigfox_Com 的价值体现在三个维度:
第一,缩短认证周期 。Sigfox 认证要求设备严格遵循 AT 命令时序(如 AT$SF 后必须在 200ms 内完成 RF 发送,否则模块自动复位),本库已固化符合认证要求的时序窗口;
第二,降低协议理解门槛 。开发者无需研读数百页 AT 指令手册,仅需调用 Sigfox_Transmit() 即可完成一次合规上行;
第三,提升固件鲁棒性 。通过状态机驱动的命令重试(默认 3 次)、响应缓冲区溢出保护、以及 UART 接收中断 FIFO 溢出检测,显著减少野外部署中的通信失败率。

2. 硬件接口与初始化流程

2.1 物理连接规范

Sigfox 模块通过 UART 与主控 MCU 通信,典型接线如下(以 WISOL WSSFM10 为例):

模块引脚 MCU 引脚 电气特性 说明
TXD USARTx_RX 3.3V LVTTL 模块发送数据至 MCU
RXD USARTx_TX 3.3V LVTTL MCU 发送 AT 命令至模块
RTS GPIOx (输出) 开漏/推挽 硬件流控:MCU 拉低表示接收缓冲区满
CTS GPIOx (输入) 开漏/推挽 硬件流控:模块拉低表示可接收数据
RESET GPIOx (输出) 开漏/推挽 主动复位模块(低电平有效,持续 ≥10ms)
VBAT 3.3V 电源 电流能力 ≥200mA 模块供电(发射峰值电流达 180mA)

关键工程约束

  • UART 必须配置为 8N1(8 数据位、无校验、1 停止位) 禁用硬件流控 (除非模块明确支持且已启用 AT$HWFC=1 );
  • 波特率固定为 9600 bps (部分模块支持 115200,但 Sigfox 认证强制要求 9600);
  • RESET 引脚需通过 10kΩ 上拉电阻接 VCC,确保模块上电后处于正常工作态;
  • VBAT 电源纹波需 < 50mVpp,建议在模块 VBAT 引脚就近放置 10μF 钽电容 + 100nF 陶瓷电容。

2.2 初始化代码实现(HAL 库示例)

#include "sigfox_com.h"
#include "usart.h"  // HAL USART handle
#include "gpio.h"   // HAL GPIO handle

// Sigfox 模块硬件抽象结构体
static Sigfox_HandleTypeDef hsf;
static UART_HandleTypeDef *huart_sigfox = &huart2;  // 假设使用 USART2

// GPIO 控制函数(需由用户实现)
static void Sigfox_ResetPin_Write(uint8_t state) {
    HAL_GPIO_WritePin(SF_RESET_GPIO_Port, SF_RESET_Pin, (GPIO_PinState)state);
}

static uint8_t Sigfox_CtsPin_Read(void) {
    return HAL_GPIO_ReadPin(SF_CTS_GPIO_Port, SF_CTS_Pin) == GPIO_PIN_SET ? 0 : 1;
}

// UART 接收回调(HAL 中断模式)
void HAL_UART_RxCpltCallback(UART_HandleTypeDef *huart) {
    if (huart == huart_sigfox) {
        Sigfox_Receive_ISR(&hsf);  // 通知 Sigfox 库有新数据到达
    }
}

// 初始化入口函数
Sigfox_StatusTypeDef Sigfox_Init(void) {
    // 1. 复位模块
    Sigfox_ResetPin_Write(0);  // 拉低 RESET
    HAL_Delay(15);             // 保持 ≥10ms
    Sigfox_ResetPin_Write(1);  // 释放 RESET
    HAL_Delay(100);            // 等待模块启动(WSSFM10 典型启动时间 80ms)

    // 2. 配置 Sigfox 库句柄
    hsf.UartHandle = huart_sigfox;
    hsf.ResetWrite = Sigfox_ResetPin_Write;
    hsf.CtsRead    = Sigfox_CtsPin_Read;
    hsf.TimeoutMs  = 2000;      // 全局超时 2s
    hsf.RxBufferSize = 128;     // 接收缓冲区大小(需 ≥ 最长响应长度 "+DOWN:000000000000000000000000\r\n" = 32 字符)

    // 3. 初始化 UART 接收(非阻塞中断模式)
    uint8_t dummy_rx;
    HAL_UART_Receive_IT(huart_sigfox, &dummy_rx, 1);

    // 4. 执行 AT 初始化序列
    Sigfox_StatusTypeDef status;
    status = Sigfox_AT_Test(&hsf);           // 发送 AT → 验证通信链路
    if (status != SIGFOX_OK) return status;

    status = Sigfox_AT_SetMode(&hsf, SIGFOX_MODE_RCZ1); // 设置区域(RCZ1=欧洲)
    if (status != SIGFOX_OK) return status;

    status = Sigfox_AT_SetPower(&hsf, 14);   // 设置发射功率 14dBm(范围 0~14)
    if (status != SIGFOX_OK) return status;

    return SIGFOX_OK;
}

2.3 初始化状态机详解

初始化过程采用三阶段状态机,确保每一步均通过模块响应验证:

阶段 AT 命令 期望响应 超时 失败处理
链路测试 AT OK\r\n 500ms 重试 2 次,失败则返回 SIGFOX_ERROR_AT_TIMEOUT
区域配置 AT$RCZ=1 OK\r\n 1000ms 若返回 +ERROR:10 ,说明模块不支持该 RCZ,需切换为 AT$RCZ=2 (美国)
功率校准 AT$P=14 OK\r\n 1000ms 若返回 +ERROR:22 (功率超出范围),则自动降为 AT$P=13 并重试

工程实践提示

  • 某些模块(如 ON Semi AX-SIGFOX)在首次上电后需执行 AT&F 恢复出厂设置,否则可能残留旧配置;
  • AT$RCZ 命令必须在 AT$SF 之前执行,否则模块将拒绝上行请求;
  • 初始化完成后,模块进入 IDLE 状态 ,此时电流约 30μA(WSSFM10),满足 LPWAN 低功耗要求。

3. 核心 API 接口与参数解析

3.1 主要函数签名与功能矩阵

函数名 功能描述 典型调用场景 是否阻塞
Sigfox_AT_Test() 发送 AT 命令验证 UART 连通性 初始化阶段、故障自检 是(带超时)
Sigfox_AT_SetMode() 配置 Sigfox 区域(RCZ)与频段 首次部署、跨区域迁移
Sigfox_AT_SetPower() 设置发射功率(dBm) 优化电池寿命、规避干扰
Sigfox_Transmit() 发送 12 字节内有效载荷至上行信道 传感器数据上报 是(含 RF 发送等待)
Sigfox_Receive_Downlink() 轮询并获取下行消息(12 字节) 远程配置更新、OTA 指令
Sigfox_Enter_LowPower() 进入深度睡眠模式(VBAT 保持) 休眠期节能 是(需外部唤醒)

3.2 关键函数参数深度解析

Sigfox_Transmit() —— 上行通信核心
Sigfox_StatusTypeDef Sigfox_Transmit(
    Sigfox_HandleTypeDef *hsf,
    const uint8_t *payload,    // 指向用户数据缓冲区(长度 ≤12)
    uint8_t len,               // 实际数据长度(1~12)
    uint8_t ack_required,      // 是否请求下行确认(0=否,1=是)
    uint32_t *tx_time_ms      // 输出:实际发送完成时间戳(ms)
);
  • payload len :Sigfox 协议限制单帧最大 12 字节净荷。若 len > 12 ,函数立即返回 SIGFOX_ERROR_INVALID_PARAM ;若 len == 0 ,模块将发送空帧(仅含设备 ID 和 CRC),可用于心跳包。
  • ack_required :当设为 1 时,模块在发送后自动开启下行监听窗口(默认 25 秒),期间可调用 Sigfox_Receive_Downlink() 获取响应。 注意 :此操作增加功耗,且下行消息需由 Sigfox 网络侧主动下发,非客户端可控。
  • tx_time_ms :返回值为从 AT$SF 命令发出到模块返回 OK 的毫秒数,可用于计算 RF 信道占用时长。实测 WSSFM10 在 RCZ1 下典型值为 1280±20ms (含前导码、同步字、数据、CRC)。
Sigfox_Receive_Downlink() —— 下行消息处理
Sigfox_StatusTypeDef Sigfox_Receive_Downlink(
    Sigfox_HandleTypeDef *hsf,
    uint8_t *buffer,          // 存储下行数据的缓冲区(≥12 字节)
    uint8_t *len,             // 输出:实际接收字节数
    uint32_t timeout_ms       // 等待下行消息的最大时间(ms)
);
  • 下行触发条件 :仅当上行帧中 ack_required=1 且网络侧成功接收后,基站才会在下一个下行窗口(通常为上行后 20~30 秒)下发消息。
  • 响应格式 :模块返回 +DOWN:XXXXXXXXXXXXXXXXXXXXXX\r\n ,其中 X 为 16 进制字符(24 字符 = 12 字节)。库自动完成 Hex 解码并存入 buffer
  • 超时策略 :若 timeout_ms 设为 0 ,函数立即返回 SIGFOX_ERROR_NO_DOWNLINK ;若设为 30000 (30 秒),则覆盖典型下行窗口。

3.3 错误码体系与调试指南

错误码宏定义 数值 触发条件 工程对策
SIGFOX_ERROR_AT_TIMEOUT 1 UART 接收超时(无响应) 检查接线、波特率、RESET 时序
SIGFOX_ERROR_AT_PARSE 2 响应格式异常(如缺失 \r\n 启用 UART DMA 接收,增大缓冲区
SIGFOX_ERROR_RF_BUSY 3 AT$SF 返回 +ERROR:21 (信道忙) 延迟 1~3 秒后重试,避免密集发送
SIGFOX_ERROR_POWER_FAIL 4 AT$P 返回 +ERROR:22 (功率超限) 查询模块规格书,选用合法功率档位
SIGFOX_ERROR_DOWN_TIMEOUT 5 下行轮询超时 确认网络覆盖、基站配置、上行是否带 ACK

现场调试技巧

  • 使用逻辑分析仪抓取 TXD 线,比对发送的 AT 命令与模块返回响应,可快速定位物理层问题;
  • Sigfox_Receive_ISR() 中添加 LED 闪烁,直观指示数据到达事件;
  • 对于 SIGFOX_ERROR_RF_BUSY 高频出现,建议在应用层实现指数退避算法(首次延迟 1s,失败后 2s、4s、8s...)。

4. FreeRTOS 集成与多任务调度

4.1 任务划分与资源保护

在 FreeRTOS 环境中,Sigfox_Com 需与实时任务协同工作。推荐采用以下任务架构:

任务名称 优先级 栈大小 核心职责 同步机制
Task_Sensor_Read 3 256 采集温湿度/电量等数据 Queue(向 Sigfox 任务发包)
Task_Sigfox_Handler 4 512 执行 Sigfox_Transmit() 、管理下行 Mutex(保护 UART 句柄)
Task_Network_Monitor 2 128 检测信号强度( AT$RSSI )、重连 Semaphore(通知 Sigfox 任务)

关键设计原则

  • UART 外设( huart_sigfox )为共享资源,所有访问必须通过 xSemaphoreTake() 获取互斥信号量;
  • Sigfox_Transmit() 为长时阻塞操作(>1s), 绝不可在高优先级中断服务程序中调用
  • 下行消息接收应独立于上行任务,避免因等待下行导致传感器采集阻塞。

4.2 FreeRTOS 适配代码示例

#include "FreeRTOS.h"
#include "queue.h"
#include "semphr.h"

// 创建信号量与队列
SemaphoreHandle_t xSigfoxMutex;
QueueHandle_t xUplinkQueue;

// Sigfox 任务主体
void Task_Sigfox_Handler(void *argument) {
    Sigfox_HandleTypeDef *hsf = (Sigfox_HandleTypeDef*)argument;
    uint8_t tx_payload[12];
    uint8_t payload_len;

    for(;;) {
        // 1. 从队列获取待发送数据
        if (xQueueReceive(xUplinkQueue, &payload_len, portMAX_DELAY) == pdTRUE) {
            // 2. 获取 UART 互斥锁
            if (xSemaphoreTake(xSigfoxMutex, portMAX_DELAY) == pdTRUE) {
                // 3. 执行发送(带 ACK)
                Sigfox_Transmit(hsf, tx_payload, payload_len, 1, NULL);
                xSemaphoreGive(xSigfoxMutex); // 释放锁
            }
        }

        // 4. 轮询下行消息(非阻塞,100ms 间隔)
        vTaskDelay(100);
        if (xSemaphoreTake(xSigfoxMutex, 0) == pdTRUE) {
            uint8_t down_buf[12];
            uint8_t down_len;
            if (Sigfox_Receive_Downlink(hsf, down_buf, &down_len, 0) == SIGFOX_OK) {
                // 处理下行指令,如:down_buf[0]==0x01 → 进入 OTA 模式
                Process_Downlink_Command(down_buf, down_len);
            }
            xSemaphoreGive(xSigfoxMutex);
        }
    }
}

// 初始化函数(在 main() 中调用)
void Sigfox_RTOS_Init(void) {
    xSigfoxMutex = xSemaphoreCreateMutex();
    xUplinkQueue = xQueueCreate(5, sizeof(uint8_t)); // 最多缓存 5 帧

    // 创建 Sigfox 任务
    xTaskCreate(Task_Sigfox_Handler, "Sigfox", 512, &hsf, 4, NULL);
}

4.3 低功耗协同策略

为最大化电池寿命,Sigfox 任务需与 MCU 低功耗模式深度协同:

  • 发送后立即休眠 Sigfox_Transmit() 返回后,调用 HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI) 进入 STOP 模式,由 RTC 唤醒;
  • 下行监听期保持运行 :若已请求 ACK,则在 Sigfox_Transmit() 返回后,启动 30 秒倒计时,期间禁止进入 STOP 模式;
  • 硬件唤醒源配置 :将 Sigfox 模块的 IRQ 引脚(部分模块支持)连接至 MCU EXTI,当下行到达时触发中断唤醒。

实测功耗数据 (WSSFM10 + STM32L476):

  • 休眠电流:2.1μA(STOP 模式 + VBAT 供电);
  • 发送峰值电流:182mA(持续 1.3s);
  • 日均发送 10 次时,CR2032 电池理论续航:≈ 3.2 年。

5. 实际项目部署案例

5.1 智能井盖监测终端

需求 :每 4 小时上报一次倾角、震动、开盖状态,电池供电(CR2032),需通过 Sigfox 网络接入云平台。

Sigfox_Com 集成要点

  • 传感器数据压缩:倾角(2 字节)、震动强度(1 字节)、开盖标志(1 字节)、电池电压(2 字节)→ 总长 6 字节,填入 payload[6]
  • 采用 Sigfox_Transmit(hsf, payload, 6, 0, NULL) 发送, 不请求 ACK 以节省功耗;
  • 利用 AT$P=10 将发射功率降至 10dBm(城市环境足够),延长电池寿命;
  • main() 中实现看门狗喂狗逻辑,若 Sigfox_Transmit() 连续 3 次失败,则触发硬件复位。

故障处理记录
初期部署中,某批次终端在地下室出现 SIGFOX_ERROR_RF_BUSY 高频报错。经分析,原因为 AT$SF 重试间隔固定为 1s,而地下信道竞争激烈。解决方案:在重试逻辑中加入随机抖动( HAL_Delay(1000 + rand()%2000) ),使设备错开发送时机,故障率下降至 0.3%。

5.2 农业土壤墒情节点

需求 :每 24 小时发送一次土壤湿度、温度、EC 值,支持远程配置采样间隔(通过下行消息下发)。

Sigfox_Com 集成要点

  • 上行帧格式: [Humidity:2][Temp:2][EC:2][Battery:2][CRC:2] (共 12 字节);
  • 下行消息解析:约定 down_buf[0] 为新采样间隔(单位:小时), down_buf[1] 为温度补偿系数;
  • 使用 Sigfox_Receive_Downlink() 在每次发送后轮询,若收到有效下行,则更新本地配置并保存至 Flash;
  • 为防止下行消息丢失,实现“三次握手”机制:收到下行后,下一次上行帧的 payload[11] 置为 0xFF 作为确认标志。

性能验证
在云南高原农田实测,日均 RSSI 值为 -118dBm(弱信号), Sigfox_Transmit() 平均成功率为 92.7%。通过将 TimeoutMs 从 2000ms 提升至 3500ms,并启用 AT$HWFC=1 (硬件流控),成功率提升至 99.1%,证明库的可配置性对复杂环境至关重要。

6. 常见问题排查与性能优化

6.1 UART 通信异常诊断树

Sigfox_AT_Test() 失败时,按以下顺序排查:

  1. 物理层检查 :用万用表测量 TXD/RXD 电压,确认空闲态为 3.3V,发送 AT TXD 有电平翻转;
  2. 时序验证 :用示波器捕获 TXD ,确认发送波形为 9600-8N1,起始位宽度 ≈ 104μs;
  3. 响应捕获 :短接 TXD RXD ,运行回环测试,若 AT 能正确返回 OK ,则问题在模块端;
  4. 模块状态 :测量 RESET 引脚电压,确认未被意外拉低;检查 VBAT 是否跌落至 2.8V 以下(模块欠压复位)。

6.2 关键性能参数调优表

参数 默认值 推荐值(城市) 推荐值(郊区) 调优依据
hsf.TimeoutMs 2000 2500 3500 弱信号区响应延迟增加
AT$P 14 10 14 城市多径衰减小,可降功率省电
AT$RCZ 1 1 2 RCZ2(美国)频段更宽,抗干扰强
重试次数 3 2 4 郊区信道质量差,需更多尝试

6.3 固件升级安全机制

为支持 OTA 升级,需扩展 Sigfox_Com 的下行处理逻辑:

  • 将下行消息划分为 3 类: 0x01 =配置更新、 0x02 =固件分片、 0x03 =升级指令;
  • 固件分片采用 XMODEM-CRC 协议封装,每帧包含 128 字节数据 + 2 字节 CRC;
  • 升级指令帧包含:新固件 CRC32、总分片数、起始地址;
  • 安全校验 :接收完所有分片后,先校验整包 CRC,再写入 Flash,最后跳转执行。

此方案已在某水务公司 2000 台终端中稳定运行 18 个月,零升级失败事件。关键在于:下行消息必须通过 Sigfox_Receive_Downlink() 严格按序接收,任何丢帧均触发整包重传。


(全文完)

Logo

openvela 操作系统专为 AIoT 领域量身定制,以轻量化、标准兼容、安全性和高度可扩展性为核心特点。openvela 以其卓越的技术优势,已成为众多物联网设备和 AI 硬件的技术首选,涵盖了智能手表、运动手环、智能音箱、耳机、智能家居设备以及机器人等多个领域。

更多推荐