STM32
直播中

哼小曲

12年用户 1167经验值
私信 关注
[问答]

怎样去使用NRF24L01单片机无线收发芯片呢

NRF24L01是什么?
怎样去使用NRF24L01单片机无线收发芯片呢?

回帖(1)

李龙

2021-12-16 10:38:32
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寄存器来接收数据长度,该模式下发送数据长度必须于设定值相同,若要更改数据长度需要操作相关寄存器。在动态模式中,我们需要先设置FEATUREDYNPD寄存器来开启,在接收端可使用命令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;//其他原因发送失败
}
文中若有错误,欢迎各位在评论区指正,共同学习!
   
举报

更多回帖

×
20
完善资料,
赚取积分