You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Time Division Multiplexing[TDM] Arduino实现及RFM23模块全双工改造咨询

Arduino平台RFM23半双工模块TDM模拟全双工实现方案

核心实现逻辑

TDM(时分复用)的核心是为通信网络内的所有节点分配互斥的收发时间片,通过全局时间同步避免半双工模块的收发冲突。RFM23的收发状态切换延迟小于1ms,采用10ms级时间片即可满足绝大多数低速率物联网场景的双向通信需求,单节点仅需1片RFM23即可实现原2片方案的双向通信能力。

硬件接线要求

和常规半双工RFM23接线方案完全一致,无需额外外设:

  • RFM23的SPI接口(SCK、MISO、MOSI)接Arduino对应SPI引脚
  • RFM23的CS引脚接Arduino自定义GPIO(示例中为10号引脚)
  • RFM23的nIRQ引脚接Arduino外部中断引脚(示例中为2号引脚)
  • RFM23的SDN引脚可接Arduino GPIO实现硬复位,也可直接接地

核心TDM调度规则

  • 网络内设1个主节点,其余为从节点,主节点周期性发送同步帧校准所有从节点的本地时钟,确保全网络时间片对齐
  • 单个通信周期可根据节点数量拆分,2节点通信时可拆分为2个等长时间片,预留1ms保护间隔抵消模块切换延迟
  • 所有数据帧采用固定格式:0xAA 0x55(帧头) + 1字节节点地址 + 1字节数据长度 + N字节 payload + 1字节CRC8校验,降低接收端识别成本

示例核心代码

基于RH_RF22库开发,可直接复用基础配置:

#include <RH_RF22.h>

// 硬件引脚定义
#define RFM23_CS_PIN  10
#define RFM23_IRQ_PIN 2
RH_RF22 rfm23(RFM23_CS_PIN, RFM23_IRQ_PIN);

// TDM参数配置
#define SYNC_PERIOD     1000    // 主节点同步帧发送间隔,单位ms
#define TIME_SLOT_MS    10      // 单时间片长度,单位ms
#define GUARD_DELAY_MS  1       // 状态切换保护间隔
bool is_master_node    = true;  // 当前节点身份配置,从节点设为false
bool current_is_tx_slot = false;
uint32_t last_sync_tick = 0;
uint32_t slot_start_tick = 0;

void setup() {
  Serial.begin(115200);
  // 初始化RFM23模块
  if (!rfm23.init()) {
    Serial.println("RFM23 init failed");
    while(1);
  }
  rfm23.setFrequency(433.0); // 按需修改通信频段
  rfm23.setTxPower(RH_RF22_TXPOW_11DBM);
}

void loop() {
  uint32_t current_tick = millis();
  // 主节点同步帧发送逻辑
  if (is_master_node && current_tick - last_sync_tick >= SYNC_PERIOD) {
    uint8_t sync_frame[] = {0xAA, 0x55, 0x00, 0x00, 0x00}; // 同步帧固定标识
    rfm23.send(sync_frame, sizeof(sync_frame));
    rfm23.waitPacketSent();
    last_sync_tick = current_tick;
    current_is_tx_slot = true;
    slot_start_tick = current_tick;
  }

  // 时间片切换逻辑
  if (current_tick - slot_start_tick >= TIME_SLOT_MS) {
    current_is_tx_slot = !current_is_tx_slot;
    slot_start_tick = current_tick;
    // 切换RFM23工作状态,加保护间隔避免冲突
    if (current_is_tx_slot) {
      rfm23.setModeTx();
    } else {
      rfm23.setModeRx();
    }
    delay(GUARD_DELAY_MS);
  }

  // 发送逻辑:仅当前为发送时间片时执行
  if (current_is_tx_slot) {
    uint8_t tx_buf[] = "Test data from local node";
    rfm23.send(tx_buf, sizeof(tx_buf));
    rfm23.waitPacketSent();
    // 按需添加自定义发送逻辑
    delay(2); // 避免单时间片内重复发送
  }

  // 接收逻辑:仅当前为接收时间片时执行
  if (!current_is_tx_slot) {
    uint8_t rx_buf[RH_RF22_MAX_MESSAGE_LEN];
    uint8_t rx_len = sizeof(rx_buf);
    if (rfm23.recv(rx_buf, &rx_len)) {
      // 跳过同步帧,处理业务数据
      if (!(rx_len == 5 && rx_buf[0] == 0xAA && rx_buf[1] == 0x55)) {
        Serial.print("Received payload: ");
        Serial.write(rx_buf, rx_len);
        Serial.println();
      } else {
        // 从节点收到同步帧时校准本地时间片
        if (!is_master_node) {
          slot_start_tick = current_tick;
          current_is_tx_slot = false;
          rfm23.setModeRx();
        }
      }
    }
  }
}

调优注意事项

  • 时间片长度需匹配单包数据的发送时长,若单包数据量大可适当延长时间片,避免单帧未发送完成就触发时间片切换
  • 若网络内节点数量超过2个,可对应增加时间片数量,每个节点分配独立的发送时间片即可
  • 长时间运行出现时钟漂移时,可缩短同步帧发送间隔到300~500ms,避免时间片错位导致的丢包
  • 丢包率较高时可在数据帧中增加序号字段,在发送时间片内增加最多2次重传逻辑

内容的提问来源于stack exchange,提问作者hadi floka

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.10.06 01:00:05