LoRa开发7:PingPong系统
1 引言
前2章介绍了SX1278的发送和接收,在此基础上,我们设计一个有趣的PingPong系统,更好地理解LoRa终端的收发逻辑。
该系统将LoRa终端自动定义成2种角色:master和slave。master主动发送ping数据帧,接收pong数据帧;slave如果接收到ping数据帧,回应pong数据帧。
2 整体逻辑流程
如上图所示,当LoRa终端上电后,在(2 * PingPongPeriod)周期内没有接收到ping数据帧,它就认为自己是master。Master节点每隔(1 * PingPongPeriod)周期主动发送ping数据帧,然后启动RF接收,可能接收到pong回应帧(正常通信),也可能接收超时(slave没有上电或通信失败)。
同理,当LoRa终端上电后,在(2 * PingPongPeriod)周期内接收到ping数据帧,它就认为自己是slave。Slave节点启动RF接收,如果接收到ping数据帧,它将发送pong回应帧。
一个节点从上电,判断自身角色,根据角色处理逻辑,如下流程图所示。
3 代码剖析
PROCESS_THREAD(PingPong, ev, data)
{
#definePING “ping, this is MASTER ofrime node.”
#definePONG “pong, this is SLAVE of rimenode.”
#definePING_SIZE 34
#definePONG_SIZE 33
staticbool s_bIsMaster;
staticuint16_t s_wPingPongPeriod;
staticint32_t s_lTxCnt = 0;
staticint32_t s_lRxCnt = 0;
PROCESS_BEGIN();
InitSetLoRa();
s_wPingPongPeriod =
SX1278GetTimeOnAir(4) + SX1278GetTimeOnAir(4) + 15; 1
/*Determine MASTER or SLAVE by RX “ping”. */
SX1278Receive(2 * s_wPingPongPeriod); 2
PROCESS_YIELD(); /* Yield until receive or timeout. */ 3
SX1278SetSleep(); /* MUST stop RxContinuous mode manually. */ 4
if(GetCompareRxFrame(PING, PING_SIZE)) 5
{
s_bIsMaster = FALSE;
}
else
{
s_bIsMaster = TRUE;
}
if(s_bIsMaster) /* Is MASTER */
{
while (1)
{
/* TX “ping” */
++s_lTxCnt;
SX1278Send(PING, PING_SIZE); 6
PROCESS_YIELD_UNTIL( (RF_Tx_Done == s_tRFResult) ||
(RF_Tx_Timeout ==s_tRFResult) ); 7
/* RX “pong” */
SX1278Receive(s_wPingPongPeriod); 8
PROCESS_YIELD(); /* Yield until receive a frame or timeout. */
SX1278SetSleep(); /* MUST stop RxContinuous mode manually. */
if (GetCompareRxFrame(PONG, PONG_SIZE)) 9
{
++s_lRxCnt;
RIME_DBG( RIME_DBG_ON,
“TxCnt=%ld, Rx Cnt=%ld, SNR=%d, RSSI=%d.\r\n”,
s_lTxCnt, s_lRxCnt, s_chPacketSnr,s_nPacketRssi ); 10
}
}
}
else /* Is SLAVE */
{
while (1)
{
/* RX “ping” */
SX1278Receive(0); 11
PROCESS_YIELD(); /* Yield until receive a frame or rx error. */
SX1278SetSleep(); /* MUST stop RxContinuous mode manually. */
if (GetCompareRxFrame(PING, PING_SIZE)) 12
{
/* TX “pong” */
++s_lTxCnt;
SX1278Send(PONG, PONG_SIZE); 13
PROCESS_YIELD_UNTIL( (RF_Tx_Done ==s_tRFResult) ||
(RF_Tx_Timeout == s_tRFResult) ); 14
++s_lRxCnt;
RIME_DBG( RIME_DBG_ON,
“Tx Cnt=%ld, RxCnt=%ld, SNR=%d, RSSI=%d.\r\n”,
s_lTxCnt, s_lRxCnt,s_chPacketSnr, s_nPacketRssi );
}
}
}
PROCESS_END();
}
Line#1:计算PingPong通信空中时间,添加15ms做为收发准备时间;
Line#2:启动接收功能,超时时长为2倍PingPong通信空中时间;
Line#3:阻塞进程,直到接收数据帧或超时;
Line#4:设置SX1278为休眠,否则它将处于持续接收状态(那怕超时亦如此);
Line#5:GetCompareRxFrame()复制数据帧到解析工作区,比较是否为ping帧;
Master节点逻辑
Line#6:master节点发送ping数据帧;
Line#7:阻塞进程,直到发送ping数据帧完毕;
Line#8:启动接收功能,超时时长为PingPong通信空中时间;
Line#9:比较是否为pong回应帧;
Line#10:打印发送和接收数据帧个数,SNR和RSSI值;
Slave节点逻辑
Line#11:启动持续接收功能,为0表明关闭超时功能;
Line#12:比较是否为ping数据帧;
Line#13:slave节点发送pong回应帧;
Line#14:阻塞进程,直到发送pong回应帧完毕;
您的留言或需求: