「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]='\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 }

 

 

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM