STM32+NRF24L01收發程序

硬件平臺:STM32F103+NRF24L01

nrf24l01.h

#ifndef __NRF24L01_H
#define __NRF24L01_H

extern Uchar nrfFlag;
//////////////////////////////////////////////////////////////////////////////////////////////////////////
//*********************************************NRF24L01*************************************
extern Uchar nrfWorkState;
extern Uchar g_rf_status;
extern Uchar g_rf_rx_buf[0x30];
//#define RX_DR g_rf_status^6
//#define TX_DS g_rf_status^5
//#define MAX_RT    g_rf_status^4
#define RX_DR   (g_rf_status&0x40)
#define TX_DS   (g_rf_status&0x20)
#define MAX_RT  (g_rf_status&0x10)
//24L01發送接收數據寬度定義
#define TX_ADR_WIDTH    5       //5字節的地址寬度
#define RX_ADR_WIDTH    5       //5字節的地址寬度
#define TX_PLOAD_WIDTH  6   //32字節的用戶數據寬度
#define RX_PLOAD_WIDTH  6   //32字節的用戶數據寬度

//Uchar const TX_ADDRESS[TX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //本地地址
//Uchar const RX_ADDRESS[RX_ADR_WIDTH]= {0x34,0x43,0x10,0x10,0x01}; //接收地址
//***************************************NRF24L01寄存器指令*******************************************************
#define READ_REG_NRF        0x00  //讀配置寄存器,低5位爲寄存器地址
#define WRITE_REG_NRF       0x20  //寫配置寄存器,低5位爲寄存器地址
#define RD_RX_PLOAD     0x61    // 讀取接收數據指令
#define WR_TX_PLOAD     0xA0    // 寫待發數據指令
#define FLUSH_TX        0xE1    // 沖洗發送 FIFO指令
#define FLUSH_RX        0xE2    // 沖洗接收 FIFO指令
#define REUSE_TX_PL     0xE3    // 定義重複裝載數據指令
#define NOP             0xFF    // 保留
//*************************************SPI(nRF24L01)寄存器地址****************************************************
#define CONFIG          0x00  // 配置收發狀態,CRC校驗模式以及收發狀態響應方式
#define EN_AA           0x01  // 自動應答功能設置
#define EN_RXADDR       0x02  // 可用信道設置
#define SETUP_AW        0x03  // 收發地址寬度設置
#define SETUP_RETR      0x04  // 自動重發功能設置
#define RF_CH           0x05  // 工作頻率設置
#define RF_SETUP        0x06  // 發射速率、功耗功能設置
#define STATUS          0x07  // 狀態寄存器

#define MAX_TX          0x10  //達到最大發送次數中斷
#define TX_OK           0x20  //TX發送完成中斷
#define RX_OK           0x40  //接收到數據中斷

#define OBSERVE_TX      0x08  // 發送監測功能
#define CD              0x09  // 地址檢測
#define RX_ADDR_P0      0x0A  // 頻道0接收數據地址
#define RX_ADDR_P1      0x0B  // 頻道1接收數據地址
#define RX_ADDR_P2      0x0C  // 頻道2接收數據地址
#define RX_ADDR_P3      0x0D  // 頻道3接收數據地址
#define RX_ADDR_P4      0x0E  // 頻道4接收數據地址
#define RX_ADDR_P5      0x0F  // 頻道5接收數據地址
#define TX_ADDR         0x10  // 發送地址寄存器
#define RX_PW_P0        0x11  // 接收頻道0接收數據長度
#define RX_PW_P1        0x12  // 接收頻道0接收數據長度
#define RX_PW_P2        0x13  // 接收頻道0接收數據長度
#define RX_PW_P3        0x14  // 接收頻道0接收數據長度
#define RX_PW_P4        0x15  // 接收頻道0接收數據長度
#define RX_PW_P5        0x16  // 接收頻道0接收數據長度
#define FIFO_STATUS     0x17  // FIFO棧入棧出狀態寄存器設置
//**************************************************************************************
//////////////////////////////////////////////////////////////////////////////////////////////////////////

extern void NRF_IRQ_Init(void);
extern void NRF24L01_Init(void);//初始化
extern void NRF24L01_RX_Mode(void);//配置爲接收模式
extern void NRF24L01_TX_Mode(void);//配置爲發送模式
extern Uchar NRF24L01_Write_Buf(Uchar reg, Uchar *pBuf, Uchar Uchars);//寫數據區
extern Uchar NRF24L01_Read_Buf(Uchar reg, Uchar *pBuf, Uchar Uchars);//讀數據區
extern Uchar NRF24L01_Read_Reg(Uchar reg);          //讀寄存器
extern Uchar NRF24L01_Write_Reg(Uchar reg, Uchar value);//寫寄存器
extern Uchar NRF24L01_Check(void);//檢查24L01是否存在
extern Uchar NRF24L01_TxPacket(Uchar *txbuf);//發送一個包的數據
extern Uchar NRF24L01_RxPacket(Uchar *rxbuf);//接收一個包的數據
extern void NRF24L01_CheckRecvData(void);
#endif

nrf24l01.c

Uchar nrfFlag;
Uchar nrfWorkState;
Uchar g_rf_status;                                                              // RF狀態寄存器的值
Uchar g_rf_rx_buf[0x30];

Uchar TX_ADDRESS[TX_ADR_WIDTH]={0x01,0x02,0x03,0x04,0xA5};      // 定義RF接收應用地址
Uchar RX_ADDRESS[TX_ADR_WIDTH]= {0x01,0x02,0x03,0x04,0xA6};         // 定義RF發送工廠地址
Uchar RX_ADDRESS_APP[TX_ADR_WIDTH]= {0x01,0x02,0x03,0x04,0xA6};         // 定義RF接收工廠地址

//SPI寫寄存器
//reg:指定寄存器地址
//value:寫入的值
extern Uchar NRF24L01_Write_Reg(Uchar reg,Uchar value)
{
    Uchar status;
    SPISemGet();
    //NRF24L01_CSN=0;                 //使能SPI傳輸
    NRF24L01_CSN_Low();
    status =SPI_FLASH_SendByte(reg);//發送寄存器號
    SPI_FLASH_SendByte(value);      //寫入寄存器的值
    //NRF24L01_CSN=1;                 //禁止SPI傳輸
    NRF24L01_CSN_High();
    SPISemPut();
    return(status);                 //返回狀態值
}
//讀取SPI寄存器值
//reg:要讀的寄存器
extern Uchar NRF24L01_Read_Reg(Uchar reg)
{
    Uchar reg_val;
    SPISemGet();         
    NRF24L01_CSN_Low();  //使能SPI傳輸
    SPI_FLASH_SendByte(reg);   //發送寄存器號
    reg_val=SPI_FLASH_SendByte(0XFF);//讀取寄存器內容
    NRF24L01_CSN_High();  //禁止SPI傳輸
    SPISemPut();
    return(reg_val);           //返回狀態值
}
//在指定位置讀出指定長度的數據
//reg:寄存器(位置)
//*pBuf:數據指針
//len:數據長度
//返回值,此次讀到的狀態寄存器值
extern Uchar NRF24L01_Read_Buf(Uchar reg,Uchar *pBuf,Uchar len)
{
    Uchar status,Uchar_ctr;
    NRF24L01_CSN_Low();  //使能SPI傳輸
    status=SPI_FLASH_SendByte(reg);//發送寄存器值(位置),並讀取狀態值
    for(Uchar_ctr=0;Uchar_ctr<len;Uchar_ctr++)pBuf[Uchar_ctr]=SPI_FLASH_SendByte(0XFF);//讀出數據
    //NRF24L01_CSN=1;       //關閉SPI傳輸
    NRF24L01_CSN_High();
    return status;        //返回讀到的狀態值
}
//在指定位置寫指定長度的數據
//reg:寄存器(位置)
//*pBuf:數據指針
//len:數據長度
//返回值,此次讀到的狀態寄存器值
extern Uchar NRF24L01_Write_Buf(Uchar reg, Uchar *pBuf, Uchar len)
{
    Uchar status,Uchar_ctr;

    NRF24L01_CSN_Low(); //使能SPI傳輸
    status = SPI_FLASH_SendByte(reg);//發送寄存器值(位置),並讀取狀態值
    for(Uchar_ctr=0; Uchar_ctr<len; Uchar_ctr++)SPI_FLASH_SendByte(*pBuf++); //寫入數據

    NRF24L01_CSN_High();   //關閉SPI傳輸

    return status;          //返回讀到的狀態值
}


//檢測24L01是否存在
//返回值:0,成功;1,失敗
extern Uchar NRF24L01_Check(void)
{
    Uchar buf[TX_ADR_WIDTH];

    //NRF24L01_Write_Buf(WRITE_REG_NRF+TX_ADDR,TX_ADDRESS,TX_ADR_WIDTH);//寫入5個字節的地址.
#ifdef  NRF_MODE_SEND
    NRF24L01_Read_Buf(TX_ADDR,buf,5); //讀出寫入的地址
#else
    NRF24L01_Read_Buf(RX_ADDR_P0,buf,5); //讀出寫入的地址
#endif
//  DEBUGBUFFER("NRF24L01_Check", buf, 5);
#ifdef  NRF_MODE_SEND
    if (Buffercmp(TX_ADDRESS, buf, RX_ADR_WIDTH) == PASSED)
#else
    if (Buffercmp(RX_ADDRESS, buf, RX_ADR_WIDTH) == PASSED)
#endif
    {
        nrfWorkState = 1;
        return 1;//檢測24L01錯誤
    }

    nrfWorkState = 0;
    return 0;        //檢測到24L01
}

//啓動NRF24L01發送一次數據
//txbuf:待發送數據首地址
//返回值:發送完成狀況
extern Uchar NRF24L01_TxPacket(Uchar *txbuf)
{
    NRF24L01_Write_Reg(FLUSH_TX,0); // 清除TX的FIFO
    NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);//寫數據到TX BUF  32個字節

    return 0;//其他原因發送失敗
}
//啓動NRF24L01發送一次數據
//txbuf:待發送數據首地址
//返回值:0,接收完成;其他,錯誤代碼
extern Uchar NRF24L01_RxPacket(Uchar *rxbuf)
{
    Uchar state = 0;

    state=NRF24L01_Read_Reg(STATUS);  //讀取狀態寄存器的值
    NRF24L01_Write_Reg(WRITE_REG_NRF+STATUS,state); //清除TX_DS或MAX_RT中斷標誌

    if(state&RX_OK)//接收到數據
    {
        NRF24L01_Read_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//讀取數據
        NRF24L01_Write_Reg(FLUSH_RX,0xff);//清除RX FIFO寄存器
        return 0;
    }

    return 1;//沒收到任何數據
}
//該函數初始化NRF24L01到RX模式
//設置RX地址,寫RX數據寬度,選擇RF頻道,波特率和LNA HCURR
//當CE變高後,即進入RX模式,並可以接收數據了
extern void NRF24L01_RX_Mode(void)
{
    NRF24L01_CE_Low();
    NRF24L01_Write_Reg(WRITE_REG_NRF + CONFIG, 0x0f);       // 上電, CRC爲2 bytes,接收模式,允許RX_DR產生中斷
    NRF24L01_CE_High();
}
//該函數初始化NRF24L01到TX模式
//設置TX地址,寫TX數據寬度,設置RX自動應答的地址,填充TX發送數據,選擇RF頻道,波特率和LNA HCURR
//PWR_UP,CRC使能
//當CE變高後,即進入RX模式,並可以接收數據了
//CE爲高大於10us,則啓動發送.
extern void NRF24L01_TX_Mode(void)
{
    NRF24L01_CE_Low();
    //設置接收包數據長度
    NRF24L01_Write_Reg(WRITE_REG_NRF + RX_PW_P0, TX_PLOAD_WIDTH);   // PIPE0 接收數據包長度
    NRF24L01_Write_Reg(WRITE_REG_NRF+CONFIG,0x0e);    //配置基本工作模式的參數;PWR_UP,EN_CRC,16BIT_CRC,接收模式,開啓所有中斷
    NRF24L01_CE_High();
}

extern void NRF24L01_CheckRecvData(void)
{
    Uchar buf[0x40];

    if(NRF24L01_RxPacket(buf)==0)//一旦接收到信息,則顯示出來.
    {
        DEBUGBUFFER("NRF24L01 RECV", buf, 32);
    }
}


//初始化24L01的IO口
extern void NRF24L01_Init(void)
{
#ifdef NRF_MODE_SEND
    GPIO_InitTypeDef GPIO_InitStructure;

    GPIO_InitStructure.GPIO_Pin  = PIN_NRF24L01_IRQ;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //IRQ 輸入
    GPIO_Init(PORT_NRF24L01_IRQ, &GPIO_InitStructure);
#else
    NRF_IRQ_Init();
#endif
    //NRF24L01_CE=0;            //使能24L01
//  NRF24L01_CSN=1;         //SPI片選取消
    NRF24L01_CE_Low();
    NRF24L01_CSN_High();

    NRF24L01_Write_Buf(WRITE_REG_NRF + TX_ADDR, TX_ADDRESS, TX_ADR_WIDTH);  // 設置發射地址及長度
    NRF24L01_Write_Buf(WRITE_REG_NRF + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH);   // 設置接收地址及長度
    NRF24L01_Write_Buf(WRITE_REG_NRF + RX_ADDR_P1, RX_ADDRESS_APP, RX_ADR_WIDTH);   // 設置接收地址及長度


    //SPI_Write_Reg(WRITE_REG + EN_AA, 0x01);                           // 啓動自動應答功能
    NRF24L01_Write_Reg(WRITE_REG_NRF+ EN_AA, 0x00);                             // 關閉自動應答功能

    //SPI_Write_Reg(WRITE_REG + EN_RXADDR, 0x01);                       // PIPE0接收數據
    NRF24L01_Write_Reg(WRITE_REG_NRF + EN_RXADDR, 0x03);                        // PIPE0,PIPE1接收數據

    //SPI_Write_Reg(WRITE_REG + SETUP_RETR, 0x1a);                      // 自動重傳10次
    NRF24L01_Write_Reg(WRITE_REG_NRF + SETUP_RETR, 0x00);                       // 禁止重傳

    NRF24L01_Write_Reg(WRITE_REG_NRF + RF_CH, 40);                              // RF頻率2440MHz
    //SPI_Write_Reg(WRITE_REG + RF_SETUP, 0x0f);                        // 發射功率0dBm, 傳輸速率2Mbps,
    NRF24L01_Write_Reg(WRITE_REG_NRF + RF_SETUP, 0x27);                         // 發射功率0dBm, 傳輸速率250kbps,

    NRF24L01_Write_Reg(WRITE_REG_NRF + RX_PW_P0, TX_PLOAD_WIDTH);               // PIPE0 接收數據包長度
    NRF24L01_Write_Reg(WRITE_REG_NRF + RX_PW_P1, TX_PLOAD_WIDTH);               // PIPE1 接收數據包長度

}

extern void NRF_IRQ_Init(void)
{
    EXTI_InitTypeDef EXTI_InitStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    /* Connect EXTI Line to GPIO Pin */
    GPIO_EXTILineConfig(PORT_SRC_NRF_IRQ, PIN_SRC_NRF_IRQ);

    /* Configure EXTI line */
    EXTI_InitStructure.EXTI_Line = EXTI_LINE_NRF_IRQ;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Falling;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);

    /* Enable and set EXTI Interrupt to the highest priority */
    NVIC_InitStructure.NVIC_IRQChannel = EXIT_IRQN_NRF_IRQ;
    NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0x00;
    NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0x00;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);
    EXTI_ClearITPendingBit(EXTI_LINE_NRF_IRQ);
//  EXTI_GenerateSWInterrupt(EXTI_LINE_PFO);    // test
}

extern void EXTI1_IRQHandler(void)
{
    if(EXTI_GetITStatus(EXTI_LINE_NRF_IRQ) != RESET)
    {
        EXTI_ClearITPendingBit(EXTI_LINE_NRF_IRQ);
        if (!nrfFlag)
        {
            nrfFlag = 1;
        }

        g_rf_status=NRF24L01_Read_Reg(STATUS);                                  // 讀出狀態值

        if(RX_DR){
            NRF24L01_Read_Buf(RD_RX_PLOAD,g_rf_rx_buf,RX_PLOAD_WIDTH);          // 讀出FIFO的數據
            NRF24L01_Write_Reg(FLUSH_RX,0);                                     // 清除RX的FIFO
        }

        NRF24L01_Write_Reg(WRITE_REG_NRF+STATUS,0x70);                              // 清除所有中斷標誌

    }
}

1.做主機時初始化相關流程

NRF24L01_Init();
NRF24L01_TX_Mode();

發送數據

u8 recvData[TX_PLOAD_WIDTH]={數據};
NRF24L01_TxPacket(recvData); 

2.做從機時初始化相關流程

NRF24L01_Init();
NRF24L01_RX_Mode();

每收到一次有效數據發生一次中斷

g_rf_status=NRF24L01_Read_Reg(STATUS);                                  // 讀出狀態值

        if(RX_DR){
            NRF24L01_Read_Buf(RD_RX_PLOAD,g_rf_rx_buf,RX_PLOAD_WIDTH);          // 讀出FIFO的數據
            NRF24L01_Write_Reg(FLUSH_RX,0);                                     // 清除RX的FIFO
            //DEBUGBUFFER("NRF", g_rf_rx_buf, TX_PLOAD_WIDTH);
        }

        NRF24L01_Write_Reg(WRITE_REG_NRF+STATUS,0x70);  
發佈了36 篇原創文章 · 獲贊 23 · 訪問量 12萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章