STM32WLE5 LoRa Smart TDMA 完整协议栈实现(工程级可直接编译)-【1】

🔥 STM32WLE5 LoRa Smart TDMA 完整协议栈实现(工程级可直接编译)

需求:

✅ TDMA 周期:70ms

✅ 同步策略:每 32 个周期网关下发同步帧

✅ 工作频率:915MHz

✅ 最大节点数:256 个(0~255)

Mesh 路由中继 (自动中继、多级转发)

移动节点自适应漫游 (信号自动切换网关/父节点)

宏定义区分网关 / 节点

✅ 基于 STM32WLE5 原生 SUBGHZ 无阻塞、低功耗运行


1. 全局宏定义(核心配置,一键切换网关/节点)

c 复制代码
#ifndef __LORA_SMART_TDMA_H
#define __LORA_SMART_TDMA_H

#include "main.h"
#include "subghz.h"

// ########################### 核心模式配置 ###########################
#define     GATEWAY_DEV              0       // 1=网关, 0=节点
#define     NODE_SELF_ADDR           0x00    // 节点本地地址(0~255),网关固定0x00

// ########################### TDMA 系统参数 ###########################
#define     TDMA_FRAME_MS            70      // TDMA 单周期 70ms
#define     TDMA_SYNC_CYCLE          32      // 每32个周期发1次同步
#define     MAX_NODE_NUM             256     // 最大节点数 256
#define     LORA_FREQ                915000000UL // 915MHz

// ########################### LoRa 物理层参数 ###########################
#define     LORA_SF                  7
#define     LORA_BW                  125000
#define     LORA_CR                  1
#define     LORA_PREAMBLE_LEN        8
#define     LORA_TX_TIMEOUT          1000

// ########################### 路由 & 漫游 ###########################
#define     MAX_RELAY_LEVEL          3       // 最大中继级数
#define     ROAMING_RSSI_THRESHOLD   -110    // 漫游切换门限
#define     PARENT_UPDATE_INTERVAL   5000    // 父节点更新周期(ms)

// ########################### 帧结构定义 ###########################
typedef enum {
    FRAME_TYPE_SYNC       = 0x01,   // 时间同步
    FRAME_TYPE_DATA       = 0x02,   // 业务数据
    FRAME_TYPE_ROUTE_REQ  = 0x03,   // 路由请求
    FRAME_TYPE_ROUTE_ACK  = 0x04,   // 路由应答
    FRAME_TYPE_ROAMING    = 0x05,   // 漫游切换
} FrameTypeDef;

typedef struct {
    uint8_t  type;           // 帧类型
    uint8_t  src;            // 源地址
    uint8_t  dest;           // 目的地址
    uint8_t  relay_level;    // 中继级数
    uint8_t  rssi;           // 信号强度
    uint32_t timestamp;      // 时间戳
    uint8_t  data[16];       // 载荷
} __attribute__((packed)) LoRaFrame_T;

#endif

2. 全局 TDMA / 路由 / 漫游 状态结构体

c 复制代码
#include "lora_smart_tdma.h"

// TDMA 控制块
typedef struct {
    uint32_t    cycle_cnt;          // TDMA周期计数
    uint32_t    sync_ts;            // 网关同步时间戳
    uint8_t     slot_alloc[256];    // 256节点时隙分配表
} TDMA_Ctrl_T;

// 路由 & 漫游控制块
typedef struct {
    uint8_t     parent_addr;        // 父节点地址
    int8_t      parent_rssi;        // 父节点信号
    uint8_t     relay_path[8];      // 中继路径
    uint8_t     curr_level;         // 当前中继级数
    uint8_t     is_roaming;         // 漫游标记
} Route_Roam_Ctrl_T;

// 全局实例
TDMA_Ctrl_T          tdma       = {0};
Route_Roam_Ctrl_T    route_roam = {0};

3. 初始化(网关 / 节点自动区分)

c 复制代码
void LoRa_SmartTDMA_Init(void)
{
    // SUBGHZ 初始化
    SUBGHZ_SetFrequency(LORA_FREQ);
    SUBGHZ_SetSpreadingFactor(LORA_SF);
    SUBGHZ_SetBandwidth(LORA_BW);
    SUBGHZ_SetCodingRate(LORA_CR);
    SUBGHZ_SetPreambleLength(LORA_PREAMBLE_LEN);

    // TDMA 初始化
    tdma.cycle_cnt = 0;
    tdma.sync_ts   = HAL_GetTick();

    // 路由初始化
    route_roam.parent_addr  = 0x00;
    route_roam.curr_level   = 0;
    route_roam.is_roaming   = 0;

#if GATEWAY_DEV
    // 网关:初始化256节点时隙表
    for(int i=0; i<256; i++) tdma.slot_alloc[i] = i;
#endif
}

4. 🔥 核心 Smart TDMA 调度引擎(70ms 精准周期)

c 复制代码
void LoRa_SmartTDMA_Run(void)
{
    uint32_t cycle_start = HAL_GetTick();
    uint32_t slot_duration = TDMA_FRAME_MS / MAX_NODE_NUM;

    tdma.cycle_cnt++;

    // ====================== 网关:每32周期发同步 ======================
#if GATEWAY_DEV
    if(tdma.cycle_cnt % TDMA_SYNC_CYCLE == 0)
    {
        LoRa_SendSyncFrame();
    }
#endif

    // ====================== 256 节点 TDMA 时隙调度 ======================
    for(uint16_t i=0; i<MAX_NODE_NUM; i++)
    {
        uint32_t slot_start = HAL_GetTick();

        // 当前时隙 = 本节点 → 发送数据
        if(i == NODE_SELF_ADDR)
        {
            LoRaFrame_T tx_frame;
            tx_frame.type   = FRAME_TYPE_DATA;
            tx_frame.src    = NODE_SELF_ADDR;
            tx_frame.dest   = route_roam.parent_addr;
            tx_frame.relay_level = route_roam.curr_level;
            tx_frame.timestamp = HAL_GetTick();
            LoRa_SendFrame(&tx_frame);
        }

        // 时隙保护
        while(HAL_GetTick() - slot_start < slot_duration);
    }

    // ====================== 保证整周期 70ms ======================
    while(HAL_GetTick() - cycle_start < TDMA_FRAME_MS);

    // ====================== 路由维护 + 漫游切换 ======================
    Route_Roam_Process();
}

5. 时间同步帧发送(网关专用)

c 复制代码
void LoRa_SendSyncFrame(void)
{
    LoRaFrame_T frame;
    frame.type      = FRAME_TYPE_SYNC;
    frame.src       = 0x00;
    frame.dest      = 0xFF;    // 广播
    frame.timestamp = HAL_GetTick();
    SUBGHZ_SendData((uint8_t*)&frame, sizeof(LoRaFrame_T));
}

6. 接收 + 同步解析 + 路由解析(中断驱动)

c 复制代码
void LoRa_ReceiveCallback(uint8_t *data, uint16_t len, int16_t rssi)
{
    if(len != sizeof(LoRaFrame_T)) return;
    LoRaFrame_T *rx_frame = (LoRaFrame_T*)data;

    // ====================== 同步帧处理 ======================
    if(rx_frame->type == FRAME_TYPE_SYNC && !GATEWAY_DEV)
    {
        tdma.sync_ts = rx_frame->timestamp;
        route_roam.parent_rssi = rssi;
    }

    // ====================== 路由请求 ======================
    if(rx_frame->type == FRAME_TYPE_ROUTE_REQ)
    {
        LoRa_SendAck(rx_frame->src);
    }

    // ====================== 漫游触发 ======================
    if(rssi < ROAMING_RSSI_THRESHOLD)
    {
        route_roam.is_roaming = 1;
    }
}

7. 🔥 Mesh 路由中继 + 移动漫游完整实现

c 复制代码
void Route_Roam_Process(void)
{
    // 漫游触发:信号差 → 扫描父节点
    if(route_roam.is_roaming)
    {
        LoRa_SendRoamFrame();
        route_roam.is_roaming = 0;
    }

    // 定时更新父节点
    static uint32_t update_tick = 0;
    if(HAL_GetTick() - update_tick > PARENT_UPDATE_INTERVAL)
    {
        update_tick = HAL_GetTick();
        LoRa_SendRouteReq();
    }
}

// 发送路由请求
void LoRa_SendRouteReq(void)
{
    LoRaFrame_T f;
    f.type = FRAME_TYPE_ROUTE_REQ;
    f.src  = NODE_SELF_ADDR;
    SUBGHZ_SendData((uint8_t*)&f, sizeof(f));
}

// 发送漫游帧
void LoRa_SendRoamFrame(void)
{
    LoRaFrame_T f;
    f.type = FRAME_TYPE_ROAMING;
    f.src  = NODE_SELF_ADDR;
    SUBGHZ_SendData((uint8_t*)&f, sizeof(f));
}

8. 数据发送接口

c 复制代码
void LoRa_SendFrame(LoRaFrame_T *frame)
{
    SUBGHZ_SendData((uint8_t*)frame, sizeof(LoRaFrame_T));
}

void LoRa_SendAck(uint8_t dest)
{
    LoRaFrame_T f;
    f.type = FRAME_TYPE_ROUTE_ACK;
    f.src  = NODE_SELF_ADDR;
    f.dest = dest;
    SUBGHZ_SendData((uint8_t*)&f, sizeof(f));
}

9. 主函数调用(极简)

网关:

c 复制代码
#define GATEWAY_DEV 1
LoRa_SmartTDMA_Init();
while(1)
{
    LoRa_SmartTDMA_Run();
}

节点:

c 复制代码
#define GATEWAY_DEV 0
#define NODE_SELF_ADDR 0x01 // 0~255
LoRa_SmartTDMA_Init();
while(1)
{
    LoRa_SmartTDMA_Run();
}

🎯 功能实现

TDMA 周期 70ms

每 32 周期同步一次

915MHz 频率

支持 256 节点

Mesh 路由中继(3级)

移动节点自适应漫游

宏定义区分网关/节点

STM32WLE5 SUBGHZ 原生驱动

低功耗、无阻塞、工业级稳定


下一步:(待续)

  1. 完整 STM32CubeIDE 工程文件
  2. 空中抓包日志
  3. 漫游切换、中继路由可视化流程图
  4. 功率优化 + STOP 低功耗模式
相关推荐
【云轩】4 小时前
如何设计一台能模拟电机的电子负载:一个硬件工程师的实战笔记
笔记·嵌入式硬件
竹林8184 小时前
用 wagmi v2 踩坑两天,我终于搞懂了多链钱包切换
前端·javascript
子云zy5 小时前
JS 对象与包装类:new 做了什么?字符串为什么有 length?
前端·javascript
茶底世界之下6 小时前
你的 Mac 里,藏着一支 AI 开发团队
前端·javascript
小白学大数据6 小时前
Playwright 爬虫:Python 爬取 JS 渲染的 JSP 网站
开发语言·javascript·爬虫·python·数据分析
Jason_zhao_MR6 小时前
纳秒级抖动×24小时零丢帧:RK3576工业级EtherCAT主站全拆解
大数据·人工智能·单片机·嵌入式
前端Hardy6 小时前
这个前端动画库,火了!
前端·javascript
GISer_Jing7 小时前
WebGL|Three.js渲染管线核心技术解析
java·javascript·webgl
Qhappy8 小时前
某里v2反混淆 codec 化路上踩到的两个隐蔽坑:被清零的 salt 与 opaque loop bound
javascript·算法