首页 > 代码库 > 「ZigBee模块」组网实验-信号传输质量检测

「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;              //波特率设为11520013     UTX0IF = 0;               //UART0 TX中断标志初始置位014 }

 

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_rf16     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_SEND31      appMode = MODE_TX;32     #else33      appMode = MODE_RX;34     #endif  35     // Transmitter application36     if(appMode == MODE_TX) {37         // No return from here38         appTransmitter();39     }40     // Receiver application41     else if(appMode == MODE_RX) {42         // No return from here43         appReceiver();44     }45     // Role is undefined. This code should not be reached46     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   //配置定时器和IO25   //暂时不知道有什么用...以后补上26   appConfigTimer(0xC8);27 28   //初始化数据包载荷29   //txPacket是什么? 就是一个数据包~在per_test.h中!30   //里面有两个变量,seqNumber和padding[6]31   //就是说一个数据包里面有6个字节的内容和一个表示序号的seqNumber32   //讲一下seqNumber 就是拿来当序号用,发送时按012345这样的顺序发送,所以理应012345这样接受33   //如果这次收到3,下次收到5,那就表示丢包了34   txPacket.seqNumber = 0;35   for(n = 0; n < sizeof(txPacket.padding); n++)  //初始化下,数据包里面就是01234536   {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++;           //发送了一个数据包了 +158 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]=\0;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("\n",strlen("\n"));136 137       halLedClear(2);138 139       halMcuWaitMs(300);140     }                    141   }142 }

 

 

 

 

 

「ZigBee模块」组网实验-信号传输质量检测