ZigBee开发(11)--组网实验PER
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. ***********************************************************************************/