在博客里面潜水了多年,只是在学习别人的博客,有时虽然博客写的不是完整,只能通过好几个博客同时看才能解决问题,但是自己收获颇多,感谢各位的奉献。言归正传,这几天在调NRF24l01的一对多通信,在网上找到的都是一对二的,或者写的比较模糊不清,这对像我这样的新手很不友好,遂,决定写一篇博客记录一下自己的调试过程,在文末附上代码。
目录
NRF24l01通信原理
一对一的配置说明
一对一的代码
一对多的配置说明(1对六、六发一收)
一对多的代码、
一对一的原理:
首先在接收端(0通道)配置接收地址、0通道的自动应答功能、使能接收地址,设置通信频率、设置通道0的数据宽度、设置发射参数、设置成为接收模式。
在发送端设置发送地址、接收地址(为了自动应答功能)、0通道的自动应答功能、使能接收地址,设置通信频率、设置通道0的数据宽度、设置发射参数、设置成为发送模式。
然后发送端发送一帧数据(这帧数据带有发送地址)、因为开启了自动应答功能,发送完毕后发送端会立即进入接收模式。此时接收端如果接到数据以后会首先会将发送端的地址和接收端的地址进行对比,如果一致(所以接收端的接收地址和发送端的发送地址要一致)则认为是正确的数据,将会接收。接收端会立即发送出自己的接收地址,这时发送端如果接收到了以后会和自己配置的接收地址比较是否一致,如果一致,则认为此次发送成功。
多对一的原理:
通信逻辑和一对一通信的原理相同。多对一通信的实现可以通过NRF24l01的地址不同或者发射频率不同实现组网设计。如果使用频率不同(优点为实现简单,缺点是在接收端要不断的进行频率切换才能轮询的接收各个发送端的数据)进行多对一通信的话,那就配置成一对一通信模式,然后发送端的发射频率设置不同,则可实现多对一通信(下文会有详细说明),另一个办法就是使用相同频率,使用不同的通道和地址(优点是使用相同频率,不用切换频率,自动识别来自哪个发送端的数据。缺点是配置较多)实现多对一的通信,NRF24l01最多为六通道通信,六通道配置不同的地址,这样就能实现六对一的通信了(下文有详细说明)。
NRF24L01_CE=0;
NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS0,RX_ADR_WIDTH);//写RX节点地址
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01); //使能通道0的自动应答
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01);//使能通道0的接收地址
NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40); //设置RF通信频率 发射频率=2.4G + 40 = 2.44G
NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//选择通道0的有效数据宽度
NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);//设置TX发射参数,0db增益,2Mbps,低噪声增益开启
NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG, 0x0f);//配置基本工作模式数;PWR_UP,EN_CRC,16BIT_CRC,接收模式
NRF24L01_CE = 1; //CE为高,进入接收模式
1中配置接收端的通道0的接收地址,RX_ADR_WIDTH为地址宽度,在本文里是5.
2中为使能通道0的自动应答和使能通道0的接收地址。这里需要说明一下0x01是怎么来的。
使能通道自动应答功能和接收地址是通过位来使能的,1为使能,0为失能。一共六个通道。如下图所示。
通道5 | 通道4 | 通道3 | 通道2 | 通道1 | 通道0 | 值 | 功能 |
0 | 0 | 0 | 0 | 0 | 1 | 0x01 | 使能通道0 |
0 | 0 | 0 | 0 | 1 | 0 | 0x02 | 使能通道1 |
0 | 0 | 0 | 0 | 1 | 1 | 0x03 | 使能通道0和1 |
. | . | . | . | . | . | . | 省略 |
1 | 1 | 1 | 1 | 1 | 1 | 0x3f | 使能所有通道 |
3为设置发射频率,计算方法为 发射频率 = 2.4GHz+40MHz = 2.4390625GHz
4为设置通道0的数据宽度(本文为32字节)
5为设置发射速率为2M,低噪声增益开启
6为设置为接收模式
NRF24L01_CE=0;
NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS0,TX_ADR_WIDTH);//写TX节点地址
NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS0,RX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACK
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01); //使能通道0的自动应答
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址
NRF24L01_Write_Reg(NRF_WRITE_REG+SETUP_RETR,0x1a);//设置自动重发间隔时间:500us + 86us;最大自动重发次数:10次
NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40); //设置RF通道为40
NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f); //设置TX发射参数,0db增益,2Mbps,低噪声增益开启
NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0e); //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,发射模式,开启所有中断
NRF24L01_CE=1;//CE为高,10us后启动发送
主要是红框位置与接收端不同,这里主要是为了自动应答功能,作用上文已有说明。
const u8 RX_ADDRESS0[] = {0xff,0xff,0xff,0xff,0x00};//
const u8 RX_ADDRESS1[] = {0xfe,0xaa,0xaa,0xaa,0x01};//
const u8 RX_ADDRESS2[] = {0x02};//??2??
const u8 RX_ADDRESS3[] = {0x03};//??3??
const u8 RX_ADDRESS4[] = {0x04};//??4??
const u8 RX_ADDRESS5[] = {0x05};//??5??
const u8 TX_ADDRESS0[] = {0xff,0xff,0xff,0xff,0x00};//
const u8 TX_ADDRESS1[] = {0xfe,0xaa,0xaa,0xaa,0x01};//
const u8 TX_ADDRESS2[] = {0x02};//
const u8 TX_ADDRESS3[] = {0x03};//
const u8 TX_ADDRESS4[] = {0x04};//
const u8 TX_ADDRESS5[] = {0x05};//
这里要注意,通道0的地址和通道1的地址高字节和低字节都要不同,具体原因我也不知道,我最开始设置的只有高字节不同,结果就不稳定,不是每次上电都能正常传数据的。
NRF24L01_CE=0;
NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS0,RX_ADR_WIDTH);//写RX节点地址
NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P1,(u8*)RX_ADDRESS1,RX_ADR_WIDTH);//写RX节点地址
NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P1,(u8*)RX_ADDRESS1,1);
NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P2,(u8*)RX_ADDRESS2,1);//写RX节点地址
NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P3,(u8*)RX_ADDRESS3,1);//写RX节点地址
NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P4,(u8*)RX_ADDRESS4,1);//写RX节点地址
NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P5,(u8*)RX_ADDRESS5,1);//写RX节点地址
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x3f); //使能通道0的自动应答
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x3f);//使能通道0的接收地址
NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40); //设置RF通信频率
NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//选择通道0的有效数据宽度
NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P1,RX_PLOAD_WIDTH);
NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P2,RX_PLOAD_WIDTH);
NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P3,RX_PLOAD_WIDTH);
NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P4,RX_PLOAD_WIDTH);
NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P5,RX_PLOAD_WIDTH);
NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);//设置TX发射参数,0db增益,2Mbps,低噪声增益开启
NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG, 0x0f);//配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式
NRF24L01_CE = 1; //CE为高,进入接收模式
NRF24L01_CE=0;
NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS0,TX_ADR_WIDTH);//写TX节点地址
NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS0,RX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACK
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x3f); //使能通道0的自动应答
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x3f); //使能通道0的接收地址
NRF24L01_Write_Reg(NRF_WRITE_REG+SETUP_RETR,0x1a);//设置自动重发间隔时间:500us + 86us;最大自动重发次数:10次
NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40); //设置RF通道为40
NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f); //设置TX发射参数,0db增益,2Mbps,低噪声增益开启
NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0e); //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式,开启所有中断
NRF24L01_CE=1;//CE为高,10us后启动发送
NRF24L01_CE=0;
NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS1,TX_ADR_WIDTH);//写TX节点地址
NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS1,RX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACK
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x3f); //使能通道0的自动应答
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x3f); //使能通道0的接收地址
NRF24L01_Write_Reg(NRF_WRITE_REG+SETUP_RETR,0x1a);//设置自动重发间隔时间:500us + 86us;最大自动重发次数:10次
NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40); //设置RF通道为40
NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f); //设置TX发射参数,0db增益,2Mbps,低噪声增益开启
NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0e); //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式,开启所有中断
NRF24L01_CE=1;//CE为高,10us后启动发送
NRF24L01_CE=0;
NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS2,TX_ADR_WIDTH);//写TX节点地址
NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS2,RX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACK
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x3f); //使能通道0的自动应答
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x3f); //使能通道0的接收地址
NRF24L01_Write_Reg(NRF_WRITE_REG+SETUP_RETR,0x1a);//设置自动重发间隔时间:500us + 86us;最大自动重发次数:10次
NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40); //设置RF通道为40
NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f); //设置TX发射参数,0db增益,2Mbps,低噪声增益开启
NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0e); //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式,开启所有中断
NRF24L01_CE=1;//CE为高,10us后启动发送
u8 NRF24L01_RxPacket(u8 *rxbuf)
{
u8 sta;
SPI2_SetSpeed(SPI_BaudRatePrescaler_8); //spi速度为9Mhz(24L01的最大SPI时钟为10Mhz)
sta=NRF24L01_Read_Reg(STATUS); //读取状态寄存器的值
NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中断标志
if(sta&RX_OK)//接收到数据
{
switch((sta >> 1) & 0x07)
{
case 0x00:NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf_1,RX_PLOAD_WIDTH);//读取数据
break;
case 0x01: NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf_2,RX_PLOAD_WIDTH);
break;
case 0x02: NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf_3,RX_PLOAD_WIDTH);
break;
case 0x03:NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf_4,RX_PLOAD_WIDTH);//读取数据
break;
case 0x04: NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf_5,RX_PLOAD_WIDTH);
break;
case 0x05: NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf_6,RX_PLOAD_WIDTH);
break;
default: ;
break;
}
NRF24L01_Write_Reg(FLUSH_RX,0xff);//清除RX FIFO寄存器
return 0;
}
return 1;//没收到任何数据
}
至此NRF24l01配置已经说明完毕,如果还不通请留言。