我是靠谱客的博主 魁梧水池,这篇文章主要介绍ZigBee信号传输质量检测,现在分享给大家,希望可以做个参考。

  PER(误包率检测)实验是Basic RF的第二个实验,和无线点灯一样是没有使用协议栈的点对点通讯。
  实验现象:两块WeBee模块通信,一个模块作发射,另外一个模块接收,接收模块通过串口在PC机上显示当前的误包率、RSSI值和接收到数据包的个数。

void main ( void ) {
    uint8 appMode;
    appState = IDLE;
    appStarted = TRUE;
    /* Config basicRF 配置“Basic RF” */
    basicRfConfig.panId = PAN_ID;
    basicRfConfig.ackRequest = FALSE;
    /* Initialise board peripherals 初始化外围硬件 */
    halBoardInit();

    /* Initalise hal_rf 初始化hal_rf */
    if ( halRfInit() == FAILED ) {
        HAL_ASSERT ( FALSE );
    }

    /* Indicate that device is powered */
    halLedSet ( 1 );
    /* Print Logo and splash screen on LCD */
    utilPrintLogo ( "PER Tester" );
    /* Wait for user to press S1 to enter menu */
    halMcuWaitMs ( 350 );
    /* Set channel 设置信道,规范要求信道只能为为11至25,这里选择信道11 */
    basicRfConfig.channel = 0x0B;
#ifdef MODE_SEND /* 设置模块的模式,一个作为发射,另一个为接收,看是否“define MODE_SEND” */
    appMode = MODE_TX;
#else
    appMode = MODE_RX;
#endif
    /* Transmitter application */
    if ( appMode == MODE_TX ) {
        /* No return from here 如果“define MODE_SEND”,则进入appTransmitter发射模式 */
        appTransmitter();
    } else if ( appMode == MODE_RX ) { /* Receiver application */
        /* No return from here 如果没有“define MODE_SEND”,则进入appReceiver接收模式 */
        appReceiver();
    }

    HAL_ASSERT ( FALSE ); /* Role is undefined. This code should not be reached */
}

大家看注释也应该知道main.c做了哪些事情:

  1. 一大堆的初始化(都是必须的)。
  2. 设置信道,发射和接收模块的信道必须一致。
  3. 选择为发射或者接收模式。

  发射函数define MODE_SEND则进入appTransmitter

static void appTransmitter() {
    uint32 burstSize = 0;
    uint32 pktsSent = 0;
    uint8 appTxPower;
    uint8 n;
    /* Initialize BasicRF 初始化“Basic RF” */
    basicRfConfig.myAddr = TX_ADDR;

    if ( basicRfInit ( &basicRfConfig ) == FAILED ) {
        HAL_ASSERT ( FALSE );
    }

    /* Set TX output power 设置输出功率 */
    halRfSetTxPower ( 2 ); /* HAL_RF_TXPOWER_4_DBM */
    /* Set burst size 设置进行一次测试所发送的数据包数量 */
    burstSize = 1000;
    /* Basic RF puts on receiver before transmission of packet, and turns off after packet is sent */
    basicRfReceiveOff();
    /* Config timer and IO 配置定时器和IO */
    appConfigTimer ( 0xC8 );
    /* Initalise packet payload 初始化数据包载荷 */
    txPacket.seqNumber = 0;

    for ( n = 0; n < sizeof ( txPacket.padding ); n++ ) {
        txPacket.padding[n] = n;
    }

    while ( TRUE ) {
        while ( appStarted ) {
            if ( pktsSent < burstSize ) {
                /* Make sure sequence number has network byte order */
                UINT32_HTON ( txPacket.seqNumber ); /* 改变发送序号的字节顺序 */
                basicRfSendPacket ( RX_ADDR, ( uint8 * ) &txPacket, PACKET_SIZE );
                /* Change byte order back to host order before increment 在增加序号前将字节顺序改回为主机顺序 */
                UINT32_NTOH ( txPacket.seqNumber );
                txPacket.seqNumber++; /* 数据包序列号自加1 */
                pktsSent++;
                appState = IDLE;
                halLedToggle ( 1 ); /* 改变LED1的亮灭状态 */
                halMcuWaitMs ( 500 );
            } else {
                appStarted = !appStarted;
            }

            pktsSent = 0; /* Reset statistics and sequence number 复位统计和序号 */
        }
    }
}

总结appTransmitter函数完成的任务:

  1. 初始化Basic RF
  2. 设置发射功率。
  3. 设定测试的数据包量。
  4. 配置定时器和IO
  5. 初始化数据包载荷。
  6. 进行循环函数,不断地发送数据包,每发送完一次,下一个数据包的序列号自加1再发送。
static void appReceiver() {
    uint32 segNumber = 0; /* 数据包序列号 */
    int16 perRssiBuf[RSSI_AVG_WINDOW_SIZE] = {0}; /* Ring buffer for RSSI 存储RSSI的环形缓冲区 */
    uint8 perRssiBufCounter = 0; /* Counter to keep track of the 计数器用于RSSI缓冲区统计 */
    perRxStats_t rxStats = {0, 0, 0, 0};
    int16 rssi;
    uint8 resetStats = FALSE;
    int8 Myper[5];
    int8 Myrssi[2];
    int8 Myreceive[4];
    int32 temp_per; /* 存放掉包率 */
    int32 temp_receive; /* 存放接收的包的个数 */
    int32 temp_rssi; /* 存放前32个rssi值的平均值 */
    /*-----------------------------------------------------------------------*/
    initUART();
    basicRfConfig.myAddr = RX_ADDR;

    if ( basicRfInit ( &basicRfConfig ) == FAILED )  { /* 初始化“Basic RF” */
        HAL_ASSERT ( FALSE );
    }

    basicRfReceiveOn();

    while ( TRUE ) {
        while ( !basicRfPacketIsReady() ); /* 等待新的数据包 */
        if ( basicRfReceive ( ( uint8 * ) &rxPacket, MAX_PAYLOAD_LENGTH, &rssi ) > 0 ) {
            halLedSet ( 3 ); /* 对应的引脚为P1_4 */
            UINT32_NTOH ( rxPacket.seqNumber ); /* 改变接收序号的字节顺序 */
            segNumber = rxPacket.seqNumber

            if ( resetStats ) { /* 若统计被复位,设置期望收到的数据包序号为已经收到的数据包序号 */
                rxStats.expectedSeqNum = segNumber;
                resetStats = FALSE;
            }

            rxStats.rssiSum -= perRssiBuf[perRssiBufCounter]; /* 从sum中减去旧的RSSI值 */
            perRssiBuf[perRssiBufCounter] = rssi; /* 存储新的RSSI值到环形缓冲区,之后它将被加入sum */
            rxStats.rssiSum += perRssiBuf[perRssiBufCounter]; /* 增加新的RSSI值到sum */

            if ( ++perRssiBufCounter == RSSI_AVG_WINDOW_SIZE ) {
                perRssiBufCounter = 0; /* Wrap ring buffer counter */
            }

            /* Check if received packet is the expected packet 检查接收到的数据包是否是所期望收到的数据包 */
            if ( rxStats.expectedSeqNum == segNumber ) { /* 是所期望收到的数据包 */
                rxStats.expectedSeqNum++;
            } else if ( rxStats.expectedSeqNum < segNumber ) { /* 大于期望收到的数据包的序号,则认为丢包 */
                /* If there is a jump in the sequence numbering this means some packets inbetween has been lost. */
                rxStats.lostPkts += segNumber – rxStats.expectedSeqNum;
                rxStats.expectedSeqNum = segNumber + 1;
            } else { /* 小于期望收到的数据包的序号 */
                rxStats.expectedSeqNum = segNumber + 1;
                rxStats.rcvdPkts = 0;
                rxStats.lostPkts = 0;
            }

            rxStats.rcvdPkts++;
            /*---------------以下为串口打印部分的函数---------------*/
            temp_receive = ( int32 ) rxStats.rcvdPkts;
            if ( temp_receive > 1000 ) {
                if ( halButtonPushed() == HAL_BUTTON_1 ) {
                    resetStats = TRUE;
                    rxStats.rcvdPkts = 1;
                    rxStats.lostPkts = 0;
                }
            }

            Myreceive[0] = temp_receive / 100 + '0'; /* 打印接收到数据包的个数 */
            Myreceive[1] = temp_receive % 100 / 10 + '0';
            Myreceive[2] = temp_receive % 10 + '0';
            Myreceive[3] = '';
            UartTX_Send_String ( "RECE: ", strlen ( "RECE: " ) );
            UartTX_Send_String ( Myreceive, 4 );
            UartTX_Send_String ( " ", strlen ( " " ) );
            /*--------------------------------------------------------------------------------------------*/
            temp_per = ( int32 ) ( ( rxStats.lostPkts * 1000 ) / ( rxStats.lostPkts + rxStats.rcvdPkts ) );
            Myper[0] = temp_per / 100 + '0'; /* 打印当前计算出来的误包率 */
            Myper[1] = temp_per % 100 / 10 + '0';
            Myper[2] = '.';
            Myper[3] = temp_per % 10 + '0';
            Myper[4] =  '%';
            UartTX_Send_String ( "PER: ", strlen ( "PER: " ) );
            UartTX_Send_String ( Myper, 5 );
            UartTX_Send_String ( " ", strlen ( " " ) );
            /*------------------------------------------------------------------------------------*/
            temp_rssi = ( 0 - ( int32 ) rxStats.rssiSum / 32 ); /* 打印上32个数据包的RSSI值的平均值 */
            Myrssi[0] = temp_rssi / 10 + '0';
            Myrssi[1] = temp_rssi % 10 + '0';
            UartTX_Send_String ( "RSSI: -", strlen ( "RSSI: -" ) );
            UartTX_Send_String ( Myrssi, 2 );
            UartTX_Send_String ( "n", strlen ( "n" ) );
            /*-----------------------------------------*/
            halLedClear ( 3 );
            halMcuWaitMs ( 300 );
        }
    }
}

  接收函数的作用:

  1. 串口初始化。
  2. 初始化Basic RF
  3. 不断地接收数据包,并检查数据包序号是否为期望值,作出相应处理。
  4. 串口打印出接收包的个数、误包率及上32个数据包的RSSI值的平均值。

  有几个比较重要的数据作个简要的说明一下:为了获取传输的性能参数,接收器中包含了如下几个数据(包含在rxStats变量中,其类型为perRxStats_t):

  • rxStats.expectedSeqNum:预计下一个数据包的序号,其值等于成功接收的数据包 + 丢失的数据包 + 1
  • rxStats.rssiSum:上32个数据包的RSSI值的和。
  • rxStats.rcvdPkts:每次PER测试中,成功接收到的数据包的个数。
  • rxStats.lostPkts:丢失数据包的个数。

  这些数据具体是怎么得来,我们没有必要具体去分析,直接读取我们感兴趣的数据就可以了。误包率又是怎么计数的呢?TI公司的使用文档是有说明的:The PER value per thousand packets is calculated by the formula:

P E R = 1000   ∗   r x S t a t s . l o s t P k t s r x S t a t s . l o s t P k t s + r x S t a t s . r c v d P k t s ,   ( f o r   r x S t a t s . r c v d P k t s > = 1 ) PER = 1000 * frac{rxStats.lostPkts}{rxStats.lostPkts + rxStats.rcvdPkts}, (for rxStats.rcvdPkts >= 1) PER=1000  rxStats.lostPkts+rxStats.rcvdPktsrxStats.lostPkts, (for rxStats.rcvdPkts>=1)

  如果大家想了解具体内容的话,就可以去CC2530 BasicRFdocs文件夹中找到CC2530_Software_Examples.pdf文档4.2章节。

最后

以上就是魁梧水池最近收集整理的关于ZigBee信号传输质量检测的全部内容,更多相关ZigBee信号传输质量检测内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(156)

评论列表共有 0 条评论

立即
投稿
返回
顶部