本帖最后由 xiao_yp2014 于 2016-6-7 13:55 編輯
如何快速搞通“NRF24L01”,你造嗎? http://www.torrancerestoration.com/bbs/dpj-51459-1.html
nRF24L01應(yīng)用筆記(下)
上面一篇說了一下調(diào)試的方法和步驟,接下來說一下程序當(dāng)中需要注意的地方。首先,不要把nRF24L01芯片想得太神秘,其實(shí)就是一個(gè)無線通信的芯片,通信的一些參數(shù)(通信速率,地址位長(zhǎng)度,數(shù)據(jù)位長(zhǎng)度)需要寫內(nèi)部寄存器來設(shè)置。單片機(jī)和芯片是用SPI通信,這個(gè)就不再說了,那么,就直接進(jìn)入主題。
一、nRF24L01的寄存器 首先來了解一下寄存器(下面這些寄存器地址只是一個(gè)偏移地址)
- #define CONFIG 0x00 // 配置寄存器地址
- #define EN_AA 0x01 // 使能ACK自動(dòng)應(yīng)答功能地址
- #define EN_RXADDR 0x02 // 接收地址允許地址
- #define SETUP_AW 0x03 // 設(shè)置地址寬度地址
- #define SETUP_RETR 0x04 // 建立自動(dòng)應(yīng)答的時(shí)間地址
- #define RF_CH 0x05 // 射頻通道地址
- #define RF_SETUP 0x06 // 射頻寄存器地址
- #define STATUS 0x07 // 狀態(tài)寄存器地址
- #define OBSERVE_TX 0x08 // 發(fā)送檢測(cè)寄存器地址
- #define CD 0x09 // 載波檢測(cè)地址
- #define RX_ADDR_P0 0x0A // 數(shù)據(jù)通道0接收地址,最大數(shù)據(jù)長(zhǎng)度5個(gè)字節(jié)
- #define RX_ADDR_P1 0x0B // 數(shù)據(jù)通道1接收地址,最大數(shù)據(jù)長(zhǎng)度5個(gè)字節(jié)
- #define RX_ADDR_P2 0x0C // 數(shù)據(jù)通道2接收地址,最低字節(jié)可設(shè)置,高字節(jié)部分必須與RX_ADDR相同
- #define RX_ADDR_P3 0x0D // 數(shù)據(jù)通道3接收地址,最低字節(jié)可設(shè)置,高字節(jié)部分必須與RX_ADDR相同
- #define RX_ADDR_P4 0x0E // 數(shù)據(jù)通道4接收地址,最低字節(jié)可設(shè)置,高字節(jié)部分必須與RX_ADDR相同
- #define RX_ADDR_P5 0x0F // 數(shù)據(jù)通道5接收地址,最低字節(jié)可設(shè)置,高字節(jié)部分必須與RX_ADDR相同
- #define TX_ADDR 0x10 // 發(fā)送地址,在增強(qiáng)型模式下,要與RX_ADDR_P0相同
- #define RX_PW_P0 0x11 // 接收數(shù)據(jù)通道0有效數(shù)據(jù)寬度(1~32個(gè)字節(jié))
- #define RX_PW_P1 0x12 // 接收數(shù)據(jù)通道1有效數(shù)據(jù)寬度(1~32個(gè)字節(jié))
- #define RX_PW_P2 0x13 // 接收數(shù)據(jù)通道2有效數(shù)據(jù)寬度(1~32個(gè)字節(jié))
- #define RX_PW_P3 0x14 // 接收數(shù)據(jù)通道3有效數(shù)據(jù)寬度(1~32個(gè)字節(jié))
- #define RX_PW_P4 0x15 // 接收數(shù)據(jù)通道4有效數(shù)據(jù)寬度(1~32個(gè)字節(jié))
- #define RX_PW_P5 0x16 // 接收數(shù)據(jù)通道5有效數(shù)據(jù)寬度(1~32個(gè)字節(jié))
- #define FIFO_STATUS 0x17 // FIFO狀態(tài)寄存器地址
復(fù)制代碼
上面一些寄存器地址并不是真實(shí)的地址,是一個(gè)偏移地址,那實(shí)際地址如何表示呢? 實(shí)際地址 = 基地址 + 偏移地址
二、nRF24L01操作命令(下面的操作命令就是基地址)
- #define READ_REG 0x00 // 讀配置寄存器命令
- #define WRITE_REG 0x20 // 寫配置寄存器命令
- #define RD_RX_PLOAD 0x61 // 讀RX有效數(shù)據(jù)命令
- #define WR_TX_PLOAD 0xA0 // 寫TX有效數(shù)據(jù)命令
- #define FLUSH_TX 0xE1 // 清除TX_FIFO寄存器,應(yīng)用于發(fā)射模式
- #define FLUSH_RX 0xE2 // 清除RX_FIFO寄存器,應(yīng)用于接收模式
- #define REUSE_TX_PL 0xE3 // 應(yīng)用發(fā)射,重新發(fā)送上一包有效數(shù)據(jù)
- //#define NOP 0xFF // 空操作命令,一般沒有使用
復(fù)制代碼
上面一些寄存器地址并不是真實(shí)的地址,是一個(gè)偏移地址,那實(shí)際地址如何表示呢? 實(shí)際地址 = 基地址 + 偏移地址 在程序中就會(huì)有這樣寫,如下:
- SPI_Write_Reg(WRITE_REG + RX_PW_P0, TX_ADR_WIDTH); //接收數(shù)據(jù)通道0有效數(shù)據(jù)寬度5個(gè)字節(jié)
- WRITE_REG + RX_PW_P0就是設(shè)置接收數(shù)據(jù)寬度的實(shí)際寄存器
復(fù)制代碼
三、nRF24L01初始化 初始化就是設(shè)置nRF24L01的默認(rèn)工作狀態(tài),和發(fā)送或接收的一些要求,比如選擇接收通道,速率,發(fā)射功率之類的東西,這些在網(wǎng)上都可以找到程序,我也就不多說了,只提一下需要注意的地方 SPI_Write_Reg(WRITE_REG + RF_CH, 40); // 選擇射頻通道0x40 這個(gè)是設(shè)置射頻通道,后面的40可以隨便定義使用,只要發(fā)送和接收一致就行了,我是這樣處理的,可能還有其它的解釋。
四、nRF24L01設(shè)置寄存器 寄存器設(shè)置和我們使用51單片機(jī)是一樣的,都是寫一些參數(shù),來開啟或關(guān)閉某一個(gè)功能,唯一不同一點(diǎn)是,51單片機(jī)的地址是定義好了的,只需要向里面寫數(shù)據(jù)就可以了,但是nRF24L01不能這樣做,因?yàn)樗鼉?nèi)部沒有這個(gè)地址管理,就必須由主設(shè)備來選擇地址,才可以對(duì)號(hào)入座,向規(guī)定的寄存器寫正確的數(shù)據(jù)。 配置寄存器參數(shù)時(shí),要先寫地址,再寫參數(shù)。
看看程序中是如何處理的 - SPI_Write_Reg(WRITE_REG + RX_PW_P0, TX_ADR_WIDTH); //這個(gè)是調(diào)用下面的函數(shù)
- unsigned char SPI_Write_Reg(unsigned char ucWrite_Reg, unsigned char ucWriteValue)
- {
- unsigned char ucStatus;
- CSN = 0; // CSN置低,開始傳輸數(shù)據(jù)
- ucStatus = SPI_Simulation(ucWrite_Reg); // 選擇寄存器,同時(shí)返回狀態(tài)字
- SPI_Simulation(ucWriteValue); // 然后寫數(shù)據(jù)到該寄存器
- CSN = 1; // CSN拉高,結(jié)束數(shù)據(jù)傳輸
- return(ucStatus); // 返回狀態(tài)寄存器
- }
復(fù)制代碼
紅色是地址 藍(lán)色是數(shù)據(jù)
五、nRF24L01的查詢方法(中斷查詢和狀態(tài)寄存器查詢,主要介紹狀態(tài)寄存器查詢方法)
nRF24L01的查詢方法有兩種: 1、中斷查詢
IRQ:中斷信號(hào)。無線通信過程中 MCU 主要是通過 IRQ 與 NRF24L01 進(jìn)行通信。 中斷查詢開啟后,當(dāng)接收成功或者發(fā)送成功在中斷引腳上面會(huì)有一個(gè)低電平,把IRQ引腳接在單片機(jī)的外部中斷引腳上面,就能夠?qū)崟r(shí)查詢。
2、狀態(tài)寄存器查詢 狀態(tài)寄存器查詢:就是通過軟件查詢這個(gè)寄存器的置位或者是清零,來判斷是發(fā)送成功還是接收成功。
狀態(tài)寄存器查詢程序如下:
- unsigned char bdata StateFalg;//狀態(tài)標(biāo)志位,定義在bdata ,是可以位尋址。
- sbit RX_DR = StateFalg^6; //接收中斷標(biāo)志位
- sbit TX_DS = StateFalg^5; //發(fā)送中斷標(biāo)志位
- sbit MAX_RT = StateFalg^4; //發(fā)送次數(shù)超過10次中斷標(biāo)志位
- StateFalg = SPI_Read_Reg(READ_REG+STATUS); // 返回狀態(tài)寄存器
- SPI_Write_Reg(WRITE_REG+STATUS,StateFalg); // 清零對(duì)應(yīng)中斷標(biāo)志
- if(RX_DR == 1)
- {
- SPI_Read_Buf(RD_RX_PLOAD,RX_BUF, TX_PLOAD_WIDTH); //從FIFO緩存中讀取數(shù)據(jù),存入數(shù)組。
- SPI_Write_Reg(FLUSH_RX,0); //清除RX_FIFO寄存器
- }
復(fù)制代碼
六、接收或發(fā)送模式的切換
最后說一下模式的切換,模式切換可以在CONFIG寄存器中找到,先看一下 CONFIG的定義。
位7:RESERVED 默認(rèn)為“0”
位6:MASK_RX_DR 可屏蔽中斷RX_DR 1:IRQ引腳不產(chǎn)生RX_DR 中斷 0:RX_DR 中斷產(chǎn)生時(shí)IRQ引腳為低電平
位5:MASK_TX_DS 可屏蔽中斷TX_DR 1:IRQ引腳不產(chǎn)生TX_DR 中斷 0:TX_DR 中斷產(chǎn)生時(shí)IRQ引腳為低電平
位4:MASK_MAX_RT 可屏蔽中斷MAX_RT 1:IRQ引腳不產(chǎn)生TX_DS中斷 0:MAX_RT中斷產(chǎn)生時(shí),IRQ引腳為低電平
位3:EN_CRC CRC使能端 如果EN_AA中任意一位為高,則EN_CRC強(qiáng)迫為高
位2:CRCO CRC模式 1:16位CRC校驗(yàn) 0:8位CRC校驗(yàn)
位1: PWR_UP 芯片模式設(shè)置 1:上電模式 0:掉電模式
位0: PRIM_RX 接收或發(fā)射模式 1:接收模式 0:發(fā)射模式
在程序中只需要對(duì)相應(yīng)的位置“0”或者置“1”,程序如下
- 接收模式:
- SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, TX_ADDRESS, TX_ADR_WIDTH); //接收地址寬度
- SPI_Write_Reg(WRITE_REG+RX_PW_P0,TX_PLOAD_WIDTH); // 接收數(shù)據(jù)長(zhǎng)度
- SPI_Write_Reg(WRITE_REG+CONFIG,0x0f); // 接收模式,8CRC校驗(yàn),IRQ中斷顯示,上電發(fā)送
- 發(fā)送模式:
- SPI_Write_Buf(TX_ADDR, ucTX_Address, TX_ADR_WIDTH); // 寫入發(fā)送地址
- SPI_Write_Buf(WR_TX_PLOAD, ucTxData, TX_PLOAD_WIDTH); //裝載數(shù)據(jù)到FIFO中
- SPI_Write_Reg(WRITE_REG+CONFIG,0x0e); // 發(fā)送模式,8CRC校驗(yàn),IRQ中斷顯示,上電發(fā)送
復(fù)制代碼
到這里,nRF24L01無線芯片的一些基本操作和注意事項(xiàng)就是這樣。
|