STM32驅動NRF24L01

一、NRF24L01的相關介紹

1.2 引腳的介紹

關于SPI的引腳就不再說了,這里介紹其余的兩個引腳:

????????CE 模塊控制引腳:芯片開啟信號,激活RX或TX模式

????????IRQ 模塊中斷信號輸出引腳:其低電平有效,也就是中斷時變為低電平,要使用中斷時就設置為上拉輸入。。我們也可以屏蔽中斷信號,直接將這個引腳設置為下拉輸入。在以下三種情況變低:

????????????????????????Tx FIFO 發完并且收到ACK(使能ACK情況下)

????????????????????????Rx FIFO 收到數據

????????????????????????達到最大重發次數

1.3 NRF工作模式的介紹

????????NRF24L01的工作模式,由CECONFIG寄存器(0X00)PWR_UP(第1位)和PRIM_RX(第0位)位共同控制。

NRF24L01所處模式

PWR_UP位狀態

PRIM_RX 位狀態

CEFIFO 寄存器狀態
關斷模式 Shutdown0---
待機模式? Standby1-0無數據傳輸
發射空閑模式 Idle-TX101TX FIFO為空
發射模式? TX101

????????????????? 數據在TX FIFO寄存器中

????????????????停留在發送模式,直至發送完成

接收模式? RX111-

1.3.1?Shutdown 關斷工作模式

????????在Shutdown 工作模式下,Si24R1所有收發功能模塊關閉,芯片停止工作,消耗電流最小,但所有內部寄存器值和FIFO值保持不變,仍可通過SPI實現對寄存器的讀寫。 設置CONFIG寄存器的PWR_UP位的值為0,芯片立即返回到Shutdown工作模式。

1.3.2?Standby 待機工作模式

?????????在Standby 工作模式,只有晶體振蕩器電路工作,保證了芯片在消耗較少電流的同 時能夠快速啟動。設置CONFIG寄存器下的PWR_UP位的值為1,芯片待時鐘穩定后 進入Standby 模式。芯片的時鐘穩定時間一般為1.5~2ms,與晶振的性能有關。當引腳 CE=1 時,芯片將由Standby 模式進入到 Idle-TX 或 RX 模式,當 CE=0 時,芯片將由 Idle-TX、TX 或 RX模式返回到Standby模式。

1.3.3?Idle-TX 發射空閑工作模式

????????在Idle-TX 工作模式下,晶體振蕩器電路及時鐘電路工作。相比于Standby模式, 芯片消耗更多的電流。當發送端TX FIFO寄存器為空,并且引腳CE=1時,芯片進入到 Idle-TX 模式。在該模式下,如果有新的數據包被送到TX FIFO中,芯片內部的電路將 立即啟動,切換到TX模式將數據包發送。

???????? 在Standby 和 Idle-TX 工作模式下,所有內部寄存器值和 FIFO 值保持不變,仍可 通過SPI實現對寄存器的讀寫。

1.3.4?TX 發射工作模式

????????當需要發送數據時,需要切換到TX工作模式。芯片進入到TX工作模式的條件為: TX FIFO 中有數據, CONFIG寄存器的PWR_UP位的值為1,PRIM_RX位的值為0, 同時要求引腳CE上有一個至少持續10us的高脈沖。Idle-TX模式切換到TX模式的時 間為 120us~130us 之間,但不會超過 130us。單包數據發送完成后,如果 CE=1, 則由 TX FIFO的狀態來決定芯片所處的工作模式,當TX FIFO還有數據,芯片繼續保持在 TX工作模式,并發送下一包數據;當TX FIFO沒有數據,芯片返回Idle-TX模式;如 果CE=0,立即返回Standby模式。數據發射完成后,芯片產生數據發射完成中斷。

1.3.5 RX接收工作模式

????????當需要接收數據時,需要切換到RX工作模式。芯片進入到RX工作模式的條件為: 設置寄存器CONFIG的PWR_UP位的值為1,PRIM_RX位的值為1,并且引腳CE=1。 芯片由Standby 模式切換到RX模式的時間為120~130us。當接收到數據包的地址與芯片的地址相同,并且CRC檢查正確時,數據會自動存入RX FIFO,并產生數據接收中 斷。芯片最多可以同時存三個有效數據包,當FIFO已滿,接收到的數據包被自動丟掉。

二、NRF24L01的初始化

首先是關于引腳的初始化,至于SPI時序這里就不多介紹了,可以看這篇文章協議篇之SPI通信(軟件篇),而本篇文章就是基于這篇文章寫的。至于是使用SPI的哪個模式可以看手冊,這里我截取出來了:其中空閑時SCK為低電平,第一個邊沿采樣,所以使用模式0。

void NRF24L01_Init(void)
{/***** NRF的GPIO初始化 *****/GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	 //使能PB端口時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	 //使能PA端口時鐘GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Pin = NRF_CE_PIN;	//推挽 (配置CE)	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化指定IOGPIO_InitStructure.GPIO_Pin  = NRF_IRQ_PIN;//配置IRQGPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //PB15 上拉輸入  GPIO_Init(GPIOA,&GPIO_InitStructure);my_spi_init();NRF_CE(0); 			//使能24L01SPI_NSS(1);			//SPI片選取消
}

NRF24L01的通信條件:

1.? ?發射接收頻道相同(設置頻道寄存器RF_CH? 0-125);

2.? ?發射接收地址相同(設置TX_ADDR和RX_ADDR_P0相同? 5個8位地址);

3.? ?發射接收數據寬度相等( n<=32);

4.? ?發射接收速率相同(250k 1M 2M);

三、NRF的命令以及寄存器

3.1? NRF的命令

????????要實現對NRF的讀寫操作,就需要將命令以及寄存器地址結合起來使用,來實現對寄存器的操作,命令如下:

/*************************  NRF24L01寄存器操作命令  *************************/
#define NRF_READ_REG    0x00  //讀配置寄存器,低5位為寄存器地址
#define NRF_WRITE_REG   0x20  //寫配置寄存器,低5位為寄存器地址
#define RD_RX_PLOAD     0x61  //讀RX有效數據,1~32字節
#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  //空操作,可以用來讀狀態寄存器	 

3.2? NRF的寄存器

3.2.1?配置寄存器CONFIG0X00

3.2.2?自動應答使能寄存器EN_AA,0X01)

3.2.3?RX地址使能寄存器EN_RXADDR,0X02)

3.2.4?自動重發設置寄存器SETUP_RETR0X04

3.2.5?射頻頻率設置寄存器RF_CH,0X05)

頻率計算公式:2400+RF_CH? (Mhz)

3.2.6?射頻配置寄存器RF_SETUP,0X06)

3.2.7?狀態寄存器STATUS0X07

3.2.8?數據通道接收地址寄存器(RX_ADDR_P0~P5,0X0A~0X0F)

3.2.9?發送地址設置寄存器TX_ADDR,0X10)

3.2.10?接收通道有效數據寬度設置寄存器(RX_PW_P0~P5,0X11~0X16)

類似的,其他通道方法同RX_PW_P0。

四、NRF的檢查

????????時序以及初始化搞好了,那么如何檢測時序以及NRF是否正確呢?別的芯片一般可以通過讀ID來判斷,那么這個芯片的方法是往可讀可寫寄存器寫數據然后讀里面的數據是否正確。我們往發送通道寫5個字節的數據,然后挨個讀取內容,內容一致就說明檢測正確,否則失敗。

uint8_t NRF24L01_Check(void)
{u8 buf[5] = { 0x01,0x01,0x01,0x01,0x01 };u8 i;?MySPI_WriteLen(NRF_WRITE_REG+TX_ADDR,buf,5);//寫入5個字節的地址MySPI_ReadLen(TX_ADDR,buf,5); //讀出寫入的地址for(i=0;i<5;i++)if(buf[i]!=0x01)break;if(i!=5)return 1;//檢測24L01錯誤return 0;?? ??? ? //檢測到24L01
}

五、設置NRF為發送模式發送數據

? ? ? ? 在對NRF寄存器進行讀寫操作時,我們需要更改其工作模式,手冊里面有提到這句話:

注:只能在Shutdown、Standby和Idle-TX模式下才能對寄存器進行配置。

5.1 設置NRF為發射模式

? ? ? ? 由于對寄存器配置時不能為發射或者接收模式,所以我們先將CE置低位使其工作模式更改為待機模式,然后按照下列流程來配置NRF:????????

設置為發送模式的流程:

????????1)寫Tx 節點的地址 TX_ADDR

????????2)寫Rx 節點的地址(主要是為了使能Auto AckRX_ADDR_P0

????????3)使能AUTO ACK EN_AA

????????4)使能PIPE 0 EN_RXADDR

????????5)配置自動重發次數 SETUP_RETR

????????6)選擇通信頻率 RF_CH

????????7)配置發射參數(低噪放大器增益、發射功率、無線速率) RF_SETUP

????????8)配置24L01 的基本參數以及切換工作模式 CONFIG

????????首先是寫Tx節點地址,我們定義有關數組,存放五個字節的數據(TX_ADDR長度有40位,看上面關于他的介紹)利用寫寄存器命令和TX_ADDR寄存器地址將這五個字節的地址寫入。

? ? ? ? 第二步是寫Rx節點地址,主要是為了使能自動應答,其地址和Tx節點地址相同,可以看關于Ack模式的介紹有這么一段話“接收端在發送ACK信號時,取接收管道地址作為目標地址來發送ACK信號,所 以發送端需要設置接收管道0地址與自身發送地址相同,以便接收ACK信號

? ? ? ? 第三步是配置使能自動應答寄存器,我們使能數據管道0自動確認,所以寫入0x01;具體為什么這么配置可以看上文3.2.2關于這個寄存器的介紹。

????????第四步是配置使能接收數據管道地址,由于我們發射端需要接收Ack信號,所以我們要使能數據管道0,寫入0x01。

? ? ? ? 第五步是設置自動重發間隔時間以及最大自動重發次數,低四位由于配置自動重發計數,高四位用于配置自動重發延時,可以看3.2.4關于這個寄存器的介紹。我這里配置為0x1a,設置自動重發間隔時間:500us + 86us;最大自動重發次數:10次。

? ? ? ? 第六步是設置通信頻率,其值可以為0-125,見3.2.5;我這里寫入40,也就是2440MHz。

? ? ? ? 第七步是配置發射參數,可以根據寄存器的介紹自己去配置。

? ? ? ? 第八步是配置基本參數以及切換工作模式,見寄存器的描述,這里代碼如下:

/***** 將NRF設置位發送模式 *****/
void NRF24L01_TX_Mode(void)
{NRF_CE(0);//將CE置低配置為待機模式才能對寄存器進行配置MySPI_WriteLen(NRF_WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS,TX_ADR_WIDTH);//寫TX節點地址MySPI_WriteLen(NRF_WRITE_REG+RX_ADDR_P0,(u8*)TX_ADDRESS,RX_ADR_WIDTH);//設置RX節點地址,主要為了使能ACKMySPI_WriteByte(NRF_WRITE_REG+EN_AA,0x01);//使能通道0的自動應答MySPI_WriteByte(NRF_WRITE_REG+EN_RXADDR,0x01);//使能通道0的自動應答MySPI_WriteByte(NRF_WRITE_REG+SETUP_RETR,0x1a);//設置自動重發間隔時間:500us + 86us;最大自動重發次數:10次MySPI_WriteByte(NRF_WRITE_REG+RF_CH,40);       //設置RF通道為40MySPI_WriteByte(NRF_WRITE_REG+RF_SETUP,0x0f);  //設置TX發射參數,0db增益,2Mbps,低噪聲增益開啟MySPI_WriteByte(NRF_WRITE_REG+CONFIG,0x0e);    //配置基本工作模式的參數;PWR_UP,EN_CRC,16BIT_CRC,接收模式,開啟所有中斷NRF_CE(1);//CE為高,10us后啟動發送
}

5.2? NRF發送數據

? ? ? ? 要想啟動NRF發送數據,我們先將CE拉低進入待機模式才能配置寄存器,利用寫函數加寫發射負載數據命令寫入要發送的數據,注意這個數據大小為1-32字節。然后我們啟動發送,將NRF的CE腳拉高進入發射模式,然后讀IQR引腳判斷是否發送完成(Tx FIFO發完并收到Ack變為低電平)。然后我們讀取狀態寄存器,其值代表的狀態可以看寄存器介紹的3.2.7,首先判斷是否到達最大重發次數,其中MAX_TX為0x10,而狀態寄存器第四位就是達到最大重發次數中斷位,其判斷發送完成原理也是如此。

/***********************************************************
函數名稱:NRF24L01_TxPacket(u8 *txbuf)
函數功能:啟動NRF24L01發送一次數據
入口參數:txbuf  待發送的數據首地址
返回參數:返回值:TX_OK,接收完成,0xff,錯誤代碼
************************************************************/
u8 NRF24L01_TxPacket(u8 *txbuf)
{u8 sta;NRF_CE(0);MySPI_WriteLen(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);//寫數據到TX BUF  32個字節NRF_CE(1);//啟動發送while(READ_IRQ!=0);//等待發送完成sta=MySPI_ReadByte(STATUS);  //讀取狀態寄存器的值	   MySPI_WriteByte(NRF_WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中斷標志if(sta&MAX_TX)//達到最大重發次數{MySPI_WriteByte(FLUSH_TX,0xff);//清除TX FIFO寄存器 return MAX_TX; }if(sta&TX_OK)//發送完成{return TX_OK;}return 0xff;//其他原因發送失敗    
}

六、設置NRF為接收模式并接收數據

6.1 設置NRF為接收模式

????????其流程如下,和發送模式配置原理類似,可以參考發送模式,這里不再介紹。但是需要注意的就是配置要和發送模式相同,否則會導致通信不上。

設置為發送模式的流程:

????????1)寫Rx 節點的地址 RX_ADDR_P0

????????2)使能AUTO ACK EN_AA

????????3)使能PIPE 0 EN_RXADDR

????????4)選擇通信頻率 RF_CH

????????5)選擇通道0 有效數據寬度 RX_PW_P0

????????6)配置發射參數(低噪放大器增益、發射功率、無線速率) RF_SETUP

????????7)配置24L01 的基本參數以及切換工作模式 CONFIG。

/***** 將NRF設置為接收模式 *****/
void NRF24L01_RX_Mode(void)
{NRF_CE(0);	 MySPI_WriteLen(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH);//設置RX節點地址MySPI_WriteByte(NRF_WRITE_REG+EN_AA,0x01);//使能通道0的自動應答MySPI_WriteByte(NRF_WRITE_REG+EN_RXADDR,0x01);//使能通道0的自動應答MySPI_WriteByte(NRF_WRITE_REG+RF_CH,40);       //設置RF通道為40MySPI_WriteByte(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//選擇通道0的有效數據寬度 MySPI_WriteByte(NRF_WRITE_REG+RF_SETUP,0x0f);  //設置TX發射參數,0db增益,2Mbps,低噪聲增益開啟MySPI_WriteByte(NRF_WRITE_REG+CONFIG,0x0f);    //配置基本工作模式的參數;PWR_UP,EN_CRC,16BIT_CRC,接收模式,開啟所有中斷NRF_CE(1);//CE為高,10us后啟動發送
}

6.2 接收數據

? ? ? ? 通過讀取狀態寄存器的值判斷是否接收到了數據,如果接收到了數據就將數據讀取到數組并清除Rx FIFO寄存器方便下次的接收。

/***********************************************************
函數名稱:NRF24L01_RxPacket(u8 *rxbuf)
函數功能:啟動NRF24L01接收一次數據
入口參數:rxbuf:待接收數據首地址
返回參數:返回值:0,接收完成;其他,錯誤代碼
************************************************************/
u8 NRF24L01_RxPacket(u8 *rxbuf)
{u8 sta;		    							      sta=MySPI_ReadByte(STATUS);  //讀取狀態寄存器的值    	 MySPI_WriteByte(NRF_WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中斷標志if(sta&RX_OK)//接收到數據{MySPI_ReadLen(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//讀取數據MySPI_WriteByte(FLUSH_RX,0xff);//清除RX FIFO寄存器 return 0; }	   return 1;//沒收到任何數據
}

nrf24l01.c

#include "stm32f10x.h"                  // Device header
#include "nrf24l01.h"
#include "spi.h"const u8 TX_ADDRESS[TX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01}; //發送地址
const u8 RX_ADDRESS[RX_ADR_WIDTH]={0x34,0x43,0x10,0x10,0x01};void NRF24L01_Init(void)
{/***** NRF的GPIO初始化 *****/GPIO_InitTypeDef GPIO_InitStructure;RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB, ENABLE);	 //使能PB端口時鐘RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);	 //使能PA端口時鐘GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;GPIO_InitStructure.GPIO_Pin = NRF_CE_PIN;	//推挽 (配置CE)	GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;GPIO_Init(GPIOB, &GPIO_InitStructure);//初始化指定IOGPIO_InitStructure.GPIO_Pin  = NRF_IRQ_PIN;//配置IRQGPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //PB15 上拉輸入  GPIO_Init(GPIOA,&GPIO_InitStructure);my_spi_init();NRF_CE(0); 			//使能24L01SPI_NSS(1);			//SPI片選取消
}
/***** 檢測NRF  成功為0 *****/
uint8_t NRF24L01_Check(void)
{u8 buf[5] = { 0x01,0x01,0x01,0x01,0x01 };u8 i; MySPI_WriteLen(NRF_WRITE_REG+TX_ADDR,buf,5);//寫入5個字節的地址MySPI_ReadLen(TX_ADDR,buf,5); //讀出寫入的地址for(i=0;i<5;i++)if(buf[i]!=0x01)break;if(i!=5)return 1;//檢測24L01錯誤return 0;		 //檢測到24L01
}
/***** 將NRF設置位發送模式 *****/
void NRF24L01_TX_Mode(void)
{NRF_CE(0);//將CE置低配置為待機模式才能對寄存器進行配置MySPI_WriteLen(NRF_WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS,TX_ADR_WIDTH);//寫TX節點地址MySPI_WriteLen(NRF_WRITE_REG+RX_ADDR_P0,(u8*)TX_ADDRESS,RX_ADR_WIDTH);//設置RX節點地址,主要為了使能ACKMySPI_WriteByte(NRF_WRITE_REG+EN_AA,0x01);//使能通道0的自動應答MySPI_WriteByte(NRF_WRITE_REG+EN_RXADDR,0x01);//使能通道0的自動應答MySPI_WriteByte(NRF_WRITE_REG+SETUP_RETR,0x1a);//設置自動重發間隔時間:500us + 86us;最大自動重發次數:10次MySPI_WriteByte(NRF_WRITE_REG+RF_CH,40);       //設置RF通道為40MySPI_WriteByte(NRF_WRITE_REG+RF_SETUP,0x0f);  //設置TX發射參數,0db增益,2Mbps,低噪聲增益開啟MySPI_WriteByte(NRF_WRITE_REG+CONFIG,0x0e);    //配置基本工作模式的參數;PWR_UP,EN_CRC,16BIT_CRC,接收模式,開啟所有中斷NRF_CE(1);//CE為高,10us后啟動發送
}
/***** 將NRF設置為接收模式 *****/
void NRF24L01_RX_Mode(void)
{NRF_CE(0);	 MySPI_WriteLen(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH);//設置RX節點地址MySPI_WriteByte(NRF_WRITE_REG+EN_AA,0x01);//使能通道0的自動應答MySPI_WriteByte(NRF_WRITE_REG+EN_RXADDR,0x01);//使能通道0的自動應答MySPI_WriteByte(NRF_WRITE_REG+RF_CH,40);       //設置RF通道為40MySPI_WriteByte(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);//選擇通道0的有效數據寬度 MySPI_WriteByte(NRF_WRITE_REG+RF_SETUP,0x0f);  //設置TX發射參數,0db增益,2Mbps,低噪聲增益開啟MySPI_WriteByte(NRF_WRITE_REG+CONFIG,0x0f);    //配置基本工作模式的參數;PWR_UP,EN_CRC,16BIT_CRC,接收模式,開啟所有中斷NRF_CE(1);//CE為高,10us后啟動發送
}/***********************************************************
函數名稱:NRF24L01_TxPacket(u8 *txbuf)
函數功能:啟動NRF24L01發送一次數據
入口參數:txbuf  待發送的數據首地址
返回參數:返回值:TX_OK,接收完成,0xff,錯誤代碼
************************************************************/
u8 NRF24L01_TxPacket(u8 *txbuf)
{u8 sta;NRF_CE(0);MySPI_WriteLen(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);//寫數據到TX BUF  32個字節NRF_CE(1);//啟動發送while(READ_IRQ!=0);//等待發送完成sta=MySPI_ReadByte(STATUS);  //讀取狀態寄存器的值	   MySPI_WriteByte(NRF_WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中斷標志if(sta&MAX_TX)//達到最大重發次數{MySPI_WriteByte(FLUSH_TX,0xff);//清除TX FIFO寄存器 return MAX_TX; }if(sta&TX_OK)//發送完成{return TX_OK;}return 0xff;//其他原因發送失敗    
}/***********************************************************
函數名稱:NRF24L01_RxPacket(u8 *rxbuf)
函數功能:啟動NRF24L01接收一次數據
入口參數:rxbuf:待接收數據首地址
返回參數:返回值:0,接收完成;其他,錯誤代碼
************************************************************/
u8 NRF24L01_RxPacket(u8 *rxbuf)
{u8 sta;		    							      sta=MySPI_ReadByte(STATUS);  //讀取狀態寄存器的值    	 MySPI_WriteByte(NRF_WRITE_REG+STATUS,sta); //清除TX_DS或MAX_RT中斷標志if(sta&RX_OK)//接收到數據{MySPI_ReadLen(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);//讀取數據MySPI_WriteByte(FLUSH_RX,0xff);//清除RX FIFO寄存器 return 0; }	   return 1;//沒收到任何數據
}

nrf24l01.h

#ifndef __NRF24L010_H
#define __NRF24L010_H#include "stm32f10x.h"                  // Device header#define NRF_IRQ_PORT        GPIOA
#define NRF_IRQ_PIN         GPIO_Pin_8
#define NRF_CE_PORT         GPIOB
#define NRF_CE_PIN          GPIO_Pin_11#define NRF_CE(x)    NRF_CE_PORT->BSRR = NRF_CE_PIN<<(16*(!x))
#define READ_IRQ    (BitAction)(NRF_IRQ_PORT->IDR & NRF_IRQ_PIN)/*************************  NRF24L01寄存器操作命令  *************************/
#define NRF_READ_REG    0x00  //讀配置寄存器,低5位為寄存器地址
#define NRF_WRITE_REG   0x20  //寫配置寄存器,低5位為寄存器地址
#define RD_RX_PLOAD     0x61  //讀RX有效數據,1~32字節
#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:電選擇;bit2:CRC模式;bit3:CRC使能;//bit4:中斷MAX_RT(達到最大重發次數中斷)使能;bit5:中斷TX_DS使能;bit6:中斷RX_DR使能
#define EN_AA           0x01  //使能自動應答功能  bit0~5,對應通道0~5
#define EN_RXADDR       0x02  //接收地址允許,bit0~5,對應通道0~5
#define SETUP_AW        0x03  //設置地址寬度(所有數據通道):bit1,0:00,3字節;01,4字節;02,5字節;
#define SETUP_RETR      0x04  //建立自動重發;bit3:0,自動重發計數器;bit7:4,自動重發延時 250*x+86us
#define RF_CH           0x05  //RF通道,bit6:0,工作通道頻率;
#define RF_SETUP        0x06  //RF寄存器;bit3:傳輸速率(0:1Mbps,1:2Mbps);bit2:1,發射功率;bit0:低噪聲放大器增益
#define STATUS          0x07  //狀態寄存器;bit0:TX FIFO滿標志;bit3:1,接收數據通道號(最大:6);bit4,達到最多次重發//bit5:數據發送完成中斷;bit6:接收數據中斷;
#define MAX_TX  		0x10  //達到最大發送次數中斷
#define TX_OK   		0x20  //TX發送完成中斷
#define RX_OK   		0x40  //接收到數據中斷#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,不循環;
//
//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 NRF24L01_Init(void);						//初始化
void NRF24L01_RX_Mode(void);					//配置為接收模式
void NRF24L01_TX_Mode(void);					//配置為發送模式
u8 NRF24L01_Write_Reg(u8 reg, u8 value);		//寫寄存器
u8 NRF24L01_Check(void);						//檢查24L01是否存在
u8 NRF24L01_TxPacket(u8 *txbuf);				//發送一個包的數據
u8 NRF24L01_RxPacket(u8 *rxbuf);				//接收一個包的數據
void NRF24L01_Check_detection(void);
void NRF24L01_Text(u8 mode);#endif

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/64670.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/64670.shtml
英文地址,請注明出處:http://en.pswp.cn/web/64670.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【Python】 glob批處理模塊的學習

1.什么是glob模塊&#xff1f; 在 Python 中&#xff0c;glob模塊是一個用于文件路徑名的模式匹配的工具。它使用簡單的通配符規則來匹配文件和目錄的路徑&#xff0c;這些通配符規則類似于在命令行中使用的文件搜索規則。這使得在處理文件系統中的多個文件或目錄時非常方便&am…

Android 系統 AlarmManager 系統層深度定制

Android 系統 AlarmManager 系統層深度定制 目錄 引言AlarmManager 概述AlarmManager 系統架構AlarmManager 核心代碼解讀AlarmManager 深度定制方法 修改 AlarmManagerService 修改定時任務調度策略增加定時任務類型定制內核層 修改定時觸發精度增加定時觸發類型優化定時任務…

解決vue-i18n在非.vue文件中,在其他js文件中無法使用的問題

其實很簡單&#xff0c;把i18n直接掛載到window上&#xff0c;全局可使用。下面請看詳細。 一、安裝 npm install vue-i18n9二、在vue的main.js中引入 import Vue from "vue" import VueI18n from vue-i18n Vue.use(VueI18n)//注入到所有的子組件&#xff0c;就是…

線性代數期末復習 [基礎篇]

關于第六點: AXB 在期末考試中一般A都是可逆的 我們可以先把A的逆求出來,X A ? 1 B A^-1B A?1B,或者 (A,B) -> r (E, A ? 1 B A^-1B A?1B) 如果A矩陣不可逆,轉變為方程組求解問題,假設都是二維矩陣 A(x1,x2) (b1,b2) Ax1 b1,Ax2 b2 XAB 如果A可逆,直接XB A ? 1 A^-…

C++ —— 數據類型轉換和數據類型的別名

數據類型轉換 引言自動類型轉換強制類型轉換數據類型的別名 引言 計算機進行運算時&#xff0c;要求各操作數的數據類型、大小和存儲方式都要相同。&#xff08;例如&#xff1a;8字節的整數和8字節的浮點數&#xff0c;雖然占用內存大小一樣&#xff0c;但是存儲方式不同&…

Kali 自動化換源腳本編寫與使用

1. 背景與需求 在使用 Kali Linux 的過程中&#xff0c;軟件源的配置對系統的更新與軟件安裝速度至關重要。 Kali 的默認官方源提供了安全且最新的軟件包&#xff0c;但有時由于網絡條件或地理位置的限制&#xff0c;使用官方源可能會出現速度較慢的問題。 為了解決這一問題&a…

設計模式-創建型-工廠方法模式

什么是工廠方法模式&#xff1f; 工廠方法模式&#xff08;Factory Method Pattern&#xff09;是 創建型設計模式之一&#xff0c;目的是通過定義一個用于創建對象的接口&#xff0c;讓子類決定實例化哪個類。簡而言之&#xff0c;工廠方法模式通過延遲對象的創建過程到子類來…

【Unity3D】ECS入門學習(十二)IJob、IJobFor、IJobParallelFor

IJob&#xff1a;開啟單個線程進行計算&#xff0c;線程內不允許對同一個數據進行操作&#xff0c;也就是如果你想用多個IJob分別計算&#xff0c;將其結果存儲到同一個NativeArray<int>數組是不允許的&#xff0c;所以不要這樣做&#xff0c;如下例子就是反面教材&#…

Spring 創建和管理 Bean 的原理,以及Spring 的單例模式是否線程安全?(有無狀態Bean)

Spring 是一個輕量級的開源框架&#xff0c;廣泛應用于 Java 企業級應用的開發。它提供了一個全面的、基于 IOC&#xff08;控制反轉&#xff09;和 AOP&#xff08;面向切面編程&#xff09;的容器&#xff0c;可以幫助開發者更好地管理應用程序中的對象。 Spring 創建和管理…

Docker容器鏡像制作

Docker鏡像的基本概念 1. 什么是Docker鏡像&#xff1f; Docker鏡像是一種輕量級、可執行的軟件包&#xff0c;包含運行某個應用所需的所有代碼、庫、依賴項和配置文件。它的形成是一種“打包”和“快照”過程&#xff0c;使得應用能夠在不同環境中保持一致的功能表現。 2. …

InfoNCE Loss詳解(上)

引言 InfoNCE對比學習損失是學習句嵌入繞不開的知識點&#xff0c;本文就從頭開始來探討一下它是怎么來的。 先驗知識 數學期望與大數定律 期望(expectation&#xff0c;expected value&#xff0c;數學期望&#xff0c;mathematical expectation)是隨機變量的平均值&#…

.Net加密與Java互通

.Net加密與Java互通 文章目錄 .Net加密與Java互通前言RSA生成私鑰和公鑰.net加密出數據傳給Java端采用java方給出的公鑰進行加密采用java方給出的私鑰進行解密 .net 解密來自Java端的數據 AES帶有向量的AES加密帶有向量的AES解密無向量AES加密無向量AES解密 SM2(國密)SM2加密Sm…

工作中常用Vim的命令

Hi, 我是你們的老朋友&#xff0c;主要專注于嵌入式軟件開發&#xff0c;有興趣不要忘記點擊關注【碼思途遠】 目錄 0. ctags -R 1.認識 Vim的幾種工作模式 2.高頻使用命令 2.1 修改文件 2.2 關于行號 2.3 刪除多行&#xff0c;刪除部分 2.4 復制粘貼 2.5 光標移動 2.…

如何在 Vue 2 中使用 Swiper 5.4.5 處理靜態與后端數據不能切換問題

一、文章大綱 1.前言 介紹 Swiper 作為一款強大的輪播組件,常用于處理圖片、文章、商品等內容的滑動展示。 在 Vue.js 項目中集成 Swiper,尤其是在 Vue 2 中使用,常見的兩種數據來源:靜態數據與后端數據。 在 Vue 2 項目中集成 Swiper 5.4.5 2.如何通過 npm 安裝 Swiper…

究極炫酷3D立方體宇宙

演示動畫&#xff1a;https://life.mdjsjd.me/2024/12/27/3d-cube-animation/ 一個使用Python和Pygame制作的炫酷3D立方體動畫效果。結合了多種視覺特效,包括: 動態旋轉的3D立方體炫彩漸變的顏色系統星空背景粒子效果動態殘影拖尾效果深度透視投影 主要特性 動態變換: 立方…

什么是 Azure OpenAI ?了解微軟 Azure OpenAI 和 OpenAI 的關系

一、什么是Azure OpenAI &#xff1f; 微軟已與 OpenAI 合作以實現三個主要目標&#xff1a; ?利用 Azure 的基礎結構&#xff08;包括安全性、合規性和區域可用性&#xff09;&#xff0c;幫助用戶構建企業級應用程序。 ?在微軟產品&#xff08;包括 Azure AI 產品以及以外…

Linux day 1129

家人們今天繼續學習Linux&#xff0c;ok話不多說一起去看看吧 三.Linux常用命令 3.1 Linux命令體驗 3.1.1 常用命令演示 在這一部分中&#xff0c;我們主要介紹幾個常用的命令&#xff0c;讓大家快速感 受以下 Linux 指令的操作方式。主要包含以下幾個指令&#xff1a; ls命…

mysql8 從C++源碼角度看 Statement cancelled due to timeout or client request異常

##Statement cancelled due to timeout or client request 異常 Caused by: com.mysql.jdbc.exceptions.MySQLTimeoutException: Statement cancelled due to timeout or client requestat com.mysql.jdbc.PreparedStatement.executeInternal(PreparedStatement.java:1932)at …

【數據結構-單調隊列】力扣1438. 絕對差不超過限制的最長連續子數組

給你一個整數數組 nums &#xff0c;和一個表示限制的整數 limit&#xff0c;請你返回最長連續子數組的長度&#xff0c;該子數組中的任意兩個元素之間的絕對差必須小于或者等于 limit 。 如果不存在滿足條件的子數組&#xff0c;則返回 0 。 示例 1&#xff1a; 輸入&#x…

SAP HCM 標準報表與前臺操作的增強差異邏輯分析(rhgrenz4)

導讀 增強差異:SAP的HCM模塊組織和人事增強都有標準的增強點&#xff0c;不管你調用標準的函數還是前臺操作都會觸發對應的增強。所以很多業務不需要考慮那么多分散點&#xff0c;只要找到一個合適的增強點&#xff0c;就能解決很多和外圍系統集成的業務邏輯&#xff0c;今天遇…