1st's Studio.

NRF24L01详解

字数统计: 1.8k阅读时长: 7 min
2022/03/07

1.NRF24L01概述

  NRF24L01是一款在2.4~2.5GHz世界通用ISM(Industrial Scientific Medical)频段的单片无线收发器芯片。无限收发器包括:频率发生器、增强型SchockBurst \(^{TM}\)模式控制器、功率放大器、晶体震荡器、调制器、解调器。

输出功率、频道选择和协议的设置可以通过SPI接口进行设置

NRF24L01拥有极低的电流消耗——当工作在发射模式下发射功率为-6dBm时电流消耗为9mA,接收模式时为12.3mA。掉电模式和待机模式下电流消耗更低。

1.1 NRF24L01参考数据

1.2 NRF24L01基本工作原理

处理器先将待传输数据解析为01的二进制数据,然后在传输数据时候,芯片将01以电磁波的形式发送出去(例如一个大正弦波表示1,两个小正弦波表示0)

芯片接收到电磁波时,再按照一定的速率进行解波,最后得到数据

由此可见,发送方和接受方的速率以及功率都需一致

GFSK(Gauss Frequency Shift Keying) FSK调制方式

  当原始数字信号在经过FSK调变送出前,加上一个高斯低通滤波器来限制调变后的信号频谱宽度,使得在通讯上能限制频谱宽度的传输以及功率的消耗。

  GFSK高斯频移键控调制是把输入数据经高斯低通滤波器预调制滤波后,再进行FSK调制的数字调制方式。它在保持恒定幅度的同时,能够通过改变高斯低通滤波器的3dB带宽对已调信号的频谱进行控制,具有恒幅包络、功率谱集中、频谱较窄等无线通信系统所希望的特性。

1.3 NRF24L01工作模式

  NRF24L01可以设置为以下几种主要的模式,

1.4 NRF24L01 不同模式下引脚功能

待机模式:

  待机模式 I 在保证快速启动的同时减少系统平均消耗电流。在待机模式 I 下,晶振正常工作。在待机模式 II 下部分时钟缓冲器处在工作模式。当发送端 TX FIFO 寄存器为空并且 CE 为高电平时进入待机模式II。在待机模式期间,寄存器配置字内容保持不变。

掉电模式:

  在掉电模式下,nRF24L01 各功能关闭,保持电流消耗最小。进入掉电模式后, nRF24L01 停止工作,但寄存器内容保持不变。启动时间见表格。掉电模式由寄存器中 PWR_UP 位来控制。

2.元器件

2.1 元器键引脚

NRF24L01芯片有8个引脚,分别为6个功能引脚和两个电源引脚,将其对应与STM32芯片相连接即可。

3.代码(以STM32为例)

3.0 预备说明

NRF24L01操作线

1
2
3
#define NRF24L01_CE PGout(8)    // 24L01片选信号
#define NRF24L01_CSN PGout(7) // SPI片选信号
#define NRF24L01_IRQ PGout(6) // IRQ主机数据输入

3.1 设置收发地址

1
2
const u8 TX_ADDRESS[TX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01};  //发送地址
const u8 RX_ADDRESS[RX_ADR_WIDTH]={0X34,0X43,0X10,0X10,0X01}; //接受地址

3.2 NRF24L01初始化

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
void NRF24L01_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
SPI_InitTypeDef SPI_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOG,ENABLE); // 使能PB、PG时钟

GPIO_InitStructure.GPIO_Pin=GPIO_Pin_7|GPIO_Pin_8;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_Out_PP; // 推挽输出
GPIO_InitStructure.GPIO_Speed=GPIO_Speed_50MHz;
GPIO_Init(GPIOG,&GPIO_InitStructure); // 初始化指定IO口
GPIO_InitStructure.GPIO_Pin=GPIO_Pin_6;
GPIO_InitStructure.GPIO_Mode=GPIO_Mode_IPD; // PG6 输入
GPIO_Init(GPIOG,&GPIO_InitStructure);
GPIO_ResetBits(GPIOG,GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8); // PG6 7 8上拉

SPI2_Init(); // 初始化SPI
SPI_Cmd(SPI2,DISABLE); // SPI外设不使能
SPI_InitStructure.SPI_Direction=SPI_Direction_2Lines_FullDuplex;
SPI_InitStructure.SPI_Mode=SPI_Mode_Master; // 设置SPI工作模式——设置为master(主机)
SPI_InitStructure.SPI_DataSize=SPI_DataSize_8b; // 8位帧结构
SPI_InitStructure.SPI_CPOL=SPI_CPOL_Low; // 时钟悬空低
SPI_InitStructure.SPI_CPHA=SPI_CPHA_1Edge; // 数据捕获于第一个时钟沿
SPI_InitStructure.SPI_NSS=SPI_NSS_Soft; //NSS信号由软件控制
SPI_InitStructure.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_16; // 定义波特率预分频值为16
SPI_InitStructure.SPI_FirstBit=SPI_FirstBit_MSB; // MSB 位开始
SPI_InitStructure.SPI_CRCPolynomial=7; //CRC值计算的多项式
SPI_Init(SPI2,&SPI_InitStructure); // 初始化SPIx
SPI_Cmd(SPI2,ENABLE); // 使能SPI外设
NRF24L01_CE=0; // 使能24L01
NRF24L01_CSN=1; // SPI片选取消

}

3.3 写入值

在地址为reg的寄存器写入value

1
2
3
4
5
6
7
8
9
u8 NRF24L01_Write_Reg(u8 reg,u8 value)    // reg为寄存器地址,value为写入的值
{
u8 status;
NRF24L01_CSN=0; // 使能SPI传输
status=SPI2_ReadWriteByte(reg); // 发送寄存器号
SPI2_ReadWriteByte(value); // 写入寄存器值
NRF24L01_CSN=1; // 禁止SPI传输
return status
}

在跌至为reg的寄存器写入指定len长度的数据,pBuf为数据包

1
2
3
4
5
6
7
8
9
u8 NRF24L01_Write_Buf(u8 reg,u8 *pBuf,u8 len)
{
u8 status,u8_ctr;
NRF24L01_CSN=0;
status=SPI2_ReadWriteByte(reg);
for(u8_ctr=0;u8_ctr<len;u8_ctr++)SPI2_ReadWriteByte(*pBuf++);
NRF24L01_CSN=1;
return status;
}

3.4 读取值

对地址为reg的寄存器读取value

1
2
3
4
5
6
7
8
9
u8 NRF24L01_Read_Reg(u8 reg)
{
u8 reg_val;
NRF24L01_CSN=0;
SPI2_ReadWriteByte(reg);
reg_val=SPI2_ReadWriteByte(0xFF);
NRF24L01_CSN=1;
return(reg_val);
}

对地址为reg的寄存器读取指定长度len的value,pBuf为接受数据包

1
2
3
4
5
6
7
8
9
u8 NRF24L01_Read_Buf(u8 reg,u8 *pBuf,u8 len)
{
u8 reg_val;
NRF24L01_CSN=0;
status=SPI2_ReadWriteByte(reg);
for(u8_ctr=0;u8_ctr<len;u8_ctr++)pBuf[u8_ctr]=SPI2_ReadWriteByte(0xFF);
NRF24L01_CSN=1;
return status;
}

3.5 检测是否存在NRF24L01芯片

1
2
3
4
5
6
7
8
9
10
11
u8 NERF24l01_Check(void)
{
u8 buf[5]={0xA5,0xA5,0xA5,0xA5,0xA5};
u8 i;
SPI2_SetSpeed(SPI_BaudRatePrescaler_4); // spi 速度为9Mhz
NRF24L01_Write_Buf(WRITE_REG_NRF+TX_ADDR,buf,5); //写入5个字节的地址
NRF24L01_Read_Buf(TX_ADDR,buf,5); // 读出写入的地址
for(i=0;i<5;i++) if(buf[i]!=0xA5) break;
if(i!=5) return 1; // 检测到NRF24L01错误
return 0;
}

3.6 发送一次数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
u8 NRF24L01_TxPacket(u8 *txbuf)
{
u8 sta;
SPI2_SetSpeed(SPI_BaudRatePrescaler_8); //spi 速度为9Mhz
NRF24L01_CE=0;
NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH); // 写数据到TX BUF
NRF24L01_CE=1;
while(NRF24L01_IRQ!=0); // 等待发送完成
sta=NRF24L01_Read_Reg(STATUS); // 状态寄存器的值
NRF24L01_Write_Reg(WRITE_REG_NRF+STATUS,sta); // 清除TX_DS
if(sta&MAX_TX) // 达到最大重发次数
{
NRF24L01_Write_Reg(FLUSH_TX,0xFF); // 清除TX FIFO 寄存器
return MAX_TX;
}
if(sta&Tx_OK) // 发送完成
{
return TX_OK;
}
return 0xff; // 由于其他原因发送失败
}

3.7 接收一次数据

1
2
3
4
5
6
7
8
9
10
11
12
13
14
u8 NRF24L01_RxPacket(u8 *txbuf)
{
u8 sta;
SPI2_SetSpeed(SPI_BaudRatePrescaler_8); //9Mhz
sta=NRF24L01_Read_Reg(STATUS); // 读取状态寄存器的值
NRF24L01_Write_Reg(WRITE_REG_NRF+STATUS,sta);
if(sta&RX_OK) // 接收到数据
{
NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH); // 读取数据
NRF24L01_Write_Buf(FLUSH_RX,0xFF); // 清空RX FIFO寄存器
return 0;
}
return 1; // 没收到任何数据
}

3.8 切换到发送模式

1
2
3
4
5
6
7
8
9
10
11
12
13
void NRF24L01_TX_Mode(void)
{
NRF24L01_CE=0;
NRF24L01_Write_Buf(WRITE_REG_NRF+TX_ADDR,(u8*)TX_ADDRESS,TX_ADR_WIDTH);
NRF24L01_Write_Buf(WRITE_REG_NRF+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH);
NRF24L01_Write_Reg(WRITE_REG_NRF+EN_AA,0x01); // 使能通道0的自动应答
NRF24L01_Write_Reg(WRITE_REG_NRF+EN_RXADDR,0x01); // 使能通道0的接收地址
NRF24L01_Write_Reg(WRITE_REG_NRF+SETUP_RETR,0x1A); // 设置自动重发间隔时间
NRF24L01_Write_Reg(WRITE_REG_NRF+RF_CH,40); // 设置RF通道为40
NRF24L01_Write_Reg(WRITE_REG_NRF+RF_SETUP,0x0F); // 设置 TX 发射参数
NRF24L01_Write_Reg(WRITE_REG_NRF+CONFIG,0x0e); // 配置基本工作模式的参数
NRF24L01_CE=1; //CE为高,10us后自动发送
}

3.9 切换到接收模式

1
2
3
4
5
6
7
8
9
10
11
12
void NRF24L01_RX_Mode(void)
{
NRF24L01_CE=0;
NRF24L01_Write_Buf(WRITE_REG_NRF+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH);
NRF24L01_Write_Reg(WRITE_REG_NRF+EN_AA,0x01); // 使能通道0的自动应答
NRF24L01_Write_Reg(WRITE_REG_NRF+EN_RXADDR,0x01);
NRF24L01_Write_Reg(WRITE_REG_NRF+RF_CH,40); // 设置RF通信频率
NRF24L01_Write_Reg(WRITE_REG_NRF+RX_PW_P0,RX_PLOAD_WIDTH); // 选择通道0 的有效数据宽度
NRF24L01_Write_Reg(WRITE_REG_NRF+RF_SETUP,0x0F); // 设置TX发射参数
NRF24L01_Write_Reg(WRITE_REG_NRF+CONFIG,0x0F); //配置基本工作模式参数接收模式
NRF24L01_CE=1; //CE为高,进入接收模式
}

[1] nrf24l01中文手册

[2] 2.4GHz无线收发模块nRF24L0基础原理速览及在Arduino上面的使用

[3] 正点原子参考手册

CATALOG
  1. 1. 1.NRF24L01概述
    1. 1.1. 1.1 NRF24L01参考数据
    2. 1.2. 1.2 NRF24L01基本工作原理
      1. 1.2.1. GFSK(Gauss Frequency Shift Keying) FSK调制方式
    3. 1.3. 1.3 NRF24L01工作模式
    4. 1.4. 1.4 NRF24L01 不同模式下引脚功能
      1. 1.4.1. 待机模式:
      2. 1.4.2. 掉电模式:
  2. 2. 2.元器件
    1. 2.1. 2.1 元器键引脚
  3. 3. 3.代码(以STM32为例)
    1. 3.1. 3.0 预备说明
    2. 3.2. 3.1 设置收发地址
    3. 3.3. 3.2 NRF24L01初始化
    4. 3.4. 3.3 写入值
    5. 3.5. 3.4 读取值
    6. 3.6. 3.5 检测是否存在NRF24L01芯片
    7. 3.7. 3.6 发送一次数据
    8. 3.8. 3.7 接收一次数据
    9. 3.9. 3.8 切换到发送模式
    10. 3.10. 3.9 切换到接收模式