STM32WLE5 LoRa Smart TDMA 完整协议栈工程实现 -【2】

STM32WLE5 LoRa Smart TDMA 完整协议栈工程实现 -2

(接续上版:工程可编译、低功耗、SUBGHZ 中断版、256 节点、TDMA 70ms、路由中继+漫游)


0. 工程文件说明(直接放入 STM32CubeIDE)

本版为可直接编译工程版,补齐:

  • SUBGHZ 底层收发封装
  • 中断接收回调
  • 低功耗无阻塞
  • 严格 70ms 周期调度
  • 256 节点时隙精确分配
  • 网关/节点宏开关
  • 路由中继 + 漫游切换完整逻辑

文件清单:

  1. lora_smart_tdma.h
  2. lora_smart_tdma.c
  3. subghz_driver.c/h (适配 STM32WLE5 标准库)

1. lora_smart_tdma.h(接续-2)

c 复制代码
#ifndef __LORA_SMART_TDMA_H
#define __LORA_SMART_TDMA_H

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

// ########################### 模式配置 ###########################
#define USE_GATEWAY            0       // 1=网关  0=节点
#define LOCAL_NODE_ADDR        0x01    // 本节点地址 0~255,网关=0x00

// ########################### TDMA 核心参数 ###########################
#define TDMA_FRAME_PERIOD_MS   70      // 70ms 周期
#define TDMA_SYNC_INTERVAL     32      // 每32周期发同步
#define MAX_NODES              256     // 最大256节点
#define LORA_FREQ_915M         915000000UL

// ########################### LoRa 物理层 ###########################
#define LORA_SF                7
#define LORA_BW                125000
#define LORA_CR                1
#define LORA_PREAMBLE          8
#define LORA_MAX_PAYLOAD       32

// ########################### 路由/漫游 ###########################
#define MAX_RELAY_LEVEL        3
#define ROAM_RSSI_THRESHOLD    -110
#define PARENT_CHECK_MS        5000
#define ROUTE_RETRY_COUNT      3

// ########################### 帧类型 ###########################
typedef enum {
    FRAME_SYNC                = 0x01,
    FRAME_DATA                = 0x02,
    FRAME_ROUTE_REQ           = 0x03,
    FRAME_ROUTE_ACK           = 0x04,
    FRAME_ROAMING_SCAN        = 0x05,
    FRAME_ROAMING_CONFIRM     = 0x06,
} FrameType;

// ########################### 无线帧结构 ###########################
typedef struct {
    uint8_t  type;
    uint8_t  src_addr;
    uint8_t  dst_addr;
    uint8_t  relay_level;
    uint8_t  from_parent;
    int8_t   rssi;
    uint32_t timestamp;
    uint8_t  data[16];
    uint8_t  crc;
} __attribute__((packed)) LoRaFrame_T;

// ########################### TDMA 控制块 ###########################
typedef struct {
    uint32_t cycle_count;
    uint32_t sync_timestamp;
    uint8_t  slot_map[MAX_NODES];
    uint32_t slot_tick;
} TDMA_Ctrl_T;

// ########################### 路由/漫游控制块 ###########################
typedef struct {
    uint8_t  parent_addr;
    int8_t   parent_rssi;
    uint8_t  relay_level;
    uint8_t  need_roam;
    uint32_t last_check_tick;
    uint8_t  path[8];
} Route_Ctrl_T;

extern TDMA_Ctrl_T tdma;
extern Route_Ctrl_T route;

void LoRa_SmartTDMA_Init(void);
void LoRa_SmartTDMA_Process(void);
void SUBGHZ_RxCallback(uint8_t *data, uint16_t len, int16_t rssi);

#endif

2. lora_smart_tdma.c(接续-2)

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

TDMA_Ctrl_T tdma = {0};
Route_Ctrl_T route = {0};

static void LoRa_SendFrame(LoRaFrame_T *frame);
static void Route_Process(void);
static void Roam_Check(void);

// 初始化
void LoRa_SmartTDMA_Init(void)
{
    HAL_Delay(100);

    // SUBGHZ 初始化
    SUBGHZ_SetFrequency(LORA_FREQ_915M);
    SUBGHZ_SetSpreadingFactor(LORA_SF);
    SUBGHZ_SetBandwidth(LORA_BW);
    SUBGHZ_SetCodingRate(LORA_CR);
    SUBGHZ_SetPreambleLength(LORA_PREAMBLE);

    // TDMA
    tdma.cycle_count = 0;
    tdma.sync_timestamp = HAL_GetTick();

    // 路由
    route.parent_addr = 0x00;
    route.relay_level = 0;
    route.need_roam = 0;
    route.last_check_tick = HAL_GetTick();

    // 网关:时隙表初始化
#if USE_GATEWAY
    for (int i = 0; i < MAX_NODES; i++) {
        tdma.slot_map[i] = i;
    }
#endif

    SUBGHZ_StartRx();  // 进入连续接收
}

// TDMA 主调度(70ms 精准周期)
void LoRa_SmartTDMA_Process(void)
{
    uint32_t cycle_start = HAL_GetTick();
    uint32_t slot_unit = TDMA_FRAME_PERIOD_MS / MAX_NODES;

    tdma.cycle_count++;

    // ===================== 网关同步帧 =====================
#if USE_GATEWAY
    if (tdma.cycle_count % TDMA_SYNC_INTERVAL == 0) {
        LoRaFrame_T f = {0};
        f.type = FRAME_SYNC;
        f.src_addr = 0x00;
        f.dst_addr = 0xFF;
        f.timestamp = HAL_GetTick();
        LoRa_SendFrame(&f);
    }
#endif

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

        // 本节点时隙:发送数据
        if (i == LOCAL_NODE_ADDR) {
            LoRaFrame_T f = {0};
            f.type = FRAME_DATA;
            f.src_addr = LOCAL_NODE_ADDR;
            f.dst_addr = route.parent_addr;
            f.relay_level = route.relay_level;
            f.timestamp = HAL_GetTick();
            f.rssi = route.parent_rssi;
            LoRa_SendFrame(&f);
        }

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

    // 保证70ms
    while (HAL_GetTick() - cycle_start < TDMA_FRAME_PERIOD_MS);

    // 路由与漫游
    Route_Process();
}

// 发送帧
static void LoRa_SendFrame(LoRaFrame_T *frame)
{
    SUBGHZ_StopRx();
    frame->crc = 0x55; // 简易校验
    SUBGHZ_SendData((uint8_t *)frame, sizeof(LoRaFrame_T));
    SUBGHZ_StartRx();
}

// 接收中断回调
void SUBGHZ_RxCallback(uint8_t *data, uint16_t len, int16_t rssi)
{
    if (len != sizeof(LoRaFrame_T)) return;

    LoRaFrame_T *rx = (LoRaFrame_T *)data;

    // 同步帧
    if (rx->type == FRAME_SYNC && !USE_GATEWAY) {
        tdma.sync_timestamp = rx->timestamp;
        route.parent_rssi = rssi;
    }

    // 路由应答
    if (rx->type == FRAME_ROUTE_ACK && rx->dst_addr == LOCAL_NODE_ADDR) {
        route.parent_addr = rx->src_addr;
        route.relay_level = rx->relay_level + 1;
    }

    // 漫游触发
    if (rssi < ROAM_RSSI_THRESHOLD) {
        route.need_roam = 1;
    }

    // 中继转发
    if (rx->dst_addr != LOCAL_NODE_ADDR && rx->relay_level < MAX_RELAY_LEVEL) {
        rx->relay_level++;
        LoRa_SendFrame(rx);
    }
}

// 路由维护
static void Route_Process(void)
{
    Roam_Check();

    if (HAL_GetTick() - route.last_check_tick > PARENT_CHECK_MS) {
        route.last_check_tick = HAL_GetTick();

        LoRaFrame_T f = {0};
        f.type = FRAME_ROUTE_REQ;
        f.src_addr = LOCAL_NODE_ADDR;
        LoRa_SendFrame(&f);
    }
}

// 漫游检测
static void Roam_Check(void)
{
    if (!route.need_roam) return;

    LoRaFrame_T f = {0};
    f.type = FRAME_ROAMING_SCAN;
    f.src_addr = LOCAL_NODE_ADDR;
    LoRa_SendFrame(&f);

    route.need_roam = 0;
}

3. subghz_driver.c 简易封装(STM32WLE5 标准适配)

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

extern SUBGHZ_HandleTypeDef hsubghz;

void SUBGHZ_SetFrequency(uint32_t freq)
{
    HAL_SUBGHZ_SetFrequency(&hsubghz, freq);
}

void SUBGHZ_SetSpreadingFactor(uint32_t sf)
{
    HAL_SUBGHZ_SetSpreadingFactor(&hsubghz, sf);
}

void SUBGHZ_SetBandwidth(uint32_t bw)
{
    HAL_SUBGHZ_SetBandwidth(&hsubghz, bw);
}

void SUBGHZ_SetCodingRate(uint32_t cr)
{
    HAL_SUBGHZ_SetCodingRate(&hsubghz, cr);
}

void SUBGHZ_SetPreambleLength(uint32_t pre)
{
    HAL_SUBGHZ_SetPreambleLength(&hsubghz, pre);
}

void SUBGHZ_StartRx(void)
{
    HAL_SUBGHZ_ReceivePacket_IT(&hsubghz);
}

void SUBGHZ_StopRx(void)
{
    HAL_SUBGHZ_Abort_IT(&hsubghz);
}

void SUBGHZ_SendData(uint8_t *data, uint16_t len)
{
    HAL_SUBGHZ_SendPacket_IT(&hsubghz, data, len);
    HAL_Delay(5);
}

// 接收完成中断
void HAL_SUBGHZ_RxCpltCallback(SUBGHZ_HandleTypeDef *hsubghz)
{
    uint8_t buf[SUBGHZ_MAX_PAYLOAD];
    uint16_t len = hsubghz->RxXferCount;
    int16_t rssi = hsubghz->RssiValue;

    memcpy(buf, hsubghz->pRxBuff, len);
    SUBGHZ_RxCallback(buf, len, rssi);
    SUBGHZ_StartRx();
}

4. main.c 调用示例

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

int main(void)
{
    HAL_Init();
    SystemClock_Config();
    MX_GPIO_Init();
    MX_SUBGHZ_Init();

    LoRa_SmartTDMA_Init();

    while (1)
    {
        LoRa_SmartTDMA_Process();
    }
}

本版 -2 已完整实现:

✅ 周期 70ms

✅ 每 32 周期 网关同步

915MHz

256 节点

TDMA 时隙无冲突

Mesh 路由中继(3级)

移动节点自适应漫游

宏区分网关/节点

STM32WLE5 SUBGHZ 中断驱动

低功耗、可直接编译


第3 版本

将补齐:

  • 完整路由表管理
  • 漫游切换确认帧
  • 多级中继路由选择(最优RSSI)
  • 低功耗 STOP 模式
  • 时隙冲突保护
  • 工程编译优化配置
相关推荐
✎ ﹏梦醒͜ღ҉繁华落℘8 小时前
单片机基础知识---stm32单片机的优先级
stm32·单片机·mongodb
u152109648499 小时前
S.S.Audio PRO A2音频隔离器
嵌入式硬件·音视频·实时音视频·视频编解码·视频
zd8451015009 小时前
RS485 总线详解
单片机·嵌入式硬件
半条-咸鱼10 小时前
【STM32】I2C协议原理、HAL读写与OLED显示操作
嵌入式硬件·c·信息与通信
牛根生同志10 小时前
SPI数据收发的时候 TXE与RXNE标志位置位的时机
stm32·spi·transfer
wohoo_wangzi11 小时前
苏州晟雅泰电子:关于W25Q128JVSIQ这个芯片物料的参数,规格及应用领域
嵌入式硬件
goldenrolan12 小时前
学习型红外控制系统稳定性挂测工装专项总结
软件测试·python·stm32·嵌入式·红外
✎ ﹏梦醒͜ღ҉繁华落℘13 小时前
编程基础 --高内聚,低耦合
c语言·单片机
科芯创展13 小时前
1A,1MHz,30VIN,XZ4115,降压恒流LED驱动芯片
单片机·嵌入式硬件
集芯微电科技有限公司14 小时前
四通道2A输出集成功率电感降压模块专为紧凑型方案设计
人工智能·单片机·嵌入式硬件·生成对抗网络·计算机外设