PER(误包率检测)实验是Basic RF的第二个实验,和无线点灯一样是没有使用协议栈的点对点通讯。
实验现象:两块WeBee模块通信,一个模块作发射,另外一个模块接收,接收模块通过串口在PC机上显示当前的误包率、RSSI值和接收到数据包的个数。
void main ( void ) {
uint8 appMode;
appState = IDLE;
appStarted = TRUE;
/* Config basicRF 配置“Basic RF” */
basicRfConfig.panId = PAN_ID;
basicRfConfig.ackRequest = FALSE;
/* Initialise board peripherals 初始化外围硬件 */
halBoardInit();
/* Initalise hal_rf 初始化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 */
halMcuWaitMs ( 350 );
/* Set channel 设置信道,规范要求信道只能为为11至25,这里选择信道11 */
basicRfConfig.channel = 0x0B;
#ifdef MODE_SEND /* 设置模块的模式,一个作为发射,另一个为接收,看是否“define MODE_SEND” */
appMode = MODE_TX;
#else
appMode = MODE_RX;
#endif
/* Transmitter application */
if ( appMode == MODE_TX ) {
/* No return from here 如果“define MODE_SEND”,则进入appTransmitter发射模式 */
appTransmitter();
} else if ( appMode == MODE_RX ) { /* Receiver application */
/* No return from here 如果没有“define MODE_SEND”,则进入appReceiver接收模式 */
appReceiver();
}
HAL_ASSERT ( FALSE ); /* Role is undefined. This code should not be reached */
}
大家看注释也应该知道main.c做了哪些事情:
- 一大堆的初始化(都是必须的)。
- 设置信道,发射和接收模块的信道必须一致。
- 选择为发射或者接收模式。
发射函数define MODE_SEND则进入appTransmitter:
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 设置输出功率 */
halRfSetTxPower ( 2 ); /* HAL_RF_TXPOWER_4_DBM */
/* Set burst size 设置进行一次测试所发送的数据包数量 */
burstSize = 1000;
/* Basic RF puts on receiver before transmission of packet, and turns off after packet is sent */
basicRfReceiveOff();
/* Config timer and IO 配置定时器和IO */
appConfigTimer ( 0xC8 );
/* Initalise packet payload 初始化数据包载荷 */
txPacket.seqNumber = 0;
for ( n = 0; n < sizeof ( txPacket.padding ); n++ ) {
txPacket.padding[n] = n;
}
while ( TRUE ) {
while ( appStarted ) {
if ( pktsSent < burstSize ) {
/* 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++; /* 数据包序列号自加1 */
pktsSent++;
appState = IDLE;
halLedToggle ( 1 ); /* 改变LED1的亮灭状态 */
halMcuWaitMs ( 500 );
} else {
appStarted = !appStarted;
}
pktsSent = 0; /* Reset statistics and sequence number 复位统计和序号 */
}
}
}
总结appTransmitter函数完成的任务:
- 初始化
Basic RF。 - 设置发射功率。
- 设定测试的数据包量。
- 配置定时器和
IO。 - 初始化数据包载荷。
- 进行循环函数,不断地发送数据包,每发送完一次,下一个数据包的序列号自加
1再发送。
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缓冲区统计 */
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();
basicRfConfig.myAddr = RX_ADDR;
if ( basicRfInit ( &basicRfConfig ) == FAILED ) { /* 初始化“Basic RF” */
HAL_ASSERT ( FALSE );
}
basicRfReceiveOn();
while ( TRUE ) {
while ( !basicRfPacketIsReady() ); /* 等待新的数据包 */
if ( basicRfReceive ( ( uint8 * ) &rxPacket, MAX_PAYLOAD_LENGTH, &rssi ) > 0 ) {
halLedSet ( 3 ); /* 对应的引脚为P1_4 */
UINT32_NTOH ( rxPacket.seqNumber ); /* 改变接收序号的字节顺序 */
segNumber = rxPacket.seqNumber
if ( resetStats ) { /* 若统计被复位,设置期望收到的数据包序号为已经收到的数据包序号 */
rxStats.expectedSeqNum = segNumber;
resetStats = FALSE;
}
rxStats.rssiSum -= perRssiBuf[perRssiBufCounter]; /* 从sum中减去旧的RSSI值 */
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++;
} else if ( rxStats.expectedSeqNum < segNumber ) { /* 大于期望收到的数据包的序号,则认为丢包 */
/* If there is a jump in the sequence numbering this means some packets inbetween has been lost. */
rxStats.lostPkts += segNumber – rxStats.expectedSeqNum;
rxStats.expectedSeqNum = segNumber + 1;
} else { /* 小于期望收到的数据包的序号 */
rxStats.expectedSeqNum = segNumber + 1;
rxStats.rcvdPkts = 0;
rxStats.lostPkts = 0;
}
rxStats.rcvdPkts++;
/*---------------以下为串口打印部分的函数---------------*/
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] = '