zoukankan      html  css  js  c++  java
  • 「ZigBee模块」组网实验-信号传输质量检测

    信号传输质量检测

    重点在代码分析部分...就是废话比较多... 

     

    一、实验平台

    两个ZigBee模块

    一个方口USB线

    一个编译器

     

    二、实验现象

    两块ZigBee模块通信,一个模块作发射,另外一个模块作接收,接收模块通过串口在PC机上显示当前的误包率、RSSI值和接收到数据包的个数

     

     

    三、准备工作

    由于硬件平台不同,所以我们需要在per_test中加入串口发送函数

     

    1. 打开工程—>application>per_test.c

      在per_test.c文件中添加串口发送函数

    2. INCLUDES中添

     #include "string.h"

    3. 在函数声明中添加

     

    void uartInit(void);//**************************
    void uartSend(int8 *Data,int len);//**********************

     

    4. 添加串口初始化函数

     

     1 /****************************************************************
     2 串口初始化函数
     3 ****************************************************************/
     4 void initUART(void)
     5 { 
     6     PERCFG = 0x00;              //位置1 P0口
     7     P0SEL = 0x0c;              //P0_2,P0_3用作串口(外部设备功能)
     8     P2DIR &= ~0XC0;          //P0优先作为UART0
     9 
    10     U0CSR |= 0x80;              //设置为UART方式
    11     U0GCR |= 11;                       
    12     U0BAUD |= 216;              //波特率设为115200
    13     UTX0IF = 0;               //UART0 TX中断标志初始置位0
    14 }

     

    5. 添加串口发送函数

     

     1 /****************************************************************
     2 串口发送字符串函数            
     3 ****************************************************************/
     4 void uartSend(int8 *Data,int len)
     5 {
     6   int j;
     7   for(j=0;j<len;j++)
     8   {
     9     U0DBUF = *Data++;
    10     while(UTX0IF == 0);
    11     UTX0IF = 0;
    12   }
    13 }

     

    6. 因为只有接收模块使用到串口,把串口初始化放入appReceiver()即可

     

    四、分析per_test.c的代码

    看代码前还是想先解释一下,这里一个数据包就是一个结构体数据类型,里面包括6个字节的内容和1个字节的序号 我们是利用序号来判断有没有发生误包的。

     

    第一步,先找到main函数

     

     1 void main (void)
     2 {
     3     //变量声明
     4     uint8 appMode;         //用来选择模式(发送或接收)
     5     
     6     appState = IDLE;
     7     
     8     //配置basic RF
     9     basicRfConfig.panId = PAN_ID;
    10     basicRfConfig.ackRequest = FALSE;
    11 
    12     //初始化外围设备
    13     halBoardInit();
    14 
    15     //初始化hal_rf
    16     if(halRfInit()==FAILED) {
    17       HAL_ASSERT(FALSE);
    18     }
    19     
    20     //点亮led1(P1.0)用以表示程序开始运行
    21     halLedSet(1);
    22 
    23     //信道设置 11—25都可以
    24     basicRfConfig.channel = 0x0B;
    25 
    26     //这里就是模式选择啦,选择完进入那个函数,然后main函数就不需要啦
    27     //这个怎么选??
    28     //看MODE_SEND,go to definition,找到定义的地方
    29     //把那行代码注释掉就是接收部分,不注释就是发送
    30     #ifdef MODE_SEND
    31      appMode = MODE_TX;
    32     #else
    33      appMode = MODE_RX;
    34     #endif  
    35     // Transmitter application
    36     if(appMode == MODE_TX) {
    37         // No return from here
    38         appTransmitter();
    39     }
    40     // Receiver application
    41     else if(appMode == MODE_RX) {
    42         // No return from here
    43         appReceiver();
    44     }
    45     // Role is undefined. This code should not be reached
    46     HAL_ASSERT(FALSE);
    47 }

     

     

    看完main函数,再来看一下发送的函数吧~

    总结一下就是一大堆初始化然后依次发送数据包

     

     1 static void appTransmitter()
     2 {
     3   //声明变量
     4   uint32 burstSize=0;     //设定进行一次测试所发送的数据包数量
     5   uint32 pktsSent=0;      //指示当前已经发了多少个数据包
     6   uint8 n;
     7 
     8   //初始化Basic RF
     9   basicRfConfig.myAddr = TX_ADDR;
    10   if(basicRfInit(&basicRfConfig)==FAILED) 
    11   {
    12     HAL_ASSERT(FALSE);
    13   }
    14 
    15   //置输出功率
    16   halRfSetTxPower(2);
    17 
    18   //设置进行一次测试所发送的数据包数量 
    19   burstSize = 1000;
    20 
    21   //关闭接收模块,省电
    22   basicRfReceiveOff();
    23 
    24   //配置定时器和IO
    25   //暂时不知道有什么用...以后补上
    26   appConfigTimer(0xC8);
    27 
    28   //初始化数据包载荷
    29   //txPacket是什么? 就是一个数据包~在per_test.h中!
    30   //里面有两个变量,seqNumber和padding[6]
    31   //就是说一个数据包里面有6个字节的内容和一个表示序号的seqNumber
    32   //讲一下seqNumber 就是拿来当序号用,发送时按012345这样的顺序发送,所以理应012345这样接受
    33   //如果这次收到3,下次收到5,那就表示丢包了
    34   txPacket.seqNumber = 0;
    35   for(n = 0; n < sizeof(txPacket.padding); n++)  //初始化下,数据包里面就是012345
    36   {
    37     txPacket.padding[n] = n;
    38   }
    39 
    40   //主循环
    41   while (TRUE) 
    42   {
    43     if (pktsSent < burstSize) //如果数据包还没有发送完,继续执行
    44     {
    45       // 改变发送序号的字节顺序
    46       //我也不知道为什么要改变顺序再改回来,可能和数据发送的一些协议有关吧,以后知道再补上
    47       UINT32_HTON(txPacket.seqNumber);
    48       
    49       //发送数据函数(发给谁, 发的内容, 数据长度) 重点就是这行代码!
    50       //注意下,发送的就是txPacket这一整个数据,包括实际内容和序号,这是一个完整的数据包
    51       basicRfSendPacket(RX_ADDR, (uint8*)&txPacket, PACKET_SIZE);
    52 
    53       //在增加序号前将字节顺序改回为主机顺序
    54       UINT32_NTOH(txPacket.seqNumber);
    55       txPacket.seqNumber++; //发的序号+1 
    56 
    57       pktsSent++;           //发送了一个数据包了 +1
    58 
    59       halLedToggle(1);   //改变LED1的亮灭状态
    60       halMcuWaitMs(500); //延时
    61     }
    62       //数据包清零
    63      pktsSent = 0;
    64 
    65   }
    66 }

     

     

    最后是接收的部分

    总结一下,开始还是一大堆初始化,然后一直接收数据、判断是不是丢包了、处理数据、串口发送

      1 static void appReceiver()
      2 {
      3   uint32 segNumber=0;                              // 数据包序列号 
      4   int16 perRssiBuf[RSSI_AVG_WINDOW_SIZE] = {0};    // 存储RSSI的环形缓冲区
      5   uint8 perRssiBufCounter = 0;                     // 计数器用于RSSI缓冲区统计
      6  
      7   perRxStats_t rxStats = {0,0,0,0};      
      8    int16 rssi;
      9   uint8 resetStats=FALSE;
     10   
     11   int8 Myper[5];        
     12   int8 Myrssi[2];
     13   int8 Myreceive[4];
     14   int32 temp_per;           //存放掉包率
     15   int32 temp_receive;       //存放接收的包的个数
     16   int32 temp_rssi;          //存放前32个rssi值的平均值
     17   uartInit();               // 初始化串口
     18   
     19 #ifdef INCLUDE_PA
     20   uint8 gain;
     21 
     22   // Select gain (for modules with CC2590/91 only)
     23   gain =appSelectGain();
     24   halRfSetGain(gain);
     25 #endif
     26     
     27    // Initialize BasicRF     初始化Basic RF 
     28   basicRfConfig.myAddr = RX_ADDR;
     29   if(basicRfInit(&basicRfConfig)==FAILED) 
     30   {
     31     HAL_ASSERT(FALSE);
     32   }
     33   //打开接收模块
     34   basicRfReceiveOn();
     35 
     36   /* 主循环 */
     37   uartSend("PER_test: ",strlen("PER_test: ")); //串口发送数据
     38     // Main loop
     39   while (TRUE) 
     40   {
     41     while(!basicRfPacketIsReady());  // 等待新的数据包
     42     //查看之后发行这里的rxPacket和发送里面的txPacket是同一种数据类型
     43     //basicRfReceive(指向数据缓冲区的指针,缓冲区最大数据长度,这个包的rssi值)
     44     //返回缓冲区实际数据长度
     45     if(basicRfReceive((uint8*)&rxPacket, MAX_PAYLOAD_LENGTH, &rssi)>0) {
     46          halLedSet(2);//*************P1_1 LED2点亮
     47             
     48       UINT32_NTOH(rxPacket.seqNumber);  // 改变接收序号的字节顺序
     49       segNumber = rxPacket.seqNumber;   //读取包的序号
     50             
     51       // If statistics is reset set expected sequence number to
     52       // received sequence number 
     53       //若统计被复位,设置期望收到的数据包序号为已经收到的数据包序号  
     54       //怎么样被认为统计复位?在后面~
     55       if(resetStats)
     56       {
     57         rxStats.expectedSeqNum = segNumber;
     58         
     59         resetStats=FALSE;
     60       }  
     61       
     62       //下面这几行代码是用来计算上32个包的RSSI值的
     63       //先预设一个32个长度的数组,用来存放RSSI值,一个指针,指示最旧的一个RSSI值
     64       //每次获取新的包后,把最旧的RSSI值从总和处减去,再把新的RSSI值放入,并把它的值加入总和
     65       // Subtract old RSSI value from sum
     66       rxStats.rssiSum -= perRssiBuf[perRssiBufCounter];  // 从sum中减去旧的RSSI值
     67       // Store new RSSI value in ring buffer, will add it to sum later
     68       perRssiBuf[perRssiBufCounter] =  rssi;  // 存储新的RSSI值到环形缓冲区,之后它将被加入sum
     69       rxStats.rssiSum += perRssiBuf[perRssiBufCounter];  // 增加新的RSSI值到sum
     70       //如果指针超出数组最大值,复位指针
     71       if(++perRssiBufCounter == RSSI_AVG_WINDOW_SIZE) {
     72         perRssiBufCounter = 0;      
     73       }
     74 
     75       
     76       //检查接收到的数据包是否是所期望收到的数据包
     77       // 是所期望收到的数据包
     78       if(rxStats.expectedSeqNum == segNumber)   
     79       {
     80         rxStats.expectedSeqNum++;  
     81       }
     82       
     83       // 不是所期望收到的数据包(大于期望收到的数据包的序号)
     84       // 认为丢包
     85       else if(rxStats.expectedSeqNum < segNumber)  
     86       {                                            
     87         rxStats.lostPkts += segNumber - rxStats.expectedSeqNum;
     88         rxStats.expectedSeqNum = segNumber + 1;
     89       }
     90       
     91       // (小于期望收到的数据包的序号)
     92       //认为是一个新的测试开始,复位统计变量
     93       else  
     94       {              
     95         rxStats.expectedSeqNum = segNumber + 1;
     96         rxStats.rcvdPkts = 0;
     97         rxStats.lostPkts = 0;
     98       }
     99       rxStats.rcvdPkts++;
    100       
    101       //以下代码都是用于串口输出计算值的
    102       temp_receive=(int32)rxStats.rcvdPkts;
    103        if(temp_receive>1000)
    104       {
    105        if(halButtonPushed()==HAL_BUTTON_1){
    106        resetStats = TRUE;
    107        rxStats.rcvdPkts = 1;
    108        rxStats.lostPkts = 0;
    109         }
    110       }
    111 
    112       Myreceive[0]=temp_receive/100+'0';
    113       Myreceive[1]=temp_receive%100/10+'0';
    114       Myreceive[2]=temp_receive%10+'0';
    115       Myreceive[3]='';
    116       uartSend("RECE:",strlen("RECE:"));
    117       uartSend(Myreceive,4);
    118       uartSend("    ",strlen("    "));   
    119       
    120       temp_per = (int32)((rxStats.lostPkts*1000)/(rxStats.lostPkts+rxStats.rcvdPkts));
    121       Myper[0]=temp_per/100+'0';
    122       Myper[1]=temp_per%100/10+'0'; 
    123       Myper[2]='.';
    124       Myper[3]=temp_per%10+'0';
    125       Myper[4]='%';
    126       uartSend("PER:",strlen("PER:"));
    127       uartSend(Myper,5);
    128       uartSend("    ",strlen("    "));
    129      
    130       temp_rssi=(0-(int32)rxStats.rssiSum/32);
    131       Myrssi[0]=temp_rssi/10+'0';
    132       Myrssi[1]=temp_rssi%10+'0';
    133       uartSend("RSSI:-",strlen("RSSI:-"));
    134       uartSend(Myrssi,2);        
    135       uartSend("
    ",strlen("
    "));
    136 
    137       halLedClear(2);
    138 
    139       halMcuWaitMs(300);
    140     }                    
    141   }
    142 }

     

     

     

     

  • 相关阅读:
    POJ
    POJ-2253 Frogger(最短路)
    背包问题(转自背包九讲+对应题目)
    POJ-1860 Currency Exchange (最短路)
    Bellman-Ford 最短路径算法
    POJ-3295 Tautology (构造)
    POJ-2586 Y2K Accounting Bug 贪心
    POJ 2965 The Pilots Brothers' refrigerator (暴力枚举)
    python(pymysql操作数据库)
    python复习概念__oop中
  • 原文地址:https://www.cnblogs.com/Donut/p/4135648.html
Copyright © 2011-2022 走看看