NRF24L01
NRF24L01是工作在2.4~2.5GHz世界通用ISM频段的单片机无线收发芯片。
- NRF24L01的无线速率可设置1或2Mbps
- 使用SPI接口,接口速率支持0~8Mbps
- 同一频道下可接收6个通道数据,共有128个频道可以切换
- 芯片工作电压1.9~3.6V
[tr]管脚功能[/tr]
CSN | 芯片片选线,CSN为低电平芯片工作 |
SCK | 芯片控制的时钟线 |
MISO | 芯片控制数据线 |
MOSI | 芯片控制数据线 |
IRQ | 中断信号,通讯中MCU主要通过IRQ与24L01通信 |
CE | 芯片的模式控制线 |
增强型的ShockBurstTM模式
NRF24L01集成了所有高速链路层的自动应答、自动重发、数据包识别等操作,无需MCU介入。
在接收模式下,NRF24L01可同时接收6个不同通道的数据,每个通道使用不同的地址。芯片可通过STATUS寄存器的RX_P_NO来获取接收数据的通道号。接收时芯片还会通过PID(数据包识别)来判断是否与上一个数据相同,CRC检测数据的完整性,并进行自动应答。接收完毕芯片触发中断RX_DR,数据存储在RX_FIFO中。
在发送模式下,在将打包完的数据发送后,芯片将等待接收端的应答信号,若有则触发中断TX_DS并清除TX_FIFO;若无则自动重发,重发次数大于重发计数器ARC_CNT是,STATUS状态寄存器的MAX_RT置“1”,不清除TX_FIFO的数据。
数据长度,NRF24L01的发送数据长度最长32字节,其支持静态和动态1两种模式。在静态模式中,我们通过RX_PW_Px寄存器来接收数据长度,该模式下发送数据长度必须于设定值相同,若要更改数据长度需要操作相关寄存器。在动态模式中,我们需要先设置FEATURE和DYNPD寄存器来开启,在接收端可使用命令R_RX_PL_WID来获取数据长度。
NRF24L01的6个通道地址有一定的规则,其中只有数据通道0可配置40位地址。而数据通道1~5则是32位共用地址+各自地址。
需要注意:由于芯片要求,在向寄存器写入地址信息时是低字节先写;在配置数据通道2~5,由于仅最后一位可配置,因此定义仅需与设置最后一位即可。
const u8 TX_ADDRESS[TX_ADR_WIDTH]={0x77,0x35,0xF9,0xD3,0xE7}; //发送地址(本机)const u8 RX0_ADDRESS[RX_ADR_WIDTH]={0x77,0x35,0xF9,0xD3,0xE7}; //接收地址0
const u8 RX1_ADDRESS[RX_ADR_WIDTH]={0xC2,0xC2,0xC2,0xC2,0xC2}; //接收地址1
const u8 RX2_ADDRESS[RX_ADR_WIDTH]={0xC3}; //接收地址2
const u8 RX3_ADDRESS[RX_ADR_WIDTH]={0xC4}; //接收地址3
const u8 RX4_ADDRESS[RX_ADR_WIDTH]={0xC5}; //接收地址4
const u8 RX5_ADDRESS[RX_ADR_WIDTH]={0xC6}; //接收地址5
调试思路
SPI通信
NRF24L01使用SPI通信,驱动它的第一步就是通信部分的,将底层通讯部分的程序封装后,后续的寄存器操作等都是可以跨平台移植的。而SPI的通讯又可以分为模拟和硬件两种实现方式,模拟即通过软件操作GPIO来实现SPI通讯协议,这个方法由于时序是软件操作,对单片机工作频率有限定,更改工作频率可能回导致不可用。硬件即使用单片机内部的片上外设,这个相对更加稳定,但其管脚固定,且有些单片机并没有硬件的SPI外设。两种方法需要根据实际情况选择,这里展示STC15和STM32的硬件SPI下的使用方法
STC15
u8 SPIx_ReadWriteByte(u8 byte)
{
u8 d_read,d_send=byte;
SPDAT = d_send;//发送数据
while(!(SPSTAT&SPIF)) //等待数据发送完毕
;
SPSTAT = SPIF|WCOL; //清除状态位
d_read = SPDAT;
return d_read;
}
STM32
uint8_t SPIx_ReadWriteByte(SPI_HandleTypeDef* hspi,uint8_t byte)
{
uint8_t d_read,d_send=byte;
if(HAL_SPI_TransmitReceive(hspi,&d_send,&d_read,1,0xFF)!=HAL_OK)
{
d_read=0xFF;
}
return d_read;
}
动态长度
数据的动态长度必须对下图两个寄存器进行操作
NRF24L01_Write_Reg(NRF_WRITE_REG+DYNPD,0x3F); //开启6通道DPL
NRF24L01_Write_Reg(NRF_WRITE_REG+FEATURE,0x04|0x02);//开启DPL和ACK
在接受端想要获取数据长度便需要发送相关命令,而不是读取RX_PL_Px寄存器中的值
uint8_t NRF24L01_SendSring(uint8_t *txbuf,uint8_t length)
{
uint8_t sta,i;
uint8_t tx_buffer[32];//发送数据缓存
tx_buffer[0]=length-1;//发送数据的首位为数据长度,sizeof求得长度包括了‘ ’
for(i=0;i
{
tx_buffer[i+1] = txbuf
;//将待发送数据放到数据长度后,组成一个完整需要发送的数据
}
SPI1_SetSpeed(SPI_BAUDRATEPRESCALER_16); //spi速度为6.75Mhz(24L01的最大SPI时钟为10Mhz)
NRF24L01_CE_LOW();
NRF24L01_Write_Reg(FLUSH_TX,0xff);
NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,length);//写数据到TX BUF 32个字节
NRF24L01_CE_HIGH();//启动发送
while(NRF24L01_IRQ_PIN_READ()!=0);//等待发送完成
sta=NRF24L01_Read_Reg(STATUS); //读取状态寄存器的值
NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中断标志
if(sta&MAX_TX)//达到最大重发次数
{
NRF24L01_Write_Reg(FLUSH_TX,0xff);//清除TX FIFO寄存器
return MAX_TX;
}
if(sta&TX_OK)//发送完成
{
return TX_OK;
}
return 0xff;//其他原因发送失败
}
文中若有错误,欢迎各位在评论区指正,共同学习!
NRF24L01
NRF24L01是工作在2.4~2.5GHz世界通用ISM频段的单片机无线收发芯片。
- NRF24L01的无线速率可设置1或2Mbps
- 使用SPI接口,接口速率支持0~8Mbps
- 同一频道下可接收6个通道数据,共有128个频道可以切换
- 芯片工作电压1.9~3.6V
[tr]管脚功能[/tr]
CSN | 芯片片选线,CSN为低电平芯片工作 |
SCK | 芯片控制的时钟线 |
MISO | 芯片控制数据线 |
MOSI | 芯片控制数据线 |
IRQ | 中断信号,通讯中MCU主要通过IRQ与24L01通信 |
CE | 芯片的模式控制线 |
增强型的ShockBurstTM模式
NRF24L01集成了所有高速链路层的自动应答、自动重发、数据包识别等操作,无需MCU介入。
在接收模式下,NRF24L01可同时接收6个不同通道的数据,每个通道使用不同的地址。芯片可通过STATUS寄存器的RX_P_NO来获取接收数据的通道号。接收时芯片还会通过PID(数据包识别)来判断是否与上一个数据相同,CRC检测数据的完整性,并进行自动应答。接收完毕芯片触发中断RX_DR,数据存储在RX_FIFO中。
在发送模式下,在将打包完的数据发送后,芯片将等待接收端的应答信号,若有则触发中断TX_DS并清除TX_FIFO;若无则自动重发,重发次数大于重发计数器ARC_CNT是,STATUS状态寄存器的MAX_RT置“1”,不清除TX_FIFO的数据。
数据长度,NRF24L01的发送数据长度最长32字节,其支持静态和动态1两种模式。在静态模式中,我们通过RX_PW_Px寄存器来接收数据长度,该模式下发送数据长度必须于设定值相同,若要更改数据长度需要操作相关寄存器。在动态模式中,我们需要先设置FEATURE和DYNPD寄存器来开启,在接收端可使用命令R_RX_PL_WID来获取数据长度。
NRF24L01的6个通道地址有一定的规则,其中只有数据通道0可配置40位地址。而数据通道1~5则是32位共用地址+各自地址。
需要注意:由于芯片要求,在向寄存器写入地址信息时是低字节先写;在配置数据通道2~5,由于仅最后一位可配置,因此定义仅需与设置最后一位即可。
const u8 TX_ADDRESS[TX_ADR_WIDTH]={0x77,0x35,0xF9,0xD3,0xE7}; //发送地址(本机)const u8 RX0_ADDRESS[RX_ADR_WIDTH]={0x77,0x35,0xF9,0xD3,0xE7}; //接收地址0
const u8 RX1_ADDRESS[RX_ADR_WIDTH]={0xC2,0xC2,0xC2,0xC2,0xC2}; //接收地址1
const u8 RX2_ADDRESS[RX_ADR_WIDTH]={0xC3}; //接收地址2
const u8 RX3_ADDRESS[RX_ADR_WIDTH]={0xC4}; //接收地址3
const u8 RX4_ADDRESS[RX_ADR_WIDTH]={0xC5}; //接收地址4
const u8 RX5_ADDRESS[RX_ADR_WIDTH]={0xC6}; //接收地址5
调试思路
SPI通信
NRF24L01使用SPI通信,驱动它的第一步就是通信部分的,将底层通讯部分的程序封装后,后续的寄存器操作等都是可以跨平台移植的。而SPI的通讯又可以分为模拟和硬件两种实现方式,模拟即通过软件操作GPIO来实现SPI通讯协议,这个方法由于时序是软件操作,对单片机工作频率有限定,更改工作频率可能回导致不可用。硬件即使用单片机内部的片上外设,这个相对更加稳定,但其管脚固定,且有些单片机并没有硬件的SPI外设。两种方法需要根据实际情况选择,这里展示STC15和STM32的硬件SPI下的使用方法
STC15
u8 SPIx_ReadWriteByte(u8 byte)
{
u8 d_read,d_send=byte;
SPDAT = d_send;//发送数据
while(!(SPSTAT&SPIF)) //等待数据发送完毕
;
SPSTAT = SPIF|WCOL; //清除状态位
d_read = SPDAT;
return d_read;
}
STM32
uint8_t SPIx_ReadWriteByte(SPI_HandleTypeDef* hspi,uint8_t byte)
{
uint8_t d_read,d_send=byte;
if(HAL_SPI_TransmitReceive(hspi,&d_send,&d_read,1,0xFF)!=HAL_OK)
{
d_read=0xFF;
}
return d_read;
}
动态长度
数据的动态长度必须对下图两个寄存器进行操作
NRF24L01_Write_Reg(NRF_WRITE_REG+DYNPD,0x3F); //开启6通道DPL
NRF24L01_Write_Reg(NRF_WRITE_REG+FEATURE,0x04|0x02);//开启DPL和ACK
在接受端想要获取数据长度便需要发送相关命令,而不是读取RX_PL_Px寄存器中的值
uint8_t NRF24L01_SendSring(uint8_t *txbuf,uint8_t length)
{
uint8_t sta,i;
uint8_t tx_buffer[32];//发送数据缓存
tx_buffer[0]=length-1;//发送数据的首位为数据长度,sizeof求得长度包括了‘ ’
for(i=0;i
{
tx_buffer[i+1] = txbuf
;//将待发送数据放到数据长度后,组成一个完整需要发送的数据
}
SPI1_SetSpeed(SPI_BAUDRATEPRESCALER_16); //spi速度为6.75Mhz(24L01的最大SPI时钟为10Mhz)
NRF24L01_CE_LOW();
NRF24L01_Write_Reg(FLUSH_TX,0xff);
NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,length);//写数据到TX BUF 32个字节
NRF24L01_CE_HIGH();//启动发送
while(NRF24L01_IRQ_PIN_READ()!=0);//等待发送完成
sta=NRF24L01_Read_Reg(STATUS); //读取状态寄存器的值
NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中断标志
if(sta&MAX_TX)//达到最大重发次数
{
NRF24L01_Write_Reg(FLUSH_TX,0xff);//清除TX FIFO寄存器
return MAX_TX;
}
if(sta&TX_OK)//发送完成
{
return TX_OK;
}
return 0xff;//其他原因发送失败
}
文中若有错误,欢迎各位在评论区指正,共同学习!
举报