• 正文
    • 一模塊來源
    • 二規(guī)格參數(shù)
    • 三移植過程
    • 四移植驗證
  • 相關(guān)推薦
申請入駐 產(chǎn)業(yè)圖譜

【CW32模塊使用】NRF24L01無線2.4G模塊

01/13 12:54
2001
加入交流群
掃碼加入
獲取工程師必備禮包
參與熱點資訊討論

NRF24L01是一款工作在2.4-2.5GHz世界通用ISM頻段的單片收發(fā)芯片, 使用4線SPI通訊端口,通訊速率最高可達8Mbps,適合與各種MCU連接,編程簡單;輸出功率、頻道選擇和協(xié)議的設(shè)置可以通過SPI接口設(shè)置極低的電流消耗,當工作在發(fā)射模式下發(fā)射功率為6dBm時電流消耗為9.0mA接受模式為12.3mA掉電模式和待機模式下電流消耗模式更低。

模塊來源

模塊實物展示:

資料鏈接:https://pan.baidu.com/s/1CUQ3SOdnmD8xSXMdR4YopA

資料提取碼:1234

規(guī)格參數(shù)

工作電壓:1.9~3.6V

供電電流:900 ~ 12.3mA

最大數(shù)據(jù)傳輸率:2000 Kbps

控制方式:SPI

管腳數(shù)量:8 Pin(2.54mm間距排針

以上信息見廠家資料文件

移植過程

我們的目標是將例程移植至CW32F030C8T6開發(fā)板上【實現(xiàn)無線的數(shù)據(jù)傳輸?shù)墓δ堋俊J紫纫@取資料,查看數(shù)據(jù)手冊應(yīng)如何實現(xiàn)讀取數(shù)據(jù),再移植至我們的工程。

3.1查看資料

接收方式

NRF24L01的接收端是靠IRQ引腳進行判斷,當IRQ為高電平時,說明接收到了數(shù)據(jù),IRQ為1則是正在等待數(shù)據(jù)。因此可以根據(jù)IRQ引腳來決定接收的方式。這里提供輪詢方式和中斷方式。

輪詢方式接收

采用輪詢方式會阻礙其他任務(wù)的運行,因接收數(shù)據(jù)要時時刻刻判斷IRQ引腳是否為高電平,會一直占用MCU的時間。為了解決因為沒有接收到數(shù)據(jù)就卡死問題以及防止錯過數(shù)據(jù)沒有接收問題,在等待數(shù)據(jù)的過程中,加入了超時判斷,當一定的時間內(nèi)沒有接收到數(shù)據(jù),則結(jié)束等待接收,去運行其他任務(wù)。

中斷方式接收

采用中斷方式接收數(shù)據(jù),是通過將IRQ引腳設(shè)置為外部中斷功能。當檢測到IRQ引腳有變化時,則接收數(shù)據(jù)。根據(jù)24L01的要求,當接收完數(shù)據(jù)后,必須清除接收的FIFO。

3.2引腳選擇

引腳說明

硬件SPI與軟件SPI相比,硬件SPI是靠硬件上面的SPI控制器,所有的時鐘邊緣采樣,時鐘發(fā)生,還有時序控制,都是由硬件完成的。它降低了CPU的使用率,提高了運行速度。軟件SPI就是用代碼控制IO輸出高低電平,模擬SPI的時序,這種方法通信速度較慢,且不可靠。

想要使用硬件SPI驅(qū)動,需要確定使用的引腳是否有SPI外設(shè)功能??梢酝ㄟ^用戶手冊146頁進行查看。

當前使用的是硬件SPI接口,而NRF24L01我們需要與它發(fā)送數(shù)據(jù)也需要接收數(shù)據(jù),故使用的是4線的SPI,使用到了時鐘線SCK、主機輸出從機輸入線MOSI、主機輸入從機輸出線MISO和軟件控制的片選線NSS。所以除了這些引腳需要使用硬件SPI功能的引腳外,其他引腳都可以使用開發(fā)板上其他的GPIO。這里選擇使用PA5/PA6/PA7的SPI復(fù)用功能?。其他對應(yīng)接入的引腳請按照你的需要。這里選擇的引腳見右表。

有SPI功能的引腳

模塊接線圖

3.3移植至工程

移植步驟中的導(dǎo)入.c和.h文件與【CW32模塊使用】DHT11溫濕度傳感器相同,只是將.c和.h文件更改為drv_spi.c與drv_spi.h。這里不再過多講述,移植完成后面修改相關(guān)代碼。

在drv_spi.c中,修改為如下代碼。

/* * Change Logs: * Date           Author       Notes * 2024-06-21     LCKFB-LP    first version */
#include "drv_spi.h"


/** 硬件SPI */#define SPI_WAIT_TIMEOUT       ((uint16_t)0xFFFF)
/**  * @brief :SPI初始化(硬件)  * @param :無  * @note  :無  * @retval:無  */void drv_spi_init( void ){        GPIO_InitTypeDef GPIO_InitStruct1;             // GPIO初始化結(jié)構(gòu)體        GPIO_InitTypeDef GPIO_InitStruct2;             // GPIO初始化結(jié)構(gòu)體
        SPI_GPIO_RCC();                                // 使能GPIO時鐘        RCC_SPI_HARDWARE_ENABLE();                     // 使能SPI1時鐘
        // GPIO復(fù)用為SPI1        BSP_SPI_AF_SCK();        BSP_SPI_AF_MISO();        BSP_SPI_AF_MOSI();
        GPIO_InitStruct1.Pins = SPI_NSS_GPIO_PIN|                                                        SPI_CLK_GPIO_PIN|                                                        SPI_MOSI_GPIO_PIN;      // GPIO引腳        GPIO_InitStruct1.Mode = GPIO_MODE_OUTPUT_PP;    // 推挽輸出        GPIO_InitStruct1.Speed = GPIO_SPEED_HIGH;       // 輸出速度高        GPIO_Init(SPI_GPIO_PORT, &GPIO_InitStruct1);    // 初始化
        GPIO_InitStruct2.Pins = SPI_MISO_GPIO_PIN;      // GPIO引腳        GPIO_InitStruct2.Mode = GPIO_MODE_INPUT_PULLUP; // 上拉輸入        GPIO_Init(SPI_GPIO_PORT, &GPIO_InitStruct2);    // 初始化
        spi_set_nss_high();  // 片選拉高
        SPI_InitTypeDef  SPI_InitStructure; // SPI 初始化結(jié)構(gòu)體
        SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;    // 雙線全雙工        SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                         // 主機模式        SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                     // 幀數(shù)據(jù)長度為8bit        SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;                            // 時鐘空閑電平為低        SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;                          // 第1個邊沿采樣        SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                             // 片選信號由SSI寄存器控制        SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8;    // 波特率為PCLK的8分頻        SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;                    // 最高有效位 MSB 收發(fā)在前        SPI_InitStructure.SPI_Speed = SPI_Speed_Low;                          // 低速SPI
        SPI_Init(PORT_SPI, &SPI_InitStructure);   // 初始化        SPI_Cmd(PORT_SPI, ENABLE);   // 使能SPI1}
/**  * @brief :SPI收發(fā)一個字節(jié)  * @param :  * @TxByte: 發(fā)送的數(shù)據(jù)字節(jié)  * @note  :非堵塞式,一旦等待超時,函數(shù)會自動退出  * @retval:接收到的字節(jié)  */uint16_t drv_spi_read_write_byte( uint8_t TxByte ){        uint16_t l_Data = 0;        uint16_t l_WaitTime = 0;
    while(RESET == SPI_GetFlagStatus(PORT_SPI, SPI_FLAG_TXE))//等待發(fā)送緩沖區(qū)為空        {                if( SPI_WAIT_TIMEOUT == ++l_WaitTime )                {                        break;                        //如果等待超時則退出                }        }        l_WaitTime = SPI_WAIT_TIMEOUT / 2;                //重新設(shè)置接收等待時間(因為SPI的速度很快,正常情況下在發(fā)送完成之后會立即收到數(shù)據(jù),等待時間不需要過長)        SPI_SendData(PORT_SPI, TxByte);//發(fā)送數(shù)據(jù)
    while(RESET == SPI_GetFlagStatus(PORT_SPI, SPI_FLAG_RXNE))//等待接收緩沖區(qū)非空        {                if( SPI_WAIT_TIMEOUT == ++l_WaitTime )                {                                break;                        //如果等待超時則退出                }        }    l_Data = SPI_ReceiveData(PORT_SPI);//讀取接收數(shù)據(jù)
        return l_Data;                //返回}
/**  * @brief :SPI收發(fā)字符串  * @param :  * @ReadBuffer: 接收數(shù)據(jù)緩沖區(qū)地址  * @WriteBuffer:發(fā)送字節(jié)緩沖區(qū)地址  * @Length:字節(jié)長度  * @note  :非堵塞式,一旦等待超時,函數(shù)會自動退出  * @retval:無  */void drv_spi_read_write_string( uint8_t* ReadBuffer, uint8_t* WriteBuffer, uint16_t Length ){    spi_set_nss_low( );//拉低片選        while( Length-- )        {                *ReadBuffer = drv_spi_read_write_byte( *WriteBuffer ); //收發(fā)數(shù)據(jù)                ReadBuffer++;                WriteBuffer++;                                //讀寫地址加1        }    spi_set_nss_high( );//拉高片選}

在drv_spi.h中,修改為如下代碼。

/* * Change Logs: * Date           Author       Notes * 2024-06-21     LCKFB-LP    first version */
#ifndef __DRV_SPI_H__#define __DRV_SPI_H__
#include "board.h"

//SPI引腳定義#define SPI_GPIO_RCC()           __RCC_GPIOA_CLK_ENABLE() // GPIO時鐘
#define SPI_GPIO_PORT            CW_GPIOA
#define SPI_CLK_GPIO_PIN         GPIO_PIN_5#define SPI_MISO_GPIO_PIN        GPIO_PIN_6#define SPI_MOSI_GPIO_PIN        GPIO_PIN_7#define SPI_NSS_GPIO_PIN         GPIO_PIN_4

#define spi_set_nss_high( )      GPIO_WritePin(SPI_GPIO_PORT, SPI_NSS_GPIO_PIN, GPIO_Pin_SET)   //片選置高#define spi_set_nss_low( )       GPIO_WritePin(SPI_GPIO_PORT, SPI_NSS_GPIO_PIN, GPIO_Pin_RESET) //片選置低


/******** 硬件SPI修改此次 ********/#define RCC_SPI_HARDWARE_ENABLE()         __RCC_SPI1_CLK_ENABLE()#define PORT_SPI                          CW_SPI1
//GPIO AF#define BSP_SPI_AF_SCK()                  PA05_AFx_SPI1SCK()#define BSP_SPI_AF_MISO()                 PA06_AFx_SPI1MISO()#define BSP_SPI_AF_MOSI()                 PA07_AFx_SPI1MOSI()

void drv_spi_init( void );uint16_t drv_spi_read_write_byte( uint8_t TxByte );void drv_spi_read_write_string( uint8_t* ReadBuffer, uint8_t* WriteBuffer, uint16_t Length );
#endif

在NRF24L01.c中,修改如下代碼。?

/* * Change Logs: * Date           Author       Notes * 2024-06-21     LCKFB-LP    first version */
#include "NRF24L01.h"#include "stdio.h"

const char *g_ErrorString = "RF24L01 is not find !...";

void drv_delay_500Ms( unsigned int ms){        while(ms--)        {                delay_ms(500);        }}
/**  * @brief :NRF24L01讀寄存器  * @param :           @Addr:寄存器地址  * @note  :地址在設(shè)備中有效  * @retval:讀取的數(shù)據(jù)  */uint8_t NRF24L01_Read_Reg( uint8_t RegAddr ){    uint8_t btmp;
    RF24L01_SET_CS_LOW( );       //片選
    drv_spi_read_write_byte( NRF_READ_REG | RegAddr );    //讀命令 地址    btmp = drv_spi_read_write_byte( 0xFF );               //讀數(shù)據(jù)
    RF24L01_SET_CS_HIGH( );      //取消片選
    return btmp;}
/**  * @brief :NRF24L01讀指定長度的數(shù)據(jù)  * @param :  *                        @reg:地址  *                        @pBuf:數(shù)據(jù)存放地址  *                        @len:數(shù)據(jù)長度  * @note  :數(shù)據(jù)長度不超過255,地址在設(shè)備中有效  * @retval:讀取狀態(tài)  */void NRF24L01_Read_Buf( uint8_t RegAddr, uint8_t *pBuf, uint8_t len ){    uint8_t btmp;
    RF24L01_SET_CS_LOW( );                        //片選
    drv_spi_read_write_byte( NRF_READ_REG | RegAddr );        //讀命令 地址    for( btmp = 0; btmp < len; btmp ++ )    {        *( pBuf + btmp ) = drv_spi_read_write_byte( 0xFF );        //讀數(shù)據(jù)    }    RF24L01_SET_CS_HIGH( );                //取消片選}
/**  * @brief :NRF24L01寫寄存器  * @param :無  * @note  :地址在設(shè)備中有效  * @retval:讀寫狀態(tài)  */void NRF24L01_Write_Reg( uint8_t RegAddr, uint8_t Value ){    RF24L01_SET_CS_LOW( );                //片選
    drv_spi_read_write_byte( NRF_WRITE_REG | RegAddr );        //寫命令 地址    drv_spi_read_write_byte( Value );                        //寫數(shù)據(jù)
    RF24L01_SET_CS_HIGH( );                //取消片選}
/**  * @brief :NRF24L01寫指定長度的數(shù)據(jù)  * @param :  *                        @reg:地址  *                        @pBuf:寫入的數(shù)據(jù)地址  *                        @len:數(shù)據(jù)長度  * @note  :數(shù)據(jù)長度不超過255,地址在設(shè)備中有效  * @retval:寫狀態(tài)  */void NRF24L01_Write_Buf( uint8_t RegAddr, uint8_t *pBuf, uint8_t len ){    uint8_t i;
    RF24L01_SET_CS_LOW( );                //片選
    drv_spi_read_write_byte( NRF_WRITE_REG | RegAddr );        //寫命令 地址    for( i = 0; i < len; i ++ )    {        drv_spi_read_write_byte( *( pBuf + i ) );                //寫數(shù)據(jù)    }
    RF24L01_SET_CS_HIGH( );                //取消片選}
/**  * @brief :清空TX緩沖區(qū)  * @param :無  * @note  :無  * @retval:無  */void NRF24L01_Flush_Tx_Fifo ( void ){    RF24L01_SET_CS_LOW( );                //片選
    drv_spi_read_write_byte( FLUSH_TX );        //清TX FIFO命令
    RF24L01_SET_CS_HIGH( );                //取消片選}
/**  * @brief :清空RX緩沖區(qū)  * @param :無  * @note  :無  * @retval:無  */void NRF24L01_Flush_Rx_Fifo( void ){    RF24L01_SET_CS_LOW( );                //片選
    drv_spi_read_write_byte( FLUSH_RX );        //清RX FIFO命令
    RF24L01_SET_CS_HIGH( );                //取消片選}
/**  * @brief :重新使用上一包數(shù)據(jù)  * @param :無  * @note  :無  * @retval:無  */void NRF24L01_Reuse_Tx_Payload( void ){    RF24L01_SET_CS_LOW( );                //片選
    drv_spi_read_write_byte( REUSE_TX_PL );                //重新使用上一包命令
    RF24L01_SET_CS_HIGH( );                //取消片選}
/**  * @brief :NRF24L01空操作  * @param :無  * @note  :無  * @retval:無  */void NRF24L01_Nop( void ){    RF24L01_SET_CS_LOW( );                //片選
    drv_spi_read_write_byte( NOP );                //空操作命令
    RF24L01_SET_CS_HIGH( );                //取消片選}
/**  * @brief :NRF24L01讀狀態(tài)寄存器  * @param :無  * @note  :無  * @retval:RF24L01狀態(tài)  */uint8_t NRF24L01_Read_Status_Register( void ){    uint8_t Status;
    RF24L01_SET_CS_LOW( );                //片選
    Status = drv_spi_read_write_byte( NRF_READ_REG + STATUS );        //讀狀態(tài)寄存器
    RF24L01_SET_CS_HIGH( );                //取消片選
    return Status;}
/**  * @brief :NRF24L01清中斷  * @param :           @IRQ_Source:中斷源  * @note  :無  * @retval:清除后狀態(tài)寄存器的值  */uint8_t NRF24L01_Clear_IRQ_Flag( uint8_t IRQ_Source ){    uint8_t btmp = 0;
    IRQ_Source &= ( 1 << RX_DR ) | ( 1 << TX_DS ) | ( 1 << MAX_RT );        //中斷標志處理    btmp = NRF24L01_Read_Status_Register( );                        //讀狀態(tài)寄存器
    RF24L01_SET_CS_LOW( );                        //片選    drv_spi_read_write_byte( NRF_WRITE_REG + STATUS );        //寫狀態(tài)寄存器命令    drv_spi_read_write_byte( IRQ_Source | btmp );                //清相應(yīng)中斷標志    RF24L01_SET_CS_HIGH( );                        //取消片選
    return ( NRF24L01_Read_Status_Register( ));                        //返回狀態(tài)寄存器狀態(tài)}
/**  * @brief :讀RF24L01中斷狀態(tài)  * @param :無  * @note  :無  * @retval:中斷狀態(tài)  */uint8_t RF24L01_Read_IRQ_Status( void ){    return ( NRF24L01_Read_Status_Register( ) & (( 1 << RX_DR ) | ( 1 << TX_DS ) | ( 1 << MAX_RT )));        //返回中斷狀態(tài)}
 /**  * @brief :讀FIFO中數(shù)據(jù)寬度  * @param :無  * @note  :無  * @retval:數(shù)據(jù)寬度  */uint8_t NRF24L01_Read_Top_Fifo_Width( void ){    uint8_t btmp;
    RF24L01_SET_CS_LOW( );                //片選
    drv_spi_read_write_byte( R_RX_PL_WID );        //讀FIFO中數(shù)據(jù)寬度命令    btmp = drv_spi_read_write_byte( 0xFF );        //讀數(shù)據(jù)
    RF24L01_SET_CS_HIGH( );                //取消片選
    return btmp;}
 /**  * @brief :讀接收到的數(shù)據(jù)  * @param :無  * @note  :無  * @retval:           @pRxBuf:數(shù)據(jù)存放地址首地址  */uint8_t NRF24L01_Read_Rx_Payload( uint8_t *pRxBuf ){    uint8_t Width, PipeNum;
    PipeNum = ( NRF24L01_Read_Reg( STATUS ) >> 1 ) & 0x07;        //讀接收狀態(tài)    Width = NRF24L01_Read_Top_Fifo_Width( );                //讀接收數(shù)據(jù)個數(shù)
    RF24L01_SET_CS_LOW( );                //片選    drv_spi_read_write_byte( RD_RX_PLOAD );                        //讀有效數(shù)據(jù)命令
    for( PipeNum = 0; PipeNum < Width; PipeNum ++ )    {        *( pRxBuf + PipeNum ) = drv_spi_read_write_byte( 0xFF );                //讀數(shù)據(jù)    }    RF24L01_SET_CS_HIGH( );                //取消片選    NRF24L01_Flush_Rx_Fifo( );        //清空RX FIFO
    return Width;}
 /**  * @brief :發(fā)送數(shù)據(jù)(帶應(yīng)答)  * @param :  *                        @pTxBuf:發(fā)送數(shù)據(jù)地址  *                        @len:長度  * @note  :一次不超過32個字節(jié)  * @retval:無  */void NRF24L01_Write_Tx_Payload_Ack( uint8_t *pTxBuf, uint8_t len ){    uint8_t btmp;    uint8_t length = ( len > 32 ) ? 32 : len;                //數(shù)據(jù)長達大約32 則只發(fā)送32個
    NRF24L01_Flush_Tx_Fifo( );                //清TX FIFO
    RF24L01_SET_CS_LOW( );                        //片選    drv_spi_read_write_byte( WR_TX_PLOAD );        //發(fā)送命令
    for( btmp = 0; btmp < length; btmp ++ )    {        drv_spi_read_write_byte( *( pTxBuf + btmp ) );        //發(fā)送數(shù)據(jù)    }    RF24L01_SET_CS_HIGH( );                        //取消片選}
 /**  * @brief :發(fā)送數(shù)據(jù)(不帶應(yīng)答)  * @param :  *                        @pTxBuf:發(fā)送數(shù)據(jù)地址  *                        @len:長度  * @note  :一次不超過32個字節(jié)  * @retval:無  */void NRF24L01_Write_Tx_Payload_NoAck( uint8_t *pTxBuf, uint8_t len ){    if( len > 32 || len == 0 )    {        return ;                //數(shù)據(jù)長度大于32 或者等于0 不執(zhí)行    }
    RF24L01_SET_CS_LOW( );        //片選    drv_spi_read_write_byte( WR_TX_PLOAD_NACK );        //發(fā)送命令    while( len-- )    {        drv_spi_read_write_byte( *pTxBuf );                        //發(fā)送數(shù)據(jù)                pTxBuf++;    }    RF24L01_SET_CS_HIGH( );                //取消片選}
 /**  * @brief :在接收模式下向TX FIFO寫數(shù)據(jù)(帶ACK)  * @param :  *                        @pData:數(shù)據(jù)地址  *                        @len:長度  * @note  :一次不超過32個字節(jié)  * @retval:無  */void NRF24L01_Write_Tx_Payload_InAck( uint8_t *pData, uint8_t len ){    uint8_t btmp;
        len = ( len > 32 ) ? 32 : len;                //數(shù)據(jù)長度大于32個則只寫32個字節(jié)
    RF24L01_SET_CS_LOW( );                        //片選    drv_spi_read_write_byte( W_ACK_PLOAD );                //命令    for( btmp = 0; btmp < len; btmp ++ )    {        drv_spi_read_write_byte( *( pData + btmp ) );        //寫數(shù)據(jù)    }    RF24L01_SET_CS_HIGH( );                        //取消片選}
 /**  * @brief :設(shè)置發(fā)送地址  * @param :  *                        @pAddr:地址存放地址  *                        @len:長度  * @note  :無  * @retval:無  */void NRF24L01_Set_TxAddr( uint8_t *pAddr, uint8_t len ){        len = ( len > 5 ) ? 5 : len;                                        //地址不能大于5個字節(jié)    NRF24L01_Write_Buf( TX_ADDR, pAddr, len );        //寫地址}
 /**  * @brief :設(shè)置接收通道地址  * @param :  *                        @PipeNum:通道  *                        @pAddr:地址存肥著地址  *                        @Len:長度  * @note  :通道不大于5 地址長度不大于5個字節(jié)  * @retval:無  */void NRF24L01_Set_RxAddr( uint8_t PipeNum, uint8_t *pAddr, uint8_t Len ){    Len = ( Len > 5 ) ? 5 : Len;    PipeNum = ( PipeNum > 5 ) ? 5 : PipeNum;                //通道不大于5 地址長度不大于5個字節(jié)
    NRF24L01_Write_Buf( RX_ADDR_P0 + PipeNum, pAddr, Len );        //寫入地址}
 /**  * @brief :設(shè)置通信速度  * @param :  *                        @Speed:速度  * @note  :無  * @retval:無  */void NRF24L01_Set_Speed( nRf24l01SpeedType Speed ){        uint8_t btmp = 0;
        btmp = NRF24L01_Read_Reg( RF_SETUP );        btmp &= ~( ( 1<<5 ) | ( 1<<3 ) );
        if( Speed == SPEED_250K )                //250K        {                btmp |= ( 1<<5 );        }        else if( Speed == SPEED_1M )   //1M        {                   btmp &= ~( ( 1<<5 ) | ( 1<<3 ) );        }        else if( Speed == SPEED_2M )   //2M        {                btmp |= ( 1<<3 );        }
        NRF24L01_Write_Reg( RF_SETUP, btmp );}
 /**  * @brief :設(shè)置功率  * @param :  *                        @Speed:速度  * @note  :無  * @retval:無  */void NRF24L01_Set_Power( nRf24l01PowerType Power ){    uint8_t btmp;
        btmp = NRF24L01_Read_Reg( RF_SETUP ) & ~0x07;    switch( Power )    {        case POWER_F18DBM:            btmp |= PWR_18DB;            break;        case POWER_F12DBM:            btmp |= PWR_12DB;            break;        case POWER_F6DBM:            btmp |= PWR_6DB;            break;        case POWER_0DBM:            btmp |= PWR_0DB;            break;        default:            break;    }    NRF24L01_Write_Reg( RF_SETUP, btmp );}
 /**  * @brief :設(shè)置頻率  * @param :  *                        @FreqPoint:頻率設(shè)置參數(shù)  * @note  :值不大于127  * @retval:無  */void RF24LL01_Write_Hopping_Point( uint8_t FreqPoint ){    NRF24L01_Write_Reg(  RF_CH, FreqPoint & 0x7F );}
/**  * @brief :NRF24L01檢測  * @param :無  * @note  :無  * @retval:無  */void NRF24L01_check( void ){        uint8_t i;        uint8_t error = 0;        uint8_t buf[5]={ 0XA5, 0XA5, 0XA5, 0XA5, 0XA5 };        uint8_t read_buf[ 5 ] = { 0 };
        while( 1 )        {                NRF24L01_Write_Buf( TX_ADDR, buf, 5 );       //寫入5個字節(jié)的地址                NRF24L01_Read_Buf( TX_ADDR, read_buf, 5 );   //讀出寫入的地址                for( i = 0; i < 5; i++ )                {                        if( buf[ i ] != read_buf[ i ] )                        {                                break;                        }                }
                if( 5 == i )                {                        break;                }                else                {                        error++;                        if( error >= 3 )                        {                                break;                        }                        //測試錯誤                        printf("NRF24L01 ERROR  FILE:NRF24L01.C  LINE = %drn",__LINE__);                }                drv_delay_500Ms( 4 );        }    printf("Successful configurationrn");}
 /**  * @brief :設(shè)置模式  * @param :  *                        @Mode:模式發(fā)送模式或接收模式  * @note  :無  * @retval:無  */void RF24L01_Set_Mode( nRf24l01ModeType Mode ){    uint8_t controlreg = 0;        controlreg = NRF24L01_Read_Reg( CONFIG );
    if( Mode == MODE_TX )        {                controlreg &= ~( 1<< PRIM_RX );        }    else        {                if( Mode == MODE_RX )                {                        controlreg |= ( 1<< PRIM_RX );                }        }
    NRF24L01_Write_Reg( CONFIG, controlreg );}
/**  * @brief :NRF24L01發(fā)送一次數(shù)據(jù)  * @param :  *                        @txbuf:待發(fā)送數(shù)據(jù)首地址  *                        @Length:發(fā)送數(shù)據(jù)長度  * @note  :無  * @retval:  *                        MAX_TX:達到最大重發(fā)次數(shù)  *                        TX_OK:發(fā)送完成  *                        0xFF:其他原因  */uint8_t NRF24L01_TxPacket( uint8_t *txbuf, uint8_t Length ){        uint8_t l_Status = 0;        uint16_t l_MsTimes = 0;
        RF24L01_SET_CS_LOW( );                //片選        drv_spi_read_write_byte( FLUSH_TX );        RF24L01_SET_CS_HIGH( );
        RF24L01_SET_CE_LOW( );        NRF24L01_Write_Buf( WR_TX_PLOAD, txbuf, Length );        //寫數(shù)據(jù)到TX BUF 32字節(jié)  TX_PLOAD_WIDTH        RF24L01_SET_CE_HIGH( );                        //啟動發(fā)送        while( 0 != RF24L01_GET_IRQ_STATUS( ))        {                delay_ms( 5 );//        printf("error-1rn");                if( 500 == l_MsTimes++ )                                                //500ms還沒有發(fā)送成功,重新初始化設(shè)備                {
                        NRF24L01_Gpio_Init_transmit( );
                        RF24L01_Init( );                        RF24L01_Set_Mode( MODE_TX );                        break;                }        }        l_Status = NRF24L01_Read_Reg(STATUS);                                                //讀狀態(tài)寄存器        NRF24L01_Write_Reg( STATUS, l_Status );                                                //清除TX_DS或MAX_RT中斷標志
        if( l_Status & MAX_TX )        //達到最大重發(fā)次數(shù)        {                NRF24L01_Write_Reg( FLUSH_TX,0xff );        //清除TX FIFO寄存器                return MAX_TX;        }        if( l_Status & TX_OK )        //發(fā)送完成        {                return TX_OK;        }
        return 0xFF;        //其他原因發(fā)送失敗}

void key_gpio_config(void){        RF24L01_CE_GPIO_RCC_ENABLE();      // 使能GPIO時鐘
        GPIO_InitTypeDef GPIO_InitStruct;                    // GPIO初始化結(jié)構(gòu)體
        GPIO_InitStruct.Pins  = RF24L01_IRQ_GPIO_PIN;        // GPIO引腳        GPIO_InitStruct.Mode  = GPIO_MODE_INPUT_PULLUP;             // 上拉輸入        GPIO_InitStruct.Speed = GPIO_SPEED_HIGH;             // 速度高        GPIO_InitStruct.IT    = GPIO_IT_FALLING;             // 下降沿觸發(fā)中斷        GPIO_Init(RF24L01_GPIO_PORT, &GPIO_InitStruct);      // 初始化
        // 清除PA0中斷標志        GPIOA_INTFLAG_CLR(BSP_KEY_EXTI_PIN);        // 使能NVIC        NVIC_EnableIRQ(BSP_KEY_EXTI_IRQN);
}
 /**  * @brief :RF24L01引腳初始化  * @param :無  * @note  :無  * @retval:無  */void NRF24L01_Gpio_Init_receive( void ){        RF24L01_CE_GPIO_RCC_ENABLE(); // GPIO時鐘使能
        //CE推挽輸出        GPIO_InitTypeDef  GPIO_InitStructure;
        GPIO_InitStructure.Pins = RF24L01_CE_GPIO_PIN;        GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;        GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;        GPIO_Init(RF24L01_GPIO_PORT, &GPIO_InitStructure);
////        IRQ上拉輸入//        gpio_mode_set(RF24L01_IRQ_GPIO_PORT, GPIO_MODE_INPUT, GPIO_PUPD_PULLUP,RF24L01_IRQ_GPIO_PIN);//    gpio_output_options_set(RF24L01_IRQ_GPIO_PORT, GPIO_OTYPE_PP, GPIO_OSPEED_50MHZ,RF24L01_IRQ_GPIO_PIN);//    gpio_bit_set(RF24L01_IRQ_GPIO_PORT,RF24L01_IRQ_GPIO_PIN);//        IRQ外部中斷方式        key_gpio_config();
        RF24L01_SET_CE_LOW( );        RF24L01_SET_CS_HIGH( );}


/************************************************函數(shù)名稱 : BSP_KEY_EXTI_IRQHandler功    能 : 中斷處理函數(shù)參    數(shù) : 無返 回 值 : 無作    者 : LCEDA*************************************************/extern uint8_t g_RF24L01RxBuffer[30];
extern uint32_t flag;
void Buff_Clear(void){        for(int i = 0; i < 30; i++)        {                g_RF24L01RxBuffer[i] = 0;        }}
void BSP_KEY_EXTI_IRQHANDLER(void){  if(RF24L01_GPIO_PORT->ISR_f.BSP_KEY_EXTI_JUDGE)   // 中斷標志位為1,按鍵按下  {                if(GPIO_ReadPin(RF24L01_GPIO_PORT, RF24L01_IRQ_GPIO_PIN) == GPIO_Pin_RESET)  // IRQ為低電平                {            NRF24L01_RxPacket(g_RF24L01RxBuffer);  //接收數(shù)據(jù)//            printf("data = %s",g_RF24L01RxBuffer );//輸出數(shù)據(jù)

            RF24L01_SET_CS_LOW( );                //片選            drv_spi_read_write_byte( FLUSH_RX );//清除RX FIFO寄存器            RF24L01_SET_CS_HIGH( );                }        else// IRQ為高電平        {
                }                GPIOA_INTFLAG_CLR(BSP_KEY_EXTI_PIN); // 清除標志位   }}
/**  * @brief :NRF24L01接收數(shù)據(jù)  * @param :  *                        @rxbuf:接收數(shù)據(jù)存放地址  * @note  :無  * @retval:接收的數(shù)據(jù)個數(shù)  */uint8_t NRF24L01_RxPacket( uint8_t *rxbuf ){        uint8_t l_Status = 0, l_RxLength = 0;
        l_Status = NRF24L01_Read_Reg( STATUS );                //讀狀態(tài)寄存器        NRF24L01_Write_Reg( STATUS,l_Status );                //清中斷標志        if( l_Status & RX_OK)        //接收到數(shù)據(jù)        {                l_RxLength = NRF24L01_Read_Reg( R_RX_PL_WID );                //讀取接收到的數(shù)據(jù)個數(shù)                NRF24L01_Read_Buf( RD_RX_PLOAD,rxbuf,l_RxLength );        //接收到數(shù)據(jù)                NRF24L01_Write_Reg( FLUSH_RX,0xff );                                //清除RX FIFO                return l_RxLength;        }        return 0;                                //沒有收到數(shù)據(jù)}
 /**  * @brief :RF24L01引腳初始化  * @param :無  * @note  :無  * @retval:無  */void NRF24L01_Gpio_Init_transmit( void ){        RF24L01_CE_GPIO_RCC_ENABLE(); // GPIO使能時鐘
        //CE推挽輸出        GPIO_InitTypeDef  GPIO_InitStructure;
        GPIO_InitStructure.Pins = RF24L01_CE_GPIO_PIN;        GPIO_InitStructure.Mode = GPIO_MODE_OUTPUT_PP;        GPIO_InitStructure.Speed = GPIO_SPEED_HIGH;        GPIO_Init(RF24L01_GPIO_PORT, &GPIO_InitStructure);
//        GPIO_InitStructure.Pins = RF24L01_IRQ_GPIO_PIN;//        GPIO_InitStructure.Mode = GPIO_MODE_INPUT_PULLUP;//        GPIO_Init(RF24L01_GPIO_PORT, &GPIO_InitStructure);////        GPIO_WritePin( RF24L01_GPIO_PORT, RF24L01_IRQ_GPIO_PIN,GPIO_Pin_SET);
        key_gpio_config();
        RF24L01_SET_CE_LOW( );        RF24L01_SET_CS_HIGH( );}

 /**  * @brief :RF24L01模塊初始化  * @param :無  * @note  :無  * @retval:無  */void RF24L01_Init( void ){    uint8_t addr[5] = {INIT_ADDR};
    RF24L01_SET_CE_HIGH( );    NRF24L01_Clear_IRQ_Flag( IRQ_ALL );#if DYNAMIC_PACKET == 1
    NRF24L01_Write_Reg( DYNPD, ( 1 << 0 ) );         //使能通道1動態(tài)數(shù)據(jù)長度    NRF24L01_Write_Reg( FEATRUE, 0x07 );    NRF24L01_Read_Reg( DYNPD );    NRF24L01_Read_Reg( FEATRUE );
#elif DYNAMIC_PACKET == 0
    L01_WriteSingleReg( L01REG_RX_PW_P0, FIXED_PACKET_LEN );        //固定數(shù)據(jù)長度
#endif        //DYNAMIC_PACKET
    NRF24L01_Write_Reg( CONFIG,     /*( 1<<MASK_RX_DR ) |*/                //接收中斷*/                                      ( 1 << EN_CRC ) |     //使能CRC 1個字節(jié)                                      ( 1 << PWR_UP ) );    //開啟設(shè)備    NRF24L01_Write_Reg( EN_AA, ( 1 << ENAA_P0 ) );                   //通道0自動應(yīng)答    NRF24L01_Write_Reg( EN_RXADDR, ( 1 << ERX_P0 ) );                //通道0接收    NRF24L01_Write_Reg( SETUP_AW, AW_5BYTES );                             //地址寬度 5個字節(jié)    NRF24L01_Write_Reg( SETUP_RETR, ARD_4000US |                        ( REPEAT_CNT & 0x0F ) );                 //重復(fù)等待時間 250us    NRF24L01_Write_Reg( RF_CH, 00 );                                     //初始化通道    NRF24L01_Write_Reg( RF_SETUP, 0x26 );
    NRF24L01_Set_TxAddr( &addr[0], 5 );                      //設(shè)置TX地址    NRF24L01_Set_RxAddr( 0, &addr[0], 5 );                   //設(shè)置RX地址}

移植驗證

將發(fā)送端代碼燒入開發(fā)板,接收端代碼燒入另一個開發(fā)板。

main.c代碼如下:

/* * Change Logs: * Date           Author       Notes * 2024-06-21     LCKFB-LP    first version */#include "board.h"#include "stdio.h"#include "bsp_uart.h"#include "NRF24L01.h"#include "drv_spi.h"
#define RECEIVING_MODE        1 // 1:接收模式 0:發(fā)送模式
uint8_t g_RF24L01RxBuffer[30];
int32_t main(void){
        board_init();
        uart1_init(115200);
        //SPI初始化        drv_spi_init( );
        #if RECEIVING_MODE
        NRF24L01_Gpio_Init_receive( );        //檢測nRF24L01        NRF24L01_check( );        //NRF初始化        RF24L01_Init( );        RF24L01_Set_Mode( MODE_RX );//NRF接收模式        .        printf("MODE_RXrn");
        while(1)        {                if( 0 != g_RF24L01RxBuffer[0])                {                        printf("Data = %srn",g_RF24L01RxBuffer);                        Buff_Clear();                }        }
        #else
        NRF24L01_Gpio_Init_transmit( );        //檢測nRF24L01        NRF24L01_check( );        //NRF初始化        RF24L01_Init( );        RF24L01_Set_Mode( MODE_TX );//NRF發(fā)送模式        .        printf("MODE_TXrn");
        while(1)        {                NRF24L01_TxPacket((uint8_t*)"hello LCKFB!rn",13);//NRF發(fā)送數(shù)據(jù)                printf("Sendrn");                delay_ms(200);        }
        #endif}

上電現(xiàn)象:一個開發(fā)板燒錄接收模式的代碼,一個開發(fā)板燒錄發(fā)送模式的代碼。

模塊移植成功案例代碼:

鏈接:https://pan.baidu.com/s/1KReODFKFa4vjTN8qfsaNrQ?pwd=LCKF

提取碼:LCKF

相關(guān)推薦

登錄即可解鎖
  • 海量技術(shù)文章
  • 設(shè)計資源下載
  • 產(chǎn)業(yè)鏈客戶資源
  • 寫文章/發(fā)需求
立即登錄

以開放、共享、互助為理念,致力于構(gòu)建武漢芯源半導(dǎo)體CW32系列MCU生態(tài)社區(qū)。無論是嵌入式MCU小自還是想要攻破技術(shù)難題的工程師,亦或是需求解決方案的產(chǎn)品經(jīng)理都可在CW32生態(tài)社區(qū)汲取營養(yǎng)、共同成長。

B站