PER(誤包率檢測)實驗是 BasicRF 的第二個實驗,和無線點燈一樣是沒有使用協議棧的點對點通訊。
通過無線點燈大家應該對 zigbee 的發射和接收有個感性的認識,本次實驗講解不會像無線點燈一樣講得那么詳細,因為接收發射的過程基本上是一樣的,
但也希望初學者能自己認真學習一下這個實驗,相信會對無線傳輸會有一個更清晰的認識。
實驗現象:
兩塊 WeBee 模塊通信,一個模塊作發射,另外一個模塊接收,接收模塊通過串口不在 PC 機上顯示當前的誤包率、 RSSI 值和接收到數據包的個數
實驗詳解:
例程的源代碼 CC2530 BasicRF.rar 是 TI 官網上下載的,打開\CC2530BasicRF\ide\srf05_cc2530\iar 里面的 per_test.eww 工程,
由於我們的硬件平台不同於 TI 的開發板,所以我們需要在 per_test 中加入串口發送函數,才能在串口調試助手上看到我們的實驗現象。
打開工程,在 application 文件夾點 per_test.c 我們的主要功能函數都在這里 ,在這個.c 文件中添加串口發送函數 INCLUDES 中添加: #include “string.h”
然后繼續添加串口初始化和發送函數:

/**************************************************************** 串口初始化函數 ****************************************************************/ void initUART(void) { PERCFG = 0x00; //位置1 P0口 P0SEL = 0x0c; //P0_2,P0_3用作串口(外部設備功能) P2DIR &= ~0XC0; //P0優先作為UART0 U0CSR |= 0x80; //設置為UART方式 U0GCR |= 11; U0BAUD |= 216; //波特率設為115200 UTX0IF = 0; //UART0 TX中斷標志初始置位0 } /**************************************************************** 串口發送字符串函數 ****************************************************************/ void UartTX_Send_String(int8 *Data,int len) { int j; for(j=0;j<len;j++) { U0DBUF = *Data++; while(UTX0IF == 0); UTX0IF = 0; } }
很簡單地就把串口搞定了,因為只有接收模塊才會用到串口,所以串口的初始化只需要放在 appReceiver ( )函數中
下面分析整個工程的發送和接收過程
首先還是要先找到 main.c
1 /*********************************************************************************** 2 * @fn main 3 * 4 * @brief This is the main entry of the "PER test" application. 5 * 6 * @param basicRfConfig - file scope variable. Basic RF configuration data 7 * appState - file scope variable. Holds application state 8 * appStarted - file scope variable. Used to control start and stop of 9 * transmitter application. 10 * 11 * @return none 12 */ 13 void main (void) 14 { 15 uint8 appMode; 16 17 appState = IDLE; 18 appStarted = TRUE;//*****************************by boo 19 20 // Config basicRF 配置 Basic RF 21 basicRfConfig.panId = PAN_ID; 22 basicRfConfig.ackRequest = FALSE; 23 24 // Initialise board peripherals 初始化外圍硬件 25 halBoardInit(); 26 27 // Initalise hal_rf初始化 hal_rf 28 if(halRfInit()==FAILED) { 29 HAL_ASSERT(FALSE); 30 } 31 32 // Indicate that device is powered 33 halLedSet(1); 34 35 // Print Logo and splash screen on LCD 36 utilPrintLogo("PER Tester"); 37 38 // Wait for user to press S1 to enter menu 39 // while (halButtonPushed()!=HAL_BUTTON_1);*********************** 40 halMcuWaitMs(350); 41 // halLcdClear();************************************ 42 43 // Set channel
//設置信道,規范要求信道只能為為 11——25。這里選擇信道 11 44 // basicRfConfig.channel = appSelectChannel(); 45 basicRfConfig.channel = 0x0B; 46 47 48 // Set mode 49 // appMode = appSelectMode();****************** 50 51 #ifdef MODE_SEND 52 appMode = MODE_TX; 53 #else 54 appMode = MODE_RX; 55 #endif 56 // Transmitter application 57 if(appMode == MODE_TX) { 58 // No return from here 59 appTransmitter(); 60 } 61 // Receiver application 62 else if(appMode == MODE_RX) { 63 // No return from here 64 appReceiver(); 65 } 66 // Role is undefined. This code should not be reached 67 HAL_ASSERT(FALSE); 68 }
大家看注釋也應該知道 main.c 做了哪些事情:
1、 一大堆的初始化(都是必須的)
2、 設置信道,發射和接收模塊的信道必須一致
3、 選擇為發射或者接收模式
發射函數 define MODE_SEND 則進入 appTransmitter();
/*********************************************************************************** * @fn appTransmitter * * @brief Application code for the transmitter mode. Puts MCU in endless * loop * * @param basicRfConfig - file scope variable. Basic RF configuration data * txPacket - file scope variable of type perTestPacket_t * appState - file scope variable. Holds application state * appStarted - file scope variable. Controls start and stop of * transmission * * @return none */ 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 /* 設置輸出功率 */ //appTxPower = appSelectOutputPower(); halRfSetTxPower(2);//HAL_RF_TXPOWER_4_DBM // halRfSetTxPower(appTxPower); // Set burst size /* 設置進行一次測試所發送的數據包數量 */ //burstSize = appSelectBurstSize(); burstSize = 1000; // Basic RF puts on receiver before transmission of packet, and turns off // after packet is sent basicRfReceiveOff(); // Config timer and IO /* 配置定時器和IO *************************/ //n= appSelectRate(); appConfigTimer(0xC8); //halJoystickInit(); // Initalise packet payload /* 初始化數據包載荷 */ txPacket.seqNumber = 0; for(n = 0; n < sizeof(txPacket.padding); n++) { txPacket.padding[n] = n; } //halLcdClear(); //halLcdWriteCharString(0,HAL_LCD_LINE_1, "Mode:Transmitter"); //halLcdWriteCharString(0,HAL_LCD_LINE_2, "CENTER to start/stop"); // Main loop /* 主循環 */ while (TRUE) { // Wait for user to start application //while(!halJoystickPushed()); // 等待用戶啟動應用 //appStartStop(); while(appStarted) { //{ //if( halJoystickPushed()) //{ // appStartStop(); //} if (pktsSent < burstSize) { //if( appState == TRANSMIT_PACKET ) //{ // 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++; pktsSent++; /* #ifdef SRF04EB utilLcdDisplayValue(HAL_LCD_LINE_2, "Sent: ", (int32)pktsSent, NULL); #else utilLcdDisplayValue(HAL_LCD_LINE_3, "Sent: ", (int32)pktsSent, NULL); #endif*/ appState = IDLE; halLedToggle(1); //改變LED1的亮滅狀態 halMcuWaitMs(5000); //} } else appStarted = !appStarted; //} // Reset statistics and sequence number/* 復位統計和序號 */ pktsSent = 0; //txPacket.seqNumber = 0; //halLcdClear(); //halLedClear(3); //halLcdWriteCharString(0,HAL_LCD_LINE_1, "Mode:Transmitter"); //halLcdWriteCharString(0,HAL_LCD_LINE_2, "CENTER to start/stop"); } } }
總結 appTransmitter 函數完成的任務:
1、初始化 Basic RF
2、設置發射功率
3、設定測試的數據包量
4、配置定時器和 IO
5、初始化數據包載荷
6、進行循環函數,不斷地發送數據包,每發送完一次,下一個數據包的序列號自加 1 再發送
接收函數沒有 define MODE_SEND 則進入 appReceiver () ///接收函數比較長,
/*********************************************************************************** * @fn appReceiver * * @brief Application code for the receiver mode. Puts MCU in endless loop * * @param basicRfConfig - file scope variable. Basic RF configuration data * rxPacket - file scope variable of type perTestPacket_t * * @return none */ 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緩沖區統計 // oldest newest byte in RSSI // ring buffer 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(); // 初始化串口 #ifdef INCLUDE_PA uint8 gain; // Select gain (for modules with CC2590/91 only) gain =appSelectGain(); halRfSetGain(gain); #endif // Initialize BasicRF 初始化Basic RF basicRfConfig.myAddr = RX_ADDR; if(basicRfInit(&basicRfConfig)==FAILED) { HAL_ASSERT(FALSE); } basicRfReceiveOn(); //halLcdClear(); //halLcdWriteCharString(0,HAL_LCD_LINE_1, "Mode:Receiver"); //halLcdWriteCharString(0,HAL_LCD_LINE_3, "Ready"); /* 主循環 */ UartTX_Send_String("PER_test: ",strlen("PER_test: ")); // Main loop while (TRUE) { while(!basicRfPacketIsReady()); // 等待新的數據包 if(basicRfReceive((uint8*)&rxPacket, MAX_PAYLOAD_LENGTH, &rssi)>0) { halLedToggle(1);//*************P1_0 // Change byte order from network to host order UINT32_NTOH(rxPacket.seqNumber); // 改變接收序號的字節順序 segNumber = rxPacket.seqNumber; // If statistics is reset set expected sequence number to // received sequence number 若統計被復位,設置期望收到的數據包序號為已經收到的數據包序號 if(resetStats) { rxStats.expectedSeqNum = segNumber; resetStats=FALSE; } // Subtract old RSSI value from sum rxStats.rssiSum -= perRssiBuf[perRssiBufCounter]; // 從sum中減去舊的RSSI值 // Store new RSSI value in ring buffer, will add it to sum later 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++; } // If there is a jump in the sequence numbering this means some packets in // between has been lost. else if(rxStats.expectedSeqNum < segNumber) // 不是所期望收到的數據包(大於期望收到的數據包的序號) { // 認為丟包 rxStats.lostPkts += segNumber - rxStats.expectedSeqNum; rxStats.expectedSeqNum = segNumber + 1; } // If the sequence number is lower than the previous one, we will assume a // new data burst has started and we will reset our statistics variables. else // (小於期望收到的數據包的序號) { // Update our expectations assuming this is a new burst*****認為是一個新的測試開始,復位統計變量 rxStats.expectedSeqNum = segNumber + 1; rxStats.rcvdPkts = 0; rxStats.lostPkts = 0; } rxStats.rcvdPkts++; // reset statistics if button 1 is pressed 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]='\0'; 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); 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); // Update LCD // PER in units per 1000 /* utilLcdDisplayValue(HAL_LCD_LINE_1, "PER: ", (int32)((rxStats.lostPkts*1000)/(rxStats.lostPkts+rxStats.rcvdPkts)), " /1000"); utilLcdDisplayValue(HAL_LCD_LINE_2, "RSSI: ", (int32)rxStats.rssiSum/32, "dBm"); #ifndef SRF04EB utilLcdDisplayValue(HAL_LCD_LINE_3, "Recv'd: ", (int32)rxStats.rcvdPkts, NULL); #endif halLedClear(3);*/ } } }
接收函數的作用:
1、 串口在此初始化
2、 初始化 Basic RF
3、 不斷地接收數據包,並檢查數據包序號是否為期望值,作出相應處理
4、 串口打印出,接收包的個數\誤包率及上 32 個數據包的 RSSI 值的平均值
有幾個比較重要的數據作個簡要的說明一下:
為了獲取傳輸的性能參數,接收器中包含了如下幾個數據(包含在 rxStats變量中,其類型為 perRxStats_t)
rxStats.expectedSeqNum 預計下一個數據包的序號, 其值等於“成功接收的數據包”+“丟失的數據包”+1
rxStats.rssiSum 上32個數據包的RSSI值的和
rxStats.rcvdPkts 每次PER測試中,成功接受到的數據包的個數
rxStats.lostPkts 丟失數據包的個數
這些數據具體是怎么得來,我們沒有必要具體去分析,直接讀取我們感興趣的數據就可以了
誤包率又是怎么計數的呢? TI 公司的使用文檔有說明的如果大家想了解具體的話就可以去\CC2530 BasicRF\docs 文件夾中找到
CC2530_Software_Examples.pdf 文檔 4.2 章節有詳細介紹的
實驗操作:
a) 下載發射模塊,在 per_test.c 中,找到:
/********************important select or shelt****************************/ #define MODE_SEND //屏蔽時: appReceiver //不屏蔽時: appTransmitter /******************************************************************/
不要屏蔽#define MODE_SEND 編譯下載到發射模塊
b) 下載接收模塊,同樣的找到
/********************important select or shelt****************************/ //#define MODE_SEND //屏蔽時: appReceiver //不屏蔽時: appTransmitter /******************************************************************/
要屏蔽#define MODE_SEND 編譯下載到接收模塊
3、 接收模塊 USB 連接 PC 機並給發射模塊供電,打開串口調試助手,並設置好相應的 COM 口和波特率,先開接收模塊,再開發送模塊。
然后就可以看到我們的實驗現象了。如圖 5 所示。由於距離比較近,所以掉包不明顯的,有興趣的可以把發送節點拿到較遠的地方,然后觀察掉包率。
或者先打開發送模塊,再打開接收模塊來測試掉包,會顯示出掉包情況。
完整PER_test.c代碼:

/*********************************************************************************** Filename: per_test.c Description: This application functions as a packet error rate (PER) tester. One node is set up as transmitter and the other as receiver. The role and configuration parameters for the PER test of the node is chosen on initalisation by navigating the joystick and confirm the choices with S1. The configuration parameters are channel, burst size and tx power. Push S1 to enter the menu. Then the configuration parameters are set by pressing joystick to right or left (increase/decrease value) and confirm with S1. After configuration of both the receiver and transmitter, the PER test is started by pressing joystick up on the transmitter. By pressing joystick up again the test is stopped. ***********************************************************************************/ /*********************************************************************************** * INCLUDES */ #include "hal_lcd.h" #include "hal_led.h" #include "hal_int.h" #include "hal_timer_32k.h" #include "hal_joystick.h" #include "hal_button.h" #include "hal_board.h" #include "hal_rf.h" #include "hal_assert.h" #include "util_lcd.h" #include "basic_rf.h" #include "per_test.h" #include "string.h" /*********************************************************************************** * CONSTANTS */ // Application states #define IDLE 0 #define TRANSMIT_PACKET 1 /*****************************important select or shelt***********************************/ #define MODE_SEND //屏蔽時:appReceiver //不屏蔽時:appTransmitter /*******************************************************************************/ /*********************************************************************************** * LOCAL VARIABLES */ static basicRfCfg_t basicRfConfig; static perTestPacket_t txPacket; static perTestPacket_t rxPacket; static volatile uint8 appState; static volatile uint8 appStarted; /*********************************************************************************** * LOCAL FUNCTIONS */ static void appTimerISR(void); static void appStartStop(void); static void appTransmitter(); static void appReceiver(); void initUART(void);//************************** void UartTX_Send_String(int8 *Data,int len);//********************** /**************************************************************** 串口初始化函數 ****************************************************************/ void initUART(void) { PERCFG = 0x00; //位置1 P0口 P0SEL = 0x0c; //P0_2,P0_3用作串口(外部設備功能) P2DIR &= ~0XC0; //P0優先作為UART0 U0CSR |= 0x80; //設置為UART方式 U0GCR |= 11; U0BAUD |= 216; //波特率設為115200 UTX0IF = 0; //UART0 TX中斷標志初始置位0 } /**************************************************************** 串口發送字符串函數 ****************************************************************/ void UartTX_Send_String(int8 *Data,int len) { int j; for(j=0;j<len;j++) { U0DBUF = *Data++; while(UTX0IF == 0); UTX0IF = 0; } } /*********************************************************************************** * @fn appTimerISR * * @brief 32KHz timer interrupt service routine. Signals PER test transmitter * application to transmit a packet by setting application state. * * @param none * * @return none */ static void appTimerISR(void) { appState = TRANSMIT_PACKET; } /*********************************************************************************** * @fn appStartStop * * @brief Joystick up interrupt service routine. Start or stop 32KHz timer, * and thereby start or stop PER test packet transmission. * * @param none * * @return none */ static void appStartStop(void) { // toggle value appStarted ^= 1; if(appStarted) { halTimer32kIntEnable(); } else { halTimer32kIntDisable(); } } /*********************************************************************************** * @fn appConfigTimer * * @brief Configure timer interrupts for application. Uses 32KHz timer * * @param uint16 rate - Frequency of timer interrupt. This value must be * between 1 and 32768 Hz * * @return none */ static void appConfigTimer(uint16 rate) { halTimer32kInit(TIMER_32K_CLK_FREQ/rate); halTimer32kIntConnect(&appTimerISR); } /*********************************************************************************** * @fn appReceiver * * @brief Application code for the receiver mode. Puts MCU in endless loop * * @param basicRfConfig - file scope variable. Basic RF configuration data * rxPacket - file scope variable of type perTestPacket_t * * @return none */ 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緩沖區統計 // oldest newest byte in RSSI // ring buffer 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(); // 初始化串口 #ifdef INCLUDE_PA uint8 gain; // Select gain (for modules with CC2590/91 only) gain =appSelectGain(); halRfSetGain(gain); #endif // Initialize BasicRF 初始化Basic RF basicRfConfig.myAddr = RX_ADDR; if(basicRfInit(&basicRfConfig)==FAILED) { HAL_ASSERT(FALSE); } basicRfReceiveOn(); //halLcdClear(); //halLcdWriteCharString(0,HAL_LCD_LINE_1, "Mode:Receiver"); //halLcdWriteCharString(0,HAL_LCD_LINE_3, "Ready"); /* 主循環 */ UartTX_Send_String("PER_test: ",strlen("PER_test: ")); // Main loop while (TRUE) { while(!basicRfPacketIsReady()); // 等待新的數據包 if(basicRfReceive((uint8*)&rxPacket, MAX_PAYLOAD_LENGTH, &rssi)>0) { halLedToggle(1);//*************P1_0 // Change byte order from network to host order UINT32_NTOH(rxPacket.seqNumber); // 改變接收序號的字節順序 segNumber = rxPacket.seqNumber; // If statistics is reset set expected sequence number to // received sequence number 若統計被復位,設置期望收到的數據包序號為已經收到的數據包序號 if(resetStats) { rxStats.expectedSeqNum = segNumber; resetStats=FALSE; } // Subtract old RSSI value from sum rxStats.rssiSum -= perRssiBuf[perRssiBufCounter]; // 從sum中減去舊的RSSI值 // Store new RSSI value in ring buffer, will add it to sum later 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++; } // If there is a jump in the sequence numbering this means some packets in // between has been lost. else if(rxStats.expectedSeqNum < segNumber) // 不是所期望收到的數據包(大於期望收到的數據包的序號) { // 認為丟包 rxStats.lostPkts += segNumber - rxStats.expectedSeqNum; rxStats.expectedSeqNum = segNumber + 1; } // If the sequence number is lower than the previous one, we will assume a // new data burst has started and we will reset our statistics variables. else // (小於期望收到的數據包的序號) { // Update our expectations assuming this is a new burst*****認為是一個新的測試開始,復位統計變量 rxStats.expectedSeqNum = segNumber + 1; rxStats.rcvdPkts = 0; rxStats.lostPkts = 0; } rxStats.rcvdPkts++; // reset statistics if button 1 is pressed 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]='\0'; 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); 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); // Update LCD // PER in units per 1000 /* utilLcdDisplayValue(HAL_LCD_LINE_1, "PER: ", (int32)((rxStats.lostPkts*1000)/(rxStats.lostPkts+rxStats.rcvdPkts)), " /1000"); utilLcdDisplayValue(HAL_LCD_LINE_2, "RSSI: ", (int32)rxStats.rssiSum/32, "dBm"); #ifndef SRF04EB utilLcdDisplayValue(HAL_LCD_LINE_3, "Recv'd: ", (int32)rxStats.rcvdPkts, NULL); #endif halLedClear(3);*/ } } } /*********************************************************************************** * @fn appTransmitter * * @brief Application code for the transmitter mode. Puts MCU in endless * loop * * @param basicRfConfig - file scope variable. Basic RF configuration data * txPacket - file scope variable of type perTestPacket_t * appState - file scope variable. Holds application state * appStarted - file scope variable. Controls start and stop of * transmission * * @return none */ 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 /* 設置輸出功率 */ //appTxPower = appSelectOutputPower(); halRfSetTxPower(2);//HAL_RF_TXPOWER_4_DBM // halRfSetTxPower(appTxPower); // Set burst size /* 設置進行一次測試所發送的數據包數量 */ //burstSize = appSelectBurstSize(); burstSize = 1000; // Basic RF puts on receiver before transmission of packet, and turns off // after packet is sent basicRfReceiveOff(); // Config timer and IO /* 配置定時器和IO *************************/ //n= appSelectRate(); appConfigTimer(0xC8); //halJoystickInit(); // Initalise packet payload /* 初始化數據包載荷 */ txPacket.seqNumber = 0; for(n = 0; n < sizeof(txPacket.padding); n++) { txPacket.padding[n] = n; } //halLcdClear(); //halLcdWriteCharString(0,HAL_LCD_LINE_1, "Mode:Transmitter"); //halLcdWriteCharString(0,HAL_LCD_LINE_2, "CENTER to start/stop"); // Main loop /* 主循環 */ while (TRUE) { // Wait for user to start application //while(!halJoystickPushed()); // 等待用戶啟動應用 //appStartStop(); while(appStarted) { //{ //if( halJoystickPushed()) //{ // appStartStop(); //} if (pktsSent < burstSize) { //if( appState == TRANSMIT_PACKET ) //{ // 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++; pktsSent++; /* #ifdef SRF04EB utilLcdDisplayValue(HAL_LCD_LINE_2, "Sent: ", (int32)pktsSent, NULL); #else utilLcdDisplayValue(HAL_LCD_LINE_3, "Sent: ", (int32)pktsSent, NULL); #endif*/ appState = IDLE; halLedToggle(1); //改變LED1的亮滅狀態 halMcuWaitMs(5000); //} } else appStarted = !appStarted; //} // Reset statistics and sequence number/* 復位統計和序號 */ pktsSent = 0; //txPacket.seqNumber = 0; //halLcdClear(); //halLedClear(3); //halLcdWriteCharString(0,HAL_LCD_LINE_1, "Mode:Transmitter"); //halLcdWriteCharString(0,HAL_LCD_LINE_2, "CENTER to start/stop"); } } } /*********************************************************************************** * @fn main * * @brief This is the main entry of the "PER test" application. * * @param basicRfConfig - file scope variable. Basic RF configuration data * appState - file scope variable. Holds application state * appStarted - file scope variable. Used to control start and stop of * transmitter application. * * @return none */ void main (void) { uint8 appMode; appState = IDLE; appStarted = TRUE;//*****************************by boo // Config basicRF basicRfConfig.panId = PAN_ID; basicRfConfig.ackRequest = FALSE; // Initialise board peripherals halBoardInit(); // Initalise 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 // while (halButtonPushed()!=HAL_BUTTON_1);*********************** halMcuWaitMs(350); // halLcdClear();************************************ // Set channel // basicRfConfig.channel = appSelectChannel(); basicRfConfig.channel = 0x0B; // Set mode // appMode = appSelectMode();****************** #ifdef MODE_SEND appMode = MODE_TX; #else appMode = MODE_RX; #endif // Transmitter application if(appMode == MODE_TX) { // No return from here appTransmitter(); } // Receiver application else if(appMode == MODE_RX) { // No return from here appReceiver(); } // Role is undefined. This code should not be reached HAL_ASSERT(FALSE); } /*********************************************************************************** Copyright 2008 Texas Instruments Incorporated. All rights reserved. IMPORTANT: Your use of this Software is limited to those specific rights granted under the terms of a software license agreement between the user who downloaded the software, his/her employer (which must be your employer) and Texas Instruments Incorporated (the "License"). You may not use this Software unless you agree to abide by the terms of the License. The License limits your use, and you acknowledge, that the Software may not be modified, copied or distributed unless embedded on a Texas Instruments microcontroller or used solely and exclusively in conjunction with a Texas Instruments radio frequency transceiver, which is integrated into your product. Other than for the foregoing purpose, you may not use, reproduce, copy, prepare derivative works of, modify, distribute, perform, display or sell this Software and/or its documentation for any purpose. YOU FURTHER ACKNOWLEDGE AND AGREE THAT THE SOFTWARE AND DOCUMENTATION ARE PROVIDED 揂S IS?WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS OR IMPLIED, INCLUDING WITHOUT LIMITATION, ANY WARRANTY OF MERCHANTABILITY, TITLE, NON-INFRINGEMENT AND FITNESS FOR A PARTICULAR PURPOSE. IN NO EVENT SHALL TEXAS INSTRUMENTS OR ITS LICENSORS BE LIABLE OR OBLIGATED UNDER CONTRACT, NEGLIGENCE, STRICT LIABILITY, CONTRIBUTION, BREACH OF WARRANTY, OR OTHER LEGAL EQUITABLE THEORY ANY DIRECT OR INDIRECT DAMAGES OR EXPENSES INCLUDING BUT NOT LIMITED TO ANY INCIDENTAL, SPECIAL, INDIRECT, PUNITIVE OR CONSEQUENTIAL DAMAGES, LOST PROFITS OR LOST DATA, COST OF PROCUREMENT OF SUBSTITUTE GOODS, TECHNOLOGY, SERVICES, OR ANY CLAIMS BY THIRD PARTIES (INCLUDING BUT NOT LIMITED TO ANY DEFENSE THEREOF), OR OTHER SIMILAR COSTS. Should you have any questions regarding your right to use this Software, contact Texas Instruments Incorporated at www.TI.com. ***********************************************************************************/