工业控制 | 能源技术 | 汽车电子 | 通信网络 | 安防监控 | 智能电网 | 移动手持 | 无线技术 | 家用电器 | 数字广播 | 消费电子 | 应用软件 | 其他方案

电路设计->综合电路图->综合电路图->编程技巧:轻松实现si446x超长数据包收发

编程技巧:轻松实现si446x超长数据包收发

作者:angelazhang时间:2015-08-15

Silicon labs EZRadioPro 系列的si446x 无线收发器,TX FIFO 和 RX FIFO只有64字节。那么如何实现超过64字节的数据包收发呢?需要繁琐的去把长包拆分成小于等于64字节的小包,每个小包单独发送,然后接收端把这些小包数据拼接回原始的长包数据吗?回答是:不!因为长包的收发在si446x 收发芯片实现是非常简单的。


打开WDS软件或者查看API寄存器描述文档,有两个中断非常有用,就是TX_FIFO_ALMOST_EMPTY_PEND 和 RX_FIFO_ALMOST_FULL_PEND,这个两个中断代表的意思就是TX FIFO 的数据即将发送完,或者RX FIFO即将被填充满。那么我们只需要根据这两个中断,就可以实现超长数据包收发了。


例如,在TX_FIFO_ALMOST_EMPTY_PEND中断产生时,立刻填充数据到TX FIFO中,新填充的数据会紧跟着之前的数据发送出去,直到数据包完全发送完成,最终产生一个发送完成中断,表示这包数据发完。接收时也是类似,当收到的数据不断往RX FIFO中填充,快要填满的时候,就会产生RX_FIFO_ALMOST_FULL_PEND中断,这时立刻把RX FIFO读取出来,那么空出来的FIFO又可以继续接收新的数据,直到接收到的总数据等于整个完整的数据包长度,产生一个接收完成中断。整个过程都是连续的,根据包长度和设定的阀值,会产生多个TX_FIFO_ALMOST_EMPTY_PEND和RX_FIFO_ALMOST_FULL_PEND中断,但是每包数据发送完成和接收完成中断只会有一个,和短包的收发是一样的。


超长数据包的具体实现步骤如下:

1、使用WDS 配置TX_FIFO_ALMOST_EMPTY和RX_FIFO_ALMOST_FULL 阀值,如图:



2、使能TX_FIFO_ALMOST_EMPTY和RX_FIFO_ALMOST_FULL中断。如图:

 


3、在收到 TX_FIFO_ALMOST_EMPTY_PEND中断时,添加对应的填充TX FIFO 代码。

   if (Si446xCmd.GET_INT_STATUS.PH_PEND &       SI446X_CMD_GET_INT_STATUS_REP_PH_PEND_PACKET_SENT_PEND_BIT)

    {

      /* Nothing is sent to TX FIFO */

      bPositionInPayload = 0u;

      /* Position to the very beginning of the custom long payload */

      pPositionInPayload = (U8*) &pRadioConfiguration->Radio_Custom_Long_Payload;

      return TRUE;

    }

   if (Si446xCmd.GET_INT_STATUS.PH_PEND &         SI446X_CMD_GET_INT_STATUS_REP_PH_PEND_TX_FIFO_ALMOST_EMPTY_PEND_BIT)

    {

        /* Calculate the number of remaining bytes has to be sent to TX FIFO */

        bNumOfRestBytes = RadioConfiguration.Radio_PacketLength - bPositionInPayload;

        if(bNumOfRestBytes > RADIO_TX_ALMOST_EMPTY_THRESHOLD)

        { // remaining byte more than threshold

          /* Fill TX FIFO with the number of THRESHOLD bytes */

          si446x_write_tx_fifo(RADIO_TX_ALMOST_EMPTY_THRESHOLD, pPositionInPayload);

          /* Calculate how many bytes are sent to TX FIFO */

          bPositionInPayload += RADIO_TX_ALMOST_EMPTY_THRESHOLD;

          /* Position to the next first byte that can be sent to TX FIFO in next round */

          pPositionInPayload += RADIO_TX_ALMOST_EMPTY_THRESHOLD;

        }

        else

        { // remaining byte less or equal than threshold

          /* Fill TX FIFO with the number of rest bytes */

          si446x_write_tx_fifo(bNumOfRestBytes, pPositionInPayload);

          /* Calculate how many bytes are sent to TX FIFO */

          bPositionInPayload += bNumOfRestBytes;

          /* Position to the next first byte that can be sent to TX FIFO in next round */

          pPositionInPayload += bNumOfRestBytes;

        }

    }


4、在收到 RX_FIFO_ALMOST_FULL_PEND中断时,添加对应的读取RX FIFO 代码。

if (Si446xCmd.GET_INT_STATUS.PH_PEND &    SI446X_CMD_GET_INT_STATUS_REP_PH_PEND_PACKET_RX_PEND_BIT)

    {

      /* Blink once LED3 as CRC OK or not enabled */

      vHmi_ChangeLedState(eHmi_Led3_c, eHmi_LedBlinkOnce_c);

      /* Calculate the number of free bytes in the array */

      bNumOfFreeBytes = RADIO_MAX_LONG_PACKET_LENGTH - bPositionInPayload;

      if (bNumOfFreeBytes >= RADIO_MAX_PACKET_LENGTH)

      {// free space in buffer more than RX FIFO size

        /* Read the RX FIFO with the number of RX FIFO size */

        si446x_read_rx_fifo(RADIO_MAX_PACKET_LENGTH, pPositionInPayload);

        /* Calculate how many bytes are already stored in the array */

        bPositionInPayload += RADIO_MAX_PACKET_LENGTH;

        /* Position to the next free byte that can be written in the next RX FIFO reading */

        pPositionInPayload += RADIO_MAX_PACKET_LENGTH;

      }

      else

      {

        /* Read the RX FIFO with the number of free bytes */

        si446x_read_rx_fifo(bNumOfFreeBytes, pPositionInPayload);

        /* Calculate how many bytes are already stored in the array */

        bPositionInPayload += bNumOfFreeBytes;

        /* Position to the next free byte that can be written in the next RX FIFO reading */

        pPositionInPayload += bNumOfFreeBytes;

      }

      /* Calculate how many bytes are already stored in the array */

       bPositionInPayload = 0u;

       /* Set writing pointer to the beginning of the array */

       pPositionInPayload = &fixRadioPacket[0u];

       /* free space */

       bNumOfFreeBytes = RADIO_MAX_LONG_PACKET_LENGTH;

       /* Start the radio */

       vRadio_StartRX(pRadioConfiguration->Radio_ChannelNumber);

      return TRUE;

    }

    if(Si446xCmd.GET_INT_STATUS.PH_PEND &       SI446X_CMD_GET_INT_STATUS_REP_PH_STATUS_RX_FIFO_ALMOST_FULL_BIT)

    {

      /* Calculate the number of free bytes in the array */

      bNumOfFreeBytes = RADIO_MAX_LONG_PACKET_LENGTH - bPositionInPayload;

      if (bNumOfFreeBytes >= RADIO_RX_ALMOST_FULL_THRESHOLD)

      { // free space in the array is more than the threshold

        /* Read the RX FIFO with the number of THRESHOLD bytes */

        si446x_read_rx_fifo(RADIO_RX_ALMOST_FULL_THRESHOLD, pPositionInPayload);

        /* Calculate how many bytes are already stored in the array */

        bPositionInPayload += RADIO_RX_ALMOST_FULL_THRESHOLD;

        /* Position to the next free byte that can be written in the next RX FIFO reading */

        pPositionInPayload += RADIO_RX_ALMOST_FULL_THRESHOLD;

      }

      else

      {

        /* Not enough free space reserved in the program */

        ERROR_HOOK;

      }

}



评论

技术专区