NRF24L01P简介
NRF24L01P射频芯片,比NRF24L01具有更高的可靠性,更多的功
率等级,以及更远的传输距离和更低的功率。此外还内置RFX2401功放芯片,
内建LNA,接收灵敏度 提高10dBm,工作在2.4GHz~2.5GHz的ISM频段。
电压:最小值=1.9V;典型值=3.0V;最大值=3.6V;
如果要接入5V,需要使用电阻进行分压,可通过U=RI进行计算。 工作温度:-40℃——85℃。典型值=27℃
模块硬件
模块一共有8个引脚:
- +3.3v
- CE:数字信号输入,模式控制线。在 CSN为低的情况下,CE 协同CONFIG 寄存器共同决定NRF24L01 的状态
- CSN:数字信号输入 ,SPI片选线,低电平使能
- SCK:数字信号输入 ,SPI时钟线
- MOSI:数字信号输入,SPI数据线,主机输出,从机输入
- MISO:数字信号输出,SPI数据线,主机输入,从机输出
- IRQ:数字信号输出,中断信号线,在达到最大重发次数,数据发送完成和收到数据时变低
- GND
连线如下:
代码格式
关于NRF24L01的函数,有一下几个函数:
void NRF24L01_Init(void); //初始化
void NRF24L01_RX_Mode_init(void); //接受模式
void NRF24L01_TX_Mode(void); //发送模式
u8 NRF24L01_Write_Buf(u8 reg, u8 *pBuf, u8 u8s);//写数据区
u8 NRF24L01_Read_Buf(u8 reg, u8 *pBuf, u8 u8s); //读数据区
u8 NRF24L01_Read_Reg(u8 reg); //读寄存器
u8 NRF24L01_Write_Reg(u8 reg, u8 value); //写寄存器
u8 NRF24L01_Check(void); //检测24l01是否存在
u8 NRF24L01_TxPacket(u8 *txbuf); //发送数据包
u8 NRF24L01_RxPacket_init(u8 *RxData_Buf0,u8 *RxData_Buf1,u8 *RxData_Buf2,u8 *RxData_Buf3); //接受数据包,这个函数可以接受四个数据通道的数据
多通道(多发一收)
多通道是在单通道的基础上进行代码的修改,所以首先要对单通道的通信进行了解
单通道通信
单通道通信的代码流程大概如下:
GPIO口初始化
SPI初始化
NRF24L01P初始化
NRF24L01P检查
NRF24L01P配置为 接收/发送
使用 接收/发送数据包接收数据
部分代码如下:
1.初始化 NRF24L01
void NRF24L01_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOA, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_SetBits(GPIOB,GPIO_Pin_12);//ÉÏÀ
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_1;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_SetBits(GPIOA,GPIO_Pin_1|GPIO_Pin_0);
SPI2_Init();
SPI_Cmd(SPI2, DISABLE);
SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode = SPI_Mode_Master;
SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;
SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;
SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;
SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;
SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_16;
SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;
SPI_InitStructure.SPI_CRCPolynomial = 7;
SPI_Init(SPI2, &SPI_InitStructure);
SPI_Cmd(SPI2, ENABLE);
NRF24L01_CE=0;
NRF24L01_CSN=1;
}
2.NRF24L01检查函数
u8 NRF24L01_Check(void)
{
u8 buf[5]={0XA5,0XA5,0XA5,0XA5,0XA5};
u8 i;
SPI2_SetSpeed(SPI_BaudRatePrescaler_16);
NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,buf,5);
NRF24L01_Read_Buf(TX_ADDR,buf,5);
for(i=0;i<5;i++)if(buf[i]!=0XA5)break;
if(i!=5)return 1;
return 0;
}
3.发送模式
void NRF24L01_TX_Mode(void)
{
NRF24L01_CE=0;
NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(u8*)TxAddr0,TX_ADR_WIDTH);
NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RxAddr0,RX_ADR_WIDTH);
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01);
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01);
NRF24L01_Write_Reg(NRF_WRITE_REG+SETUP_RETR,0x1a);
NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40);
NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);
NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0e);
NRF24L01_CE=1;
}
4.接收模式
void NRF24L01_RX_Mode(void)
{
NRF24L01_CE=0;
NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RxAddr0,RX_ADR_WIDTH);
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01);
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01);
NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40);
NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P0,TX_PLOAD_WIDTH);
NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);
NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG, 0x0f);
NRF24L01_CE = 1;
}
这里简单介绍了一下这几个函数,还有很多函数由于篇幅原因没有列出,下面来说一下代码要怎么改才能完成多发一收
多发一收
多发一收,最主要的是要改三个部分:
1.主机的接收模式函数
2.主机的接收数据包函数
3.从机的发送模式函数
主机的接收模式函数
这个函数首先要改接收的地址,如果是四个通道就要改四个通道的地址。其次要将自动应答和接收地址的0x01改为0x0f。最后再改通道的有效数据宽度。代码如下:
void NRF24L01_RX_Mode_init()
{
NRF24L01_CE=0;
NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RxAddr0,RX_ADR_WIDTH);//写RX节点地址
NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P1,(u8*)RxAddr1,RX_ADR_WIDTH);//写RX节点地址
NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P2,(u8*)RxAddr2,1);//写RX节点地址
NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P3,(u8*)RxAddr3,1);//写RX节点地址
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x0f); //使能通道0的自动应答
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x0f);//使能通道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);//选择通道1的有效数据宽度
NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P2,RX_PLOAD_WIDTH);//选择通道2的有效数据宽度
NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P3,RX_PLOAD_WIDTH);//选择通道3的有效数据宽度
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_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RxAddr0,RX_ADR_WIDTH);//写RX节点地址
NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P1,(u8*)RxAddr1,RX_ADR_WIDTH);//写RX节点地址
NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P2,(u8*)RxAddr2,1);//写RX节点地址
NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P3,(u8*)RxAddr3,1);//写RX节点地址
这里的RxAddr0,RxAddr1,RxAddr2,RxAddr3,是自己设的地址,但是还要注意一个问题是2,3,4通道与1通道的关系。
这个通道我就不详细描述,给出我用的地址:
const u8 TxAddr0[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01};
const u8 TxAddr1[TX_ADR_WIDTH]= {0xC2,0xC2,0xC2,0xC2,0xC2};
const u8 TxAddr2[TX_ADR_WIDTH] = {0xC3,0xC2,0xC2,0xC2,0xC2};
const u8 TxAddr3[TX_ADR_WIDTH]= {0xC4,0xC2,0xC2,0xC2,0xC2};
const u8 TxAddr4[TX_ADR_WIDTH] = {0xC5,0xC2,0xC2,0xC2,0xC2};
const u8 TxAddr5[TX_ADR_WIDTH]= {0xC6,0xC2,0xC2,0xC2,0xC2};
const u8 RxAddr0[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01};
const u8 RxAddr1[RX_ADR_WIDTH]= {0xC2,0xC2,0xC2,0xC2,0xC2};
const u8 RxAddr2[1] ={0xC3};
const u8 RxAddr3[1] ={0xC4};
const u8 RxAddr4[1] ={0xC5};
const u8 RxAddr5[1] ={0xC6};
关于第二个改的地方:
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x0f); //使能通道0的自动应答
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x0f);//使能通道0的接收地址
这里改成0x0f即可,具体原因参考以下博客
链接: NRF24l01的多对一通信
第三个改的地方
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);//选择通道1的有效数据宽度
NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P2,RX_PLOAD_WIDTH);//选择通道2的有效数据宽度
NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P3,RX_PLOAD_WIDTH);//选择通道3的有效数据宽度
主机的接收数据包函数
这里主要改的地方是对接收到通道号的判别
u8 NRF24L01_RxPacket_init(u8 *RxData_Buf0,u8 *RxData_Buf1,u8 *RxData_Buf2,u8 *RxData_Buf3)
{
u8 sta;
u8 RX_P_NO;
SPI2_SetSpeed(SPI_BaudRatePrescaler_8); //spi速度为9Mhz(24L01的最大SPI时钟为10Mhz)
sta=NRF24L01_Read_Reg(STATUS); //读取状态寄存器的值
RX_P_NO=sta&0x0e;
NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中断标志
if(sta&RX_OK)//接收到数据
{
switch(RX_P_NO)
{
case 0x00: {NRF24L01_Read_Buf(RD_RX_PLOAD,RxData_Buf0,RX_PLOAD_WIDTH);break;}//读取数据
case 0x02: {NRF24L01_Read_Buf(RD_RX_PLOAD,RxData_Buf1,RX_PLOAD_WIDTH);break;}
case 0x04: {NRF24L01_Read_Buf(RD_RX_PLOAD,RxData_Buf2,RX_PLOAD_WIDTH);break;}
case 0x06: {NRF24L01_Read_Buf(RD_RX_PLOAD,RxData_Buf3,RX_PLOAD_WIDTH);break;}
default : break;
}
NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,0xff);
NRF24L01_CSN=0;
NRF24L01_Write_Reg(FLUSH_RX,0xff);//清除RX FIFO寄存器
NRF24L01_CSN=1;
return 0;
}
return 1;
}
主要目的是得到接收的数据时判断是哪个通道的数据,之后传入数组。
从机的发送模式函数
void NRF24L01_TX_Mode(void)
{
NRF24L01_CE=0;
NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(u8*)TxAddr3,TX_ADR_WIDTH);//**********************************
NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RxAddr3,TX_ADR_WIDTH);//**********************************
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x0f);
NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x0f);
NRF24L01_Write_Reg(NRF_WRITE_REG+SETUP_RETR,0x1a);
NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40);
NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);
NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0e);
NRF24L01_CE=1;
}
这里主要改的地方只有一处
NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(u8*)TxAddr3,TX_ADR_WIDTH);//**********************************
NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RxAddr3,TX_ADR_WIDTH);//**********************************
这里只需要将TxAddr3改成所需要的通道即可,如TxAddr0,TxAddr1,TxAddr2。
总结
到此为止就对多发一收进行配置完成了,具体原理部分由于篇幅受限没有讲解,因为网上大部分都是原理讲解部分,而对代码部分的讲解较少,所以写了这篇,放出通信结果图:文章来源:https://www.toymoban.com/news/detail-459921.html
四个通道,每个通道的前三位分别是111,222,333,444。后续根据项目的需求进行改动。
如果对NRF24L01P的原理和寄存器等知识可以参考其他人的博客,希望这篇博客可以让大家快速上手多路通信的代码。
自己写的工程如下,希望给大家参考:
链接: NRF24L01四发一收基于STM32F103C8T6完成文章来源地址https://www.toymoban.com/news/detail-459921.html
到了这里,关于STM32F103C8T6实验代码之NRF24L01P 多发一收的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!