在使用nRF24L01模块作一对多或多对一的组网通讯中,你们都会担忧一个问题就是在发送的时候,但愿不要有其余的模块也进行发送,由于这样就会使无线信号发生碰撞,信道被堵塞,形成通讯失败。函数
为了不这种状况发生,就但愿在发送前能知道当前信道是否处于空闲,若是空闲就发送,不然就等待一会,直到空闲下来再执行发送。利用这个机制,能够很大程度上规避碰撞的发生。code
在nRF24L01+中有个RSSI寄存器,地址是0x09,该寄存器的0号位是表明当前信道信号强度的。当接收信号强度小于-60dBm时0号位为0,大于-60dBm时为1,该寄存器7-1号位是保留位,固定为0。这样咱们经过直接读取该寄存器的值是0仍是大于0就知道信道是否被占用了。循环
下面是该寄存器在一些模块厂家官方例程里的定义:方法
#define RPD 0x09 //接收功率检测寄存器
或通信
#define RSSI 0x09 //接收功率检测寄存器
下面是经过读寄存器函数读取该寄存器的状态值的代码:数据
StatusRPD = nRF24L01P_Read_Reg(RPD); //若是定义的是RSSI,那语句中RPD换成RSSI
经过上面语句获得的StatusRPD值,若是大于0则是信道被占用,在逻辑代码中经过这个判断就能够识别信道是否被占用了。也能够在发送前用循环等待这个值的变化,直到为0时进入发送状态。以下面的代码:db
while(nRF24L01P_Read_Reg(RPD));
在实际应用中,使用上述方法的确能够获得当前的信道信号强度,达到判断信道是否占用的目的。可是在循环等待的时候,偶尔会出现死循环的现象。也就是读回来的状态值一直是1,可是的确没有模块在发送,已经将其余模块所有断电了,周围也没有强信号干扰,那么问题出在哪里呢?while
仔细查看芯片手册,只找到下面这段话:co
在接收模式下,能够经过RSSI寄存器检测接收信号功率。当接收到的信号强度大于-60dBm时,RSSI寄存器的RSSI位的值将被设置为1。不然,RSSI=0。。RSSI寄存器的更新方法有两种:当接收到有效的数据包后,RSSI会自动更新,此外,将芯片从RX模式换到Standby模式时RSSI也会自动更新。RSSI的值会随温度的变化而变化,范围在±5dBm之内block
通过仔细分析和反复试验,理解了这段话所描述的具体内涵:
一、这个信号强度检测必须在接收模式下进行,在发送模式下是不许确的。
二、并非不管什么状况下,这个寄存器都会被更新,只有CE由1变为0时才更新一次;或者在接收到有效数据的时候,会自动更为1。
三、当收到有效数据将该寄存器置1后,只有将接收FIFO寄存器的数据读出后,才会变为0,不然你变化几回CE都无效(这是手册没有提到的,多数会踩到这个坑)。
上面的死循环状况通常发生在执行发送的前夕,恰好收到一个有效数据时,RSSI寄存器被置1,而代码正在处理发送,又没有去读出数据,因此就一直保持着1,因此循环条件一直知足,就成了死循环了。
解决办法建议是在检测到为RSSI为1的时候,判断一下是否收到数据,若是收到数据先读出来,至于读出来的数据要不要处理,根据您本身的业务逻辑决定便可。而后操做一次CE引脚,再次更新检测一下是否有信号占用信道。此方法通过实际应用是有效的。