【转】2.4G模块NRF24L01调试经验

2019-07-19 14:13发布

参照野火STM32程序调试NRF24L01成功,颇获喜感nRF24L01是一款工作在2.4~2.5GHz世界通用ISM频段的单片无线收发器芯片。无线收发器包括:频率发生器、增强型SchockBurstTM模式控制器、功率放大器、警惕振荡器、调制器、解调器。输出功率、频道选择和协议的设置可以通过SPI接口进行设置。模块外形图如下图所示:                 PCB和引脚示意图如下图所示:         
电路图如图所示:

VDD电压范围为1.9V~3.6V,我使用的是3.3V,与单片机的通信接口类型为SPI,读写时序如下图所示:
与开发板硬件连接如下:
* 硬件连接:----------------------------—----|
            |  PA5-SPI1-SCK     : NRF -SCK  |
            |   PA6-SPI1-MISO  : NRF -MISO |
            |   PA7-SPI1-MOSI  : NRF -MOSI |
            |   PA4         : NRF -CE     |
*          |   PA3                       : NRF -CSN  |
            |  PA2          : NRF -IRQ    |
*           -------------------------------------------
引脚配置如下:
[objc] view plain copy


  • /*配置 SPI_NRF_SPI的 SCK,MISO,MOSI引脚,GPIOA^5,GPIOA^6,GPIOA^7 */  
  • GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5|GPIO_Pin_6|GPIO_Pin_7;  
  • GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;  
  • GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用功能  
  • GPIO_Init(GPIOA, &GPIO_InitStructure);   
  •   
  • /*配置SPI_NRF_SPI的CE引脚,GPIOA^4和SPI_NRF_SPI的 CSN 引脚: NSS GPIOC^4*/  
  • GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3|GPIO_Pin_4;  
  • GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;  
  • GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;  
  • GPIO_Init(GPIOA, &GPIO_InitStructure);  
  •   
  • /*配置SPI_NRF_SPI的IRQ引脚,GPIOA^2*/  
  • GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;  
  • GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;  
  • GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU ;  //上拉输入  
  • GPIO_Init(GPIOA, &GPIO_InitStructure);   

SPI配置如下:

[objc] view plain copy


  • SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;    //双线全双工  
  • SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                   //主模式  
  • SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;           //数据大小8位  
  • SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;              //时钟极性,空闲时为低  
  • SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;                //第1个边沿有效,上升沿为采样时刻  
  • SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;               //NSS信号由软件产生  
  • SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;    //8分频,9MHz  
  • SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;                  //高位在前  
  • SPI_InitStructure.SPI_CRCPolynomial = 7;  
  • SPI_Init(SPI1, &SPI_InitStructure);  
  •   
  • /* Enable SPI1  */  
  • SPI_Cmd(SPI1, ENABLE);  




友情提示: 此问题已得到解决,问题已经关闭,关闭后问题禁止继续编辑,回答。
12条回答
TXQDM
2019-07-19 14:17
配置进入接收模式:
[objc] view plain copy
void NRF_RX_Mode(void)  
{  
   NRF_CE_LOW();      
   SPI_NRF_WriteBuf(NRF_WRITE_REG+RX_ADDR_P0,RX_ADDRESS,RX_ADR_WIDTH);//写RX节点地址  
   SPI_NRF_WriteReg(NRF_WRITE_REG+EN_AA,0x01);    //使能通道0的自动应答      
   SPI_NRF_WriteReg(NRF_WRITE_REG+EN_RXADDR,0x01);//使能通道0的接收地址      
   SPI_NRF_WriteReg(NRF_WRITE_REG+RF_CH,CHANAL);      //设置RF通信频率      
   SPI_NRF_WriteReg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//选择通道0的有效数据宽度        
   SPI_NRF_WriteReg(NRF_WRITE_REG+RF_SETUP,0x07); //设置TX发射参数,0db增益,1Mbps,低噪声增益开启     
   SPI_NRF_WriteReg(NRF_WRITE_REG+CONFIG, 0x0f);  //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式  
   NRF_CE_HIGH(); /*CE拉高,进入接收模式*/   
   delay_ms(100); //CE拉高一段时间  
}      
配置进入发射模式:
[objc] view plain copy
void NRF_TX_Mode(void)  
{   
   NRF_CE_LOW();         
   SPI_NRF_WriteBuf(NRF_WRITE_REG+TX_ADDR,TX_ADDRESS,TX_ADR_WIDTH);    //写TX节点地址;   
   SPI_NRF_WriteBuf(NRF_WRITE_REG+RX_ADDR_P0,RX_ADDRESS,RX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACK;     
   SPI_NRF_WriteReg(NRF_WRITE_REG+EN_AA,0x01);     //使能通道0的自动应答;      
   SPI_NRF_WriteReg(NRF_WRITE_REG+EN_RXADDR,0x01); //使能通道0的接收地址;   
   SPI_NRF_WriteReg(NRF_WRITE_REG+SETUP_RETR,0x1a);//设置自动重发间隔时间:500us + 86us;最大自动重发次数:10次;  
   SPI_NRF_WriteReg(NRF_WRITE_REG+RF_CH,CHANAL);   //设置RF通道为CHANAL;  
   SPI_NRF_WriteReg(NRF_WRITE_REG+RF_SETUP,0x07);  //设置TX发射参数,0db增益,1Mbps,低噪声增益开启;     
   SPI_NRF_WriteReg(NRF_WRITE_REG+CONFIG,0x0e);    //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,发射模式,开启所有中断;  
/*CE拉高,进入发送模式*/   
   NRF_CE_HIGH();  
   delay_ms(100); //CE要拉高一段时间才进入发送模式  
}  
NRF24L01的开机自检:
[objc] view plain copy
u8 NRF_Check(void)  
{  
    u8 buf[5]={0xC2,0xC2,0xC2,0xC2,0xC2};  
    u8 buf1[5];  
    u8 i;   
      
    SPI_NRF_WriteBuf(NRF_WRITE_REG+TX_ADDR,buf,5); /*写入5个字节的地址.  */   
    SPI_NRF_ReadBuf(TX_ADDR,buf1,5); /*读出写入的地址 */                  
    for(i=0;i<5;i++)     /*比较*/   
    {  
        if(buf1!=0xC2)  
        break;  
    }     
    if(i==5)  
        return SUCCESS ;        //MCU与NRF成功连接   
    else  
        return ERROR ;        //MCU与NRF不正常连接  
}  
数据发送:
[objc] view plain copy
u8 NRF_Tx_Dat(u8 *txb)  
{  
    u8 state;   
    NRF_CE_LOW(); /*ce为低,进入待机模式1*/                        
    SPI_NRF_WriteBuf(WR_TX_PLOAD,txb,TX_PLOAD_WIDTH);   /*写数据到TX BUF 最大 32个字节*/  
    NRF_CE_HIGH();    /*CE为高,txb非空,发送数据包 */                                          
    while(NRF_Read_IRQ()!=0);  /*等待发送完成中断 */      
    state = SPI_NRF_ReadReg(STATUS); /*读取状态寄存器的值 */   
    SPI_NRF_WriteReg(NRF_WRITE_REG+STATUS,state); /*清除TX_DS或MAX_RT中断标志*/      
    SPI_NRF_WriteReg(FLUSH_TX,NOP);    //清除TX FIFO寄存器   
     /*判断中断类型*/      
    if(state&MAX_RT)                     //达到最大重发次数  
        return MAX_RT;   
  
    else if(state&TX_DS)                  //发送完成  
        return TX_DS;  
    else  
        return ERROR;                 //其他原因发送失败  
}   
数据接收,可放在主函数里循环检测,也可更换为中断模式检测:
[objc] view plain copy
u8 NRF_Rx_Dat(u8 *rxb)  
{  
    u8 state;   
    NRF_CE_HIGH();   //进入接收状态  
     /*等待接收中断*/  
    //while(NRF_Read_IRQ()!=0);///////////////////////////////////////////////   
    NRF_CE_LOW();    //进入待机状态                  
    state = SPI_NRF_ReadReg(STATUS);    /*读取status寄存器的值*/   
    if(state&RX_DR)  /*判断是否接收到数据*/  //接收到数据  
    {                                          
        SPI_NRF_WriteReg(NRF_WRITE_REG+STATUS,state);/* 清除中断标志*/   
        SPI_NRF_ReadBuf(RD_RX_PLOAD,rxb,RX_PLOAD_WIDTH);//读取数据  
//      SPI_NRF_WriteReg(FLUSH_RX,NOP);          //清除RX FIFO寄存器  
        return RX_DR;   
    }else      
        return ERROR;                    //没收到任何数据  
}  

主循环任务程序如下:
[objc] view plain copy
void nrf_task(voidvoid *pdata)  
{  
    while(NRF_Check()!=SUCCESS){  
        <span style="white-space:pre">    </span>delay_ms(100);  
    }  
    NRF_TX_Mode();//主动请求连接  
    nrf_Txbuf[0]='H';  
    nrf_Txbuf[1]='E';  
    nrf_Txbuf[2]='L';  
    nrf_Txbuf[3]='L';  
    nrf_Txbuf[4]='0';  
    do  
    {      
        status = NRF_Tx_Dat(nrf_Txbuf);  
    }while((status != TX_DS)&(status != MAX_RT));//发送成功或者到达最大重发次数  
    <span style="white-space:pre">    </span>if(status == MAX_RT)   
    {      
        USART1_printf( USART1,"Connection Failed ");  
    }  
    <span style="white-space:pre">    </span>memset(nrf_Txbuf,0,sizeof(nrf_Txbuf));  
    NRF_RX_Mode();//配置为接收模式  
      
    while(1)  
    {  
        /*等待接收数据*/  
        status = NRF_Rx_Dat(nrf_Rxbuf);  
        /*判断接收状态*/  
        if(status == RX_DR)//接收到数据中断标志  
        {  
            Usb_SendData((char*)nrf_Rxbuf,strlen((char*)nrf_Rxbuf));//通过USB转发  
        }  
         
        if(0 != strlen((char*)nrf_Txbuf))//发送缓冲不为空  
        {  
            NRF_TX_Mode();//主动请求连接  
            do  
            {      
                status = NRF_Tx_Dat(nrf_Txbuf);  
                delay_ms(10);  
            }while((status != TX_DS)&(status != MAX_RT));//发送成功或者到达最大重发次数  
            memset(nrf_Txbuf,0,sizeof(nrf_Txbuf));  
            NRF_RX_Mode();//配置为接收模式  
        }  
        delay_ms(100);  
    }  
}  

一周热门 更多>