NRF24L01無線通訊模塊驅動


NRF24L01 無線模塊,采用的芯片是 NRF24L01,該芯片的主要特點如下:

12.4G 全球開放的 ISM 頻段,免許可證使用。

2)最高工作速率 2Mbps,高校的 GFSK 調制,抗干擾能力強。

3125 個可選的頻道,滿足多點通信和調頻通信的需要。

4)內置 CRC 檢錯和點對多點的通信地址控制。

5)低工作電壓(1.9~3.6V)。

6)可設置自動應答,確保數據可靠傳輸。

模塊引腳圖如下所示


模塊 VCC 腳的電壓范圍為 1.9~3.6V,建議不要超過 3.6V,否則可能燒壞模塊,一般用 3.3V

電壓比較合適。除了 VCC GND 腳,其他引腳都可以和 5V 單片機的 IO 口直連,正是因為其

兼容 5V 單片機的 IO,故使用上具有很大優勢

 

該芯片在接收模式下可以同時接收六個發送端信息,因為其內部有六個通道,發送模式下只能一個發

 

該芯片有兩種傳輸模式,第一個是無雙向鏈接的模式,也就是單向發送沒有ACK,第二種芯片自帶ACK模式,推薦用第二種,只要是使能動應答即可,並且,在第二種模式下,發送端的接收通道0用來作為ACK的接收通道,接收端的發送通道用來做ack的發送通道,設置地址時要注意這兩個地方地址應當相同

 

主要命令如下

 

寫寄存器命令只有在CE0處於待機狀態下時才有效,使用時應當注意這一點

 

具體去掉那個代碼如下

 

24l01.h

 

#ifndef __24L01_H
#define __24L01_H	 		  
#include "ioremap.h"   
#include "delay.h"
#include "spi.h"


//設備地址設置
#define ADDR1_VALUE	0X34
#define ADDR2_VALUE	0X43
#define ADDR3_VALUE	0X10
#define ADDR4_VALUE	0X10
#define ADDR5_VALUE	0X01


//////////////////////////////////////////////////////////////////////////////////////////////////////////
//NRF24L01寄存器操作命令
#define READ_REG_NRF    0x00  //讀配置寄存器,低5位為寄存器地址
#define WRITE_REG_NRF   0x20  //寫配置寄存器,低5位為寄存器地址
#define RD_RX_PLOAD     0x61  //讀RX有效數據,1~32字節,應用於接收模式下,讀取完成后自動清除FIFO
#define WR_TX_PLOAD     0xA0  //寫TX有效數據,1~32字節,應用於發射模式下
#define FLUSH_TX        0xE1  //清除TX FIFO寄存器.發射模式下用
#define FLUSH_RX        0xE2  //清除RX FIFO寄存器.接收模式下用,傳輸應答信號過程中用這個指令會讓應答數據不能完整傳輸
#define REUSE_TX_PL     0xE3  //重新使用上一包數據,CE為高,數據包被不斷發送.發射過程中必須禁止用這個功能
#define NOP             0xFF  //空操作,可以用來讀狀態寄存器	

//SPI(NRF24L01)寄存器地址
#define CONFIG          0x00  //配置寄存器地址;
//bit0:1接收模式,0發射模式;
//bit1:1上電 2掉電;
//bit2:CRC模式; 0八位CRC 1 16位CRC
//bit3:CRC使能;1使能 0不使能(若是使能自動應答,這一位必須為高)
//bit4 可屏蔽中斷 MAX_RT 1 屏蔽 0不屏蔽 發生中斷IRQ為低電平(最大重發中斷)
//bit5 可屏蔽中斷TX_DS 1屏蔽 0不 數據發送完成並收到應答
//bit6 可屏蔽中斷RX_DR 接收數據完成 1屏蔽 0不屏蔽
//bit7 默認為0

#define EN_AA           0x01  
//bit0~5,使能自動應答功能 (自動應答必然啟動CRC)對應通道0~5

#define EN_RXADDR       0x02  
//bit0~5,接收數據通道允許,對應通道0~5

#define SETUP_AW        0x03  
//bit1,0:設置地址寬度(所有數據通道) 01,3字節; 10,4字節; 11,5字節;(默認11)

#define SETUP_RETR      0x04  
//建立自動重發;
//bit3:0,自動重發計數器;0000 15次
//bit7:4,自動重發延時 0000 250*x+86us

#define RF_CH           0x05  
//RF通道,bit6:0,工作通道頻率

#define RF_SETUP        0x06  
//bit4: pll lock允許,僅用於測試模式,應當為1
//bit3: 傳輸速率(0:1Mbps,1:2Mbps);
//bit2:1,發射功率 11 0dbm;
//bit0:低噪聲放大器增益 


#define STATUS          0x07  
//bit0:TX FIFO滿標志;
//bit3:1,接收數據通道號(最大:6);接收到數據的通道號碼
//bit4,達到最多次重發 max_rt中斷
//bit5:數據發送完成中斷;寫1清除中斷
//bit6:接收數據中斷; 寫1清除中斷

#define OBSERVE_TX      0x08  //發送檢測寄存器,
//bit7:4,數據包丟失計數器;
//bit3:0,重發計數器

#define CD              0x09  //載波檢測寄存器,
//bit0,載波檢測;
							   
#define RX_ADDR_P0      0x0A  
//數據通道0接收地址,最大長度5個字節,低字節在前
#define RX_ADDR_P1      0x0B  
//數據通道1接收地址,最大長度5個字節,低字節在前
#define RX_ADDR_P2      0x0C  
//數據通道2接收地址,最低字節可設置,高字節,必須同RX_ADDR_P1[39:8]相等;
#define RX_ADDR_P3      0x0D  
//數據通道3接收地址,最低字節可設置,高字節,必須同RX_ADDR_P1[39:8]相等;
#define RX_ADDR_P4      0x0E  
//數據通道4接收地址,最低字節可設置,高字節,必須同RX_ADDR_P1[39:8]相等;
#define RX_ADDR_P5      0x0F  
//數據通道5接收地址,最低字節可設置,高字節,必須同RX_ADDR_P1[39:8]相等;

#define TX_ADDR         0x10  
//發送地址(低字節在前),ShockBurstTM模式下,RX_ADDR_P0與此地址相等
#define RX_PW_P0        0x11  
//接收數據通道0有效數據寬度(1~32字節),設置為0則非法
#define RX_PW_P1        0x12  
//接收數據通道1有效數據寬度(1~32字節),設置為0則非法
#define RX_PW_P2        0x13  
//接收數據通道2有效數據寬度(1~32字節),設置為0則非法
#define RX_PW_P3        0x14  
//接收數據通道3有效數據寬度(1~32字節),設置為0則非法
#define RX_PW_P4        0x15  
//接收數據通道4有效數據寬度(1~32字節),設置為0則非法
#define RX_PW_P5        0x16  
//接收數據通道5有效數據寬度(1~32字節),設置為0則非法

#define NRF_FIFO_STATUS 0x17  
//FIFO狀態寄存器;
//bit0,RX FIFO寄存器空標志;
//bit1,RX FIFO滿標志;
//bit2,3,保留
//bit4,TX FIFO空標志;
//bit5,TX FIFO滿標志;
//bit6,1,循環發送上一數據包.0,不循環;


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








//////////////////////////////////////////////////////////////////////////////////////////////////////////
//24L01操作線
#define NRF24L01_CE   PGout(6) //24L01片選信號
#define NRF24L01_CSN  PGout(7) //SPI片選信號	   
#define NRF24L01_IRQ  PGin(8)  //IRQ主機數據輸入


//24L01發送接收數據寬度定義
#define TX_ADR_WIDTH    5   	//5字節的地址寬度
#define RX_ADR_WIDTH    5   	//5字節的地址寬度

#define TX_PLOAD_WIDTH  32  	//32字節的用戶數據寬度
#define RX_PLOAD_WIDTH  32  	//32字節的用戶數據寬度
									   	   

void Nrf24l01Init(void);//初始化


void Nrf24l01RxMode(void);//配置為接收模式


void Nrf24l01TxMode(void);//配置為發送模式


u8 Nrf24l01WriteBuf(u8 reg, u8 *pBuf, u8 u8s);//寫數據區


u8 Nrf24l01ReadBuf(u8 reg, u8 *pBuf, u8 u8s);//讀數據區


u8 Nrf24l01ReadReg(u8 reg);			//讀寄存器


u8 Nrf24l01WriteReg(u8 reg, u8 value);//寫寄存器


u8 Nrf24l01Check(void);//檢查24L01是否存在


u8 Nrf24l01TxPacket(u8 *txbuf);//發送一個包的數據


u8 Nrf24l01RxPacket(u8 *rxbuf);//接收一個包的數據


#endif











24l01.c

 

 

#include "24l01.h"


const u8 TX_ADDRESS[TX_ADR_WIDTH]={ADDR1_VALUE,ADDR2_VALUE,ADDR3_VALUE,ADDR4_VALUE,ADDR5_VALUE}; //發送地址

const u8 RX_ADDRESS[RX_ADR_WIDTH]={ADDR1_VALUE,ADDR2_VALUE,ADDR3_VALUE,ADDR4_VALUE,ADDR5_VALUE}; //發送地址

//初始化24L01的IO口
void Nrf24l01Init(void)
{ 	
    GPIO_InitTypeDef GPIO_InitStructure;
    SPI_InitTypeDef  SPI_InitStructure;
    
    RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB|RCC_APB2Periph_GPIOD|RCC_APB2Periph_GPIOG, ENABLE);	 //使能PB,D,G端口時鍾
    
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12;				 //PB12上拉 防止W25X的干擾
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽輸出
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
    GPIO_Init(GPIOB, &GPIO_InitStructure);	//初始化指定IO
    GPIO_SetBits(GPIOB,GPIO_Pin_12);//上拉				
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;				 //PD2推挽輸出上拉   禁止SD卡的干擾
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; 		 //推挽輸出
    GPIO_SetBits(GPIOD,GPIO_Pin_2);//初始化指定IO
    
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6|GPIO_Pin_7;	//PG6 7 推挽 	  
    GPIO_Init(GPIOG, &GPIO_InitStructure);//初始化指定IO
    
    GPIO_InitStructure.GPIO_Pin  = GPIO_Pin_8;   
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPD; //PG8 輸入  
    GPIO_Init(GPIOG, &GPIO_InitStructure);
    
    GPIO_ResetBits(GPIOG,GPIO_Pin_6|GPIO_Pin_7|GPIO_Pin_8);//PG6,7,8上拉					 
    
    Spi2Init();    		//初始化SPI	 
    
    SPI_Cmd(SPI2, DISABLE); // SPI外設不使能
    
    SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex;  //SPI設置為雙線雙向全雙工
    SPI_InitStructure.SPI_Mode = SPI_Mode_Master;		//SPI主機
    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_16;		//定義波特率預分頻的值:波特率預分頻值為16
    SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;	//數據傳輸從MSB位開始
    SPI_InitStructure.SPI_CRCPolynomial = 7;	//CRC值計算的多項式
    SPI_Init(SPI2, &SPI_InitStructure);  //根據SPI_InitStruct中指定的參數初始化外設SPIx寄存器
    
    SPI_Cmd(SPI2, ENABLE); //使能SPI外設
    
    NRF24L01_CE=0; 			//使能24L01,初始化低電平進入待機模式
    NRF24L01_CSN=1;			//SPI片選取消  
    
}


//SPI寫寄存器
//reg:指定寄存器地址
//value:寫入的值
//每一個命令的執行都需要一次CSN由低到高的過程
u8 Nrf24l01WriteReg(u8 reg,u8 value)
{
    u8 status;	
    NRF24L01_CSN=0;                 //使能SPI傳輸
	NRF24L01_CE=0;					//待機模式才能進行寄存器寫入
    status =Spi2ReadWriteByte(WRITE_REG_NRF+reg);//發送寄存器號 +讀寄存器命令
    Spi2ReadWriteByte(value);      //寫入寄存器的值
    NRF24L01_CSN=1;                 //禁止SPI傳輸	   
    return(status);       			//返回狀態值
}


//讀取SPI寄存器值
//reg:要讀的寄存器
u8 Nrf24l01ReadReg(u8 reg)
{
    u8 reg_val;	    
    NRF24L01_CSN = 0;          //使能SPI傳輸		
    Spi2ReadWriteByte(READ_REG_NRF+reg);   //發送寄存器號+讀寄存器命令
    reg_val=Spi2ReadWriteByte(0XFF);//讀取寄存器內容
    NRF24L01_CSN = 1;          //禁止SPI傳輸		    
    return(reg_val);           //返回狀態值
}


//在指定位置讀出指定長度的數據
//reg:寄存器(位置)
//*pBuf:數據指針
//len:數據長度
//返回值,此次讀到的狀態寄存器值 
u8 Nrf24l01ReadBuf(u8 reg,u8 *pBuf,u8 len)
{
    u8 status,u8_ctr;	       
    NRF24L01_CSN = 0;           //使能SPI傳輸
    status=Spi2ReadWriteByte(reg);//發送寄存器值(位置),並讀取狀態值   	   
    for(u8_ctr=0;u8_ctr<len;u8_ctr++)pBuf[u8_ctr]=Spi2ReadWriteByte(0XFF);//讀出數據
    NRF24L01_CSN=1;       //關閉SPI傳輸
    return status;        //返回讀到的狀態值
}

//在指定位置寫指定長度的數據
//reg:寄存器(位置)
//*pBuf:數據指針
//len:數據長度
//返回值,此次讀到的狀態寄存器值
u8 Nrf24l01WriteBuf(u8 reg, u8 *pBuf, u8 len)
{
    u8 status,u8_ctr;	    
    NRF24L01_CSN = 0;          //使能SPI傳輸
    status = Spi2ReadWriteByte(reg);//發送寄存器值(位置),並讀取狀態值
    for(u8_ctr=0; u8_ctr<len; u8_ctr++)Spi2ReadWriteByte(*pBuf++); //寫入數據	 
    NRF24L01_CSN = 1;       //關閉SPI傳輸
    return status;          //返回讀到的狀態值
}

//檢測24L01是否存在
//返回值:0,成功;1,失敗
//通過地址檢測方式檢測24l01是否存在
u8 Nrf24l01Check(void)
{
    u8 buf[5]={0XA5,0XA5,0XA5,0XA5,0XA5};
    u8 i;
    Spi2SetSpeed(SPI_BaudRatePrescaler_4); //spi速度為9Mhz(24L01的最大SPI時鍾為10Mhz)   	 
    Nrf24l01WriteBuf(TX_ADDR,buf,5);//寫入5個字節的地址.	
    Nrf24l01ReadBuf(TX_ADDR,buf,5); //讀出寫入的地址  
    for(i=0;i<5;i++)if(buf[i]!=0XA5)break;	 							   
    if(i!=5)return 1;//檢測24L01錯誤	
    return 0;		 //檢測到24L01
}	 	
 
//該函數初始化NRF24L01到RX模式
//設置RX地址,寫RX數據寬度,選擇RF頻道,波特率和LNA HCURR
//當CE變高后,即進入RX模式,並可以接收數據了		   
void Nrf24l01RxMode(void)
{
    NRF24L01_CE=0;	  
    Nrf24l01WriteBuf(RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH);//寫RX節點地址,地址默認是五個字節
    
    Nrf24l01WriteReg(EN_AA,0x01);    //使能通道0的自動應答    
    Nrf24l01WriteReg(EN_RXADDR,0x01);//使能通道0的接收地址  	 
    Nrf24l01WriteReg(RF_CH,40);	     //設置RF通信頻率		  
    Nrf24l01WriteReg(RX_PW_P0,RX_PLOAD_WIDTH);//選擇通道0的有效數據寬度 	    
    Nrf24l01WriteReg(RF_SETUP,0x0f);//設置TX發射參數,0db增益,2Mbps,低噪聲增益開啟   
    Nrf24l01WriteReg(CONFIG, 0x0f);//配置基本工作模式的參數;PWR_UP,EN_CRC,16BIT_CRC,接收模式 
    NRF24L01_CE = 1; //CE為高,進入接收模式 
}	

//該函數初始化NRF24L01到TX模式
//設置TX地址,寫TX數據寬度,設置RX自動應答的地址,填充TX發送數據,選擇RF頻道,波特率和LNA HCURR
//PWR_UP,CRC使能
//當CE變高后,即進入RX模式,並可以接收數據了		   
//CE為高大於10us,則啟動發送.	 
void Nrf24l01TxMode(void)
{														 
    NRF24L01_CE=0;	    
    Nrf24l01WriteBuf(TX_ADDR,(u8*)TX_ADDRESS,TX_ADR_WIDTH);//寫TX節點地址 
    Nrf24l01WriteBuf(RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH); //設置TX節點地址,主要為了使能ACK,通道0作為自動ACK接收地址	  
    
    Nrf24l01WriteReg(EN_AA,0x01);     //使能通道0的自動應答    
    Nrf24l01WriteReg(EN_RXADDR,0x01); //使能通道0的接收地址  
    Nrf24l01WriteReg(SETUP_RETR,0x1a);//設置自動重發間隔時間:500us + 86us;最大自動重發次數:10次
    Nrf24l01WriteReg(RF_CH,40);       //設置RF通道為40
    Nrf24l01WriteReg(RF_SETUP,0x0f);  //設置TX發射參數,0db增益,2Mbps,低噪聲增益開啟   
    Nrf24l01WriteReg(CONFIG,0x0e);    //配置基本工作模式的參數;PWR_UP,EN_CRC,16BIT_CRC,接收模式,開啟所有中斷
    NRF24L01_CE=1;//CE為高,10us后啟動發送
}		

			   
//啟動NRF24L01發送一次數據
//txbuf:待發送數據首地址
//返回值:發送完成狀況
u8 Nrf24l01TxPacket(u8 *txbuf)
{
    u8 sta;
    Spi2SetSpeed(SPI_BaudRatePrescaler_8);//spi速度為9Mhz(24L01的最大SPI時鍾為10Mhz)   
    NRF24L01_CE=0;
    Nrf24l01WriteBuf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);//寫數據到TX BUF  32個字節
    NRF24L01_CE=1;//啟動發送	   
    while(NRF24L01_IRQ!=0);//等待發送完成
    sta=Nrf24l01ReadReg(STATUS);  //讀取狀態寄存器的值	   
    Nrf24l01WriteReg(STATUS,sta); //清除TX_DS或MAX_RT中斷標志
    if(sta&MAX_TX)//達到最大重發次數
    {
        Nrf24l01WriteReg(FLUSH_TX,0xff);//清除TX FIFO寄存器 
        return MAX_TX; 
    }
    if(sta&TX_OK)//發送完成
    {
        return TX_OK;
    }
    return 0xff;//其他原因發送失敗
}

//檢測接收狀態,為1則有數據
u8 Nrf24l01CheckRxBuffer(void)
{
	u8 sta;		  
	sta=Nrf24l01ReadReg(STATUS);  //讀取狀態寄存器的值
	if(sta&RX_OK)return 1;//接收到數據
	else return 0;
}

//啟動NRF24L01發送一次數據
//txbuf:待發送數據首地址
//返回值:0,接收完成;其他,錯誤代碼
u8 Nrf24l01RxPacket(u8 *rxbuf)
{
    u8 sta;		    							   
    Spi2SetSpeed(SPI_BaudRatePrescaler_8); //spi速度為9Mhz(24L01的最大SPI時鍾為10Mhz)   
    sta=Nrf24l01ReadReg(STATUS);  //讀取狀態寄存器的值    	 
    Nrf24l01WriteReg(STATUS,sta); //清除TX_DS或MAX_RT中斷標志
    if(sta&RX_OK)//接收到數據
    {
        Nrf24l01ReadBuf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//讀取數據
        Nrf24l01WriteReg(FLUSH_RX,0xff);//清除RX FIFO寄存器 
        return 0; 
    }	   
    return 1;//沒收到任何數據
}	

				    


					 
	  




 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM