SI4463的数据冲撞解决办法

无线数据解决冲撞的最好的办法就是从源头避免,这就需要在发送数据之前检测当前信道是否有其他数据正在发送,如当前信道正在被占用,采用一定的退避算法,例如简单的延时来避免空中的数据冲突。

  • 提供了以下两种方案:
    • 1、读取当前信道的RSSI(Received Signal Strength indicator)信号强度
    • 2、检测当前信道是否存在有效前导码(Preamble)

一、如何获取当前RSSI

Silicon Labs提供了两种方法:
    1、GET_MODEM_STATUS命令来获取CURR_RSSI和LATCH_RSSI

SI4463的数据冲撞解决办法_第1张图片
2、直接读取(Fast Response Register A) 快速响应寄存器。

u8 si4463_read_rssi(void) {
    u8 send_data = 0x50, frr[4];

    SPI1_CSN_L;
    SPI_Write(&send_data, 1);
    get_data_group(frr, 4);
    SPI1_CSN_H;
    return frr[0];
}

注意事项:

  1. 需要配置MODEM_RSSI_CONTROL=0x02( Latches at sync detect当同步字检测到之后锁存RSSI)

其目的是确定锁存的 RSSI 值没有超出阈值。如果锁存的 RSSI 超出阈值,则不会发生中断,数据包的接收继续正常进行。如果锁存的 RSSI 低于阈值,则芯片转换为 START_RX:RXTIMEOUT_STATE,并生成 INVALID_PREAMBLE中断(如果启用)。利用跳频时,接收器调到下一频率的其中一个条件是 INVALID_PREAMBLE。

  1. RSSI阈值控制MODEM_RSSI_THRESH默认值为0xFF(理解为最大值)
  2. GPIO快速输出RSSI阈值信号,是通过空闲信道检测(CCA)

CCA(空闲信道评估)信号是可以输出到其中一个 GPIO(在 API 文档中查找 GPIO_PIN_CFG)的信号之一。如果当前 RSSI
值高于 MODEM_RSSI_THRESH 中给出的阈值,则它会变高电平,如果当前 RSSI
值低于此阈值,则它会变低电平。只要接收器打开,此信号就会不断更新。

二、检测当前信道前导码

前导码配置:

#define RF_PREAMBLE_TX_LENGTH_9 0x11, 0x10, 0x09, 0x00, 0x08, 0x14, 0x00, 0x0F, 0x31, 0x00, 0x00, 0x00, 0x00

有如下配置:

  1. PREAMBLE_TX_LENGTH = 0x08 Byte;前导码为八字节传输
  2. RX_THRESH[6:0] - default:0x14 ; 当检测到14bits有效位则表示前导码被检测到
  3. RX_PREAMBLE_TIMEOUT[3:0] - default:0xF ;
  4. STANDARD_PREAM[1:0] - default:0x1 = Use standard preamble of 1010
  5. PATTERN_31_24[7:0] - default:0x00 = Preambles always sent bits 0–31 timewise。前导码按时间顺序发送

    程序代码如下:

u8 si4463_detect_preamble(u8 ch) {
    IWDG_ReloadCounter();
    u8 API_Write[7];
    API_Write[0] = CMD_GET_INT_STATUS; 
    API_Write[1] = 0xFB;                //其他位状态保留
    API_Write[2] = 0x00;                //清除MODEM_CLR_PEND
    API_Write[3] = 0xFF;               
    send_command(ch, API_Write, 4);        
    get_response(ch, API_Write, 8);          
    if (API_Write[4] & 0x02) {
        //If set, PREAMBLE_DETECT interrupt is pending
        return 1;
    }
    return 0;
}

SI4463的数据冲撞解决办法_第2张图片

实际测试经验:

  1. MODE_PEND中断挂起比MODEM_STATUS置位要快;因此我检测的是PEND
  2. 前导检测中断或无效的前导码会同时出现置位;我的做法是直接根据前导码中断,则等待后再次检测

三、根据GPIO快速读取当前信道是否有前导码存在

1、配置gpio:
//GPIO0用来检测是否存在有效前导码;GPIO1用来检测是否存在无效的前导码(实测作用不大)
u8 API_Write[8] = {0x13, 0x40|24, 0x40|25, 0x00, 0x00, 0x00, 0x00, 0x00};
set_cmd(API_Write, 8);

SI4463的数据冲撞解决办法_第3张图片
这里写图片描述
检测程序代码段

    #define valid_preamble GPIO_ReadInputDataBit(GPIOA,GPIO_Pin_8)
     while (valid_preamble && retry > 0) {
        //实测每个有效数据包的持续时间为5ms
        rt_thread_delay(6*RT_TICK_PER_SECOND/1000);
        if (waitms > 20)
            waitms -= 6;
        retry--;
    }

实际压测结果:

  1. 从节点源头上避免了数据冲突,可以增大信道的通讯量
  2. 如还有其他小概率性丢数据情况,请添加两到三次的重发机制
  3. 网关侧会出现广播数据与节点数据同时发,会出现冲突现象
  4. 两个节点之间的数据间隔15ms也会导致数据丢失
  5. 实际压力测试丢包率为0.2%

你可能感兴趣的:(无线射频【IOT】)