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] 正点原子参考手册