日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

STM32 + 无线通信模块 NRF24L01 数据收发

發(fā)布時(shí)間:2024/3/12 编程问答 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 STM32 + 无线通信模块 NRF24L01 数据收发 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

NRF24L01的模塊資料,網(wǎng)上已很詳盡了,在這不再重復(fù)描述知識點(diǎn)了。

這篇文章的目的,旨在把主要知識點(diǎn)膠接起來,梳理成一套完整的步驟,使器件快速上手匯入工作使用。

將按操作順序,拆分成7個(gè)步驟,注解重點(diǎn)、暗坑。以方便自己進(jìn)行知識管理,亦方便同行兄弟查閱。

代碼方面,盡量做到一行代碼一行解釋。(如有訂正和疑問,可留言交流,將迅速回復(fù)。)

目錄

一、思維導(dǎo)圖

二、 引腳連接,解釋

三、SPI初始化、函數(shù)封裝

四、NRF24L01參數(shù)寫入

五、中斷處理函數(shù)

六、發(fā)送數(shù)據(jù)

七、接收數(shù)據(jù)

八、代碼下載


一、思維導(dǎo)圖

3種主要工作模式、8個(gè)命令字、每包32字節(jié)有效數(shù)據(jù),等等這些,直接思維導(dǎo)圖更有效,不用文字啰嗦。

對主要點(diǎn)進(jìn)行了組織,包括了工作模式、命令字等圖例,認(rèn)真過一遍,心里馬上就能有個(gè)框框。

點(diǎn)擊一下圖片能變成清晰的大圖。當(dāng)然,右擊保存就更方便查看了。


二、 引腳連接,解釋

明確一個(gè),NRF24L01和SI24R1的引腳、程序是通用的,無需任何修改,市面上大部份的NRF24L01模塊,用的是SI24R1的芯片。兩者間通信也互通,已測試確認(rèn)!

下面是一個(gè)通用模塊的引腳,以安信可的SI24R1模塊為例:

共8個(gè)引腳:

  • VCC:3.3V。1.9~3.6V都成,不要接5V,馬上燒!
  • GND:接地??
  • CE:? ? ?模式控制。其高低電平,配合CONFIG寄存器PRIM_RX和PWR_UP兩個(gè)位,可切換工作狀態(tài): 發(fā)送、接收 、待機(jī)?。
  • IRQ:? ? 中斷信號引腳。發(fā)生以下三種中斷時(shí),引腳電平被NRF拉低:發(fā)送成功、接收到數(shù)據(jù)、已達(dá)最大重發(fā)次數(shù)。
  • CSN:? ?SPI的CS片選引腳
  • SCK:? ?SPI的時(shí)鐘線引腳
  • MOSI: SPI的主出從入數(shù)據(jù)引腳
  • MISO: SPI的主入從出數(shù)據(jù)引腳

  • 三、SPI初始化、函數(shù)封裝

    NRF的配置,就是把各種參數(shù)(數(shù)值),如頻道,速率,目標(biāo)地址等,用SPI方式寫到指定地址(芯片的寄存器).

    ?這個(gè)寫入配置的動(dòng)作,拆分開來看,理解為兩部分,是在操作兩種通信,別混亂。

    首先主機(jī)按NRF datasheet的要求,設(shè)置和通過SPI通信,向NRF芯片特定地址(寄存器)寫入?yún)?shù)值;

    而這些寫入的數(shù)值,就是用于控制NRF與別一個(gè)NRF的通信參數(shù)。

    這兩個(gè)通信,理解一下~

    1:主機(jī)和NRF間的通信:? ? ? ?

    • 使用SPI,主機(jī)完成對NRF操控,所有操控其實(shí)就是4個(gè)操作:寫參數(shù)、讀參數(shù)、寫要發(fā)送的數(shù)據(jù),讀出收到的數(shù)據(jù);?
    • 上面的操控,分拆到SPI的操作上,就是常用的6個(gè)函數(shù):SPI初始化、字節(jié)收發(fā)、寫1字節(jié),讀1字節(jié),寫N字節(jié),讀N字節(jié);
    • 寫入?yún)?shù):是NRF與NRF間通信的參數(shù)值, 如頻道 ,速率,CRC校檢,自動(dòng)回答,自動(dòng)重發(fā),目標(biāo)地址....
    • 讀取參數(shù),主要是STATUS狀態(tài)寄存器的值,用于判斷中斷源;
    • 寫入發(fā)送數(shù)據(jù),把待發(fā)送的數(shù)據(jù)寫到TX_FIFO. NRF按包發(fā)送數(shù)據(jù),包中有效數(shù)據(jù)最大32字節(jié);要手動(dòng)做分包處理;
    • 讀出收到數(shù)據(jù),檢測到RX_DR中斷發(fā)生后(IRQ引腳被拉低),用SPI把RX_FIFO緩沖區(qū)的值,讀取存放到指自已的緩沖區(qū);
    • NRF的SPI通信速度可達(dá)10MHz,但為保證數(shù)據(jù)傳輸?shù)耐暾坏舭?#xff0c;盡量不要超過8MHz;
    • NRF要求SPI通信時(shí),在上升沿采樣數(shù)據(jù),要注意時(shí)序。

    2:NRF和NRF間的收發(fā)通信:

    • NRF按主機(jī)剛才寫到芯片的參數(shù)值開始工作(手動(dòng)),通過電波傳輸?shù)搅硪粋€(gè)芯片中或接收別一芯片的數(shù)據(jù)(自動(dòng))。
    • 這部份通信我們要做的,僅是控制CE引腳的高低電平,配合CONFIG寄存器,使NRF在接收、發(fā)送、待機(jī)三種狀態(tài)切換。
    • NRF間的無線通信,基本沒我們什么事。

    編程順序:? GPIO配置? >? SPI配置? >? SPI(5個(gè)小函數(shù))? >? 寫NRF配置? >? NRF中斷處理(3種情況)? >? NRF收、發(fā)(2個(gè)主函數(shù))

    GPIO初始化代碼:

    /*** SPI通信引腳, CS, SCK, MOSI, MISO ***/ GPIOSet (NRF24L01_SPI_CSN_GPIO, NRF24L01_SPI_CSN_PIN, G_MODE_OUT , G_OTYPE_PP, G_OSPEED_25M, G_PUPD_UP , 0); // cs GPIOSet (NRF24L01_SPI_CLK_GPIO , NRF24L01_SPI_CLK_PIN , G_MODE_AF , G_OTYPE_PP , G_OSPEED_25M , G_PUPD_DOWN , G_AF_SPI2 ); // sck GPIOSet (NRF24L01_SPI_MOSI_GPIO ,NRF24L01_SPI_MOSI_PIN , G_MODE_AF , G_OTYPE_PP , G_OSPEED_25M , G_PUPD_DOWN , G_AF_SPI2 ); // mosi GPIOSet (NRF24L01_SPI_MISO_GPIO ,NRF24L01_SPI_MISO_PIN , G_MODE_AF , G_OTYPE_PP , G_OSPEED_25M , G_PUPD_DOWN , G_AF_SPI2 ); // miso /*** NRF控制引腳, CE, IRQ ***/ GPIOSet (NRF24L01_CE_GPIO , NRF24L01_CE_PIN , G_MODE_OUT , G_OTYPE_PP , G_OSPEED_25M , G_PUPD_DOWN , 0); // CE GPIOSet (NRF24L01_IRQ_GPIO , NRF24L01_IRQ_PIN , G_MODE_IN , G_OTYPE_PP , G_OSPEED_25M , G_PUPD_UP , 0); // IRQ NRF24L01芯片的IRQ引腳下拉能力很弱,注意外部上拉電阻大小,及MCU的上下拉

    GPIOSet是個(gè)自己封裝的初始化函數(shù),不用管,重點(diǎn)看其中的參數(shù)就好,注意各上下拉。

    SPI 初始化代碼:

    /*** SPI通信部分 ***/ CSN_HIGH; //失能NRF NRF24L01_SPI_EN_CLOCK ; // 時(shí)鐘 NRF24L01_SPIX->CR1 = 0; // 清0 NRF24L01_SPIX->CR1 |= 0<<0; // 采樣沿?cái)?shù), NRF要求上升沿采樣 CPHA:時(shí)鐘相位,0x1=在第2個(gè)時(shí)鐘邊沿進(jìn)行數(shù)據(jù)采樣, NRF24L01_SPIX->CR1 |= 0<<1; // 時(shí)鐘線閑時(shí)極性, CPOL:時(shí)鐘極性,0x1=空閑狀態(tài)時(shí),SCK保持高電平 NRF24L01_SPIX->CR1 |= 1<<2; // 主從模式, 0=從,1=主 NRF24L01_SPIX->CR1 |= 2<<3; // 波特率控制[5:3], 0=fPCLK/2, 1=/4倍 2=/8 3/16 NRF24L01_SPIX->CR1 |= 0<<7; // LSB先行, 0=MSB, 1=LSB NRF24L01_SPIX->CR1 |= 1<<8; // 內(nèi)部從器件選擇,根據(jù)9位設(shè)置(失能內(nèi)部NSS) NRF24L01_SPIX->CR1 |= 1<<9; // 軟件從器件管理 : 0=禁止軟件管理從設(shè)備, 1=使能軟件從器件管理(軟件NSS) NRF24L01_SPIX->CR1 |= 0<<11; // 數(shù)據(jù)幀格式, 0=8位, 1=16位 NRF24L01_SPIX->CR1 |= 1<<6; // 使能

    SPI 初始化重點(diǎn):

    • NRF要求在上升沿時(shí)采集數(shù)值。這就要閑時(shí)電平和采樣沿要配合好。
    • NRF的SPI可達(dá)10MHz, 但實(shí)際使用時(shí),不要超過8MHz。這個(gè)在SPI的波特率中可控制,因?yàn)镾PI通信速率受限低速一方。
    • 重要:如果多個(gè)設(shè)備共用同一SPI,把各自的SPI配置封裝成函數(shù),每次使用SPI通信前各自調(diào)用一次,以使用自己的配置。

    插個(gè)話題,為什么使用寄存器操作編程?因?yàn)?#xff1a;使用寄存器=簡單+清晰,你看,不是嗎?

    SPI收發(fā)函數(shù)

    /***************************************************************************** *函 數(shù): u8 SPI_RW(u8 Data) *功 能: SPI寫入一個(gè)字節(jié),并返回一個(gè)字節(jié) *參 數(shù): 要寫入的一字節(jié) *返回值: 返回一字節(jié)數(shù)據(jù) *****************************************************************************/ u8 SPI_SendByte(u8 Data) {u8 retry =0;while((NRF24L01_SPIX ->SR & 2) == 0){ // 理解方式,應(yīng)該把前式的結(jié)果理解為一個(gè)寄存器位值,如果這個(gè)位值是等號后面的值,就等待retry++;if(retry>200) return 0;}NRF24L01_SPIX ->DR = Data;retry=0;while((NRF24L01_SPIX->SR & 1) == 0 ){retry++;if(retry>200) return 0;}return NRF24L01_SPIX->DR ; }/***************************************************************************** *函 數(shù):u8 Nrf24l01_WriteReg(u8 reg,u8 value) *功 能:向指定寄存器地址,寫一個(gè)字節(jié)數(shù)據(jù) *參 數(shù):reg: 寄存器地址 * val: 要寫入的值 *返回值:status *****************************************************************************/ u8 Nrf24l01_WriteReg(u8 reg,u8 value) {u8 status; CSN_LOW;status = SPI_SendByte(reg) ;SPI_SendByte(value);CSN_HIGH; return status; }/***************************************************************************** *函 數(shù):u8 NRF24l01_read_reg(u8 reg) *功 能:向指定寄存器地址,讀出一字節(jié)數(shù)據(jù) *參 數(shù):reg: 寄存器地址 *返回值:reg_val(第二個(gè)讀取到的字節(jié)) *****************************************************************************/ u8 Nrf24l01_ReadReg(u8 reg) {u8 reg_val; CSN_LOW;SPI_SendByte(reg);reg_val = SPI_SendByte(0xFF);CSN_HIGH; return reg_val; }/***************************************************************************** *函 數(shù):u8 Nrf24l01_WriteBuf(u8 reg, u8 *pBuf, u8 len) *功 能:寫一組數(shù)據(jù)到寄存器 *參 數(shù):reg: 寄存器地址 * pBuf: 要寫入數(shù)據(jù)的地址 * len: 要寫入的數(shù)據(jù)長度 *返回值:status *備 注:NRF2401代碼移植只需把SPI驅(qū)動(dòng)修改成自己的即可 *****************************************************************************/ u8 Nrf24l01_WriteBuf(u8 reg, u8 *pBuf, u8 len) {u8 status; CSN_LOW;status = SPI_SendByte(reg);for(u8 i=0; i<len; i++) {SPI_SendByte(pBuf[i]); }CSN_HIGH; return status; }/***************************************************************************** *函 數(shù): u8 vNrf24l01_ReadBuf(u8 reg, u8 *pBuf, u8 len) *功 能: 向指定寄存器地址,讀出指定長度的數(shù)據(jù) *參 數(shù): reg : 寄存器地址 * pBuf : 數(shù)據(jù)存放緩沖區(qū) * len : 讀取的字節(jié)數(shù)量 *返回值: status : 設(shè)備狀態(tài)字 *****************************************************************************/ u8 Nrf24l01_ReadBuf(u8 reg, u8 *pBuf, u8 len) {u8 status; CSN_LOW;status = SPI_SendByte(reg);for(u8 i = 0; i<len ;i++){pBuf[i] = SPI_SendByte(0xFF); }CSN_HIGH; return status; }

    注意:在進(jìn)入下一步配置NRF24L01前,必須先測試一下SPI通信是否成功 。一般是往NRF的發(fā)送地址寄存器寫入五個(gè)字節(jié),再讀出來,把讀出的數(shù)據(jù)和原數(shù)據(jù)對比,?就能知道SPI是否配置正確、 NRF24L01是否連接成功。

    代碼程序中,有個(gè)連接測試函數(shù),可以作模塊的連接,沒有貼上來,留郵箱吧。


    四、NRF24L01參數(shù)寫入

    使用上面初始化的SPI,和剛封裝好的幾個(gè)函數(shù),就可以把需要的參數(shù),寫到NRF特定的地址(寄存器), 完成對其配置。

    NRF24L01 參數(shù)配置代碼:

    /*** NRF24L01通信配置 30,2M,***/ CE_LOW; // 熱待機(jī)模式, 只有在ce置低時(shí),才能配置寄存器 //delayUs(2000); // PowerDown 切換為 PowerUp需要1.5ms Nrf24l01_WriteReg(W_REGISTER + RF_CH, 30); // 射頻通道,即頻率(0-125) Nrf24l01_WriteReg(W_REGISTER + RF_SETUP, 0x0F); // 設(shè)置TX發(fā)射參數(shù),0db增益,2Mbps,低噪聲增益關(guān)閉 (注意:低噪聲增益關(guān)閉/開啟直接影響通信,要開啟都開啟,要關(guān)閉都關(guān)閉0x0f)0x07 Nrf24l01_WriteReg(W_REGISTER + SETUP_AW, 0x03); // 地址長度,默認(rèn)值時(shí)0x03,即5字節(jié) Nrf24l01_WriteBuf(W_REGISTER + TX_ADDR, (u8*)TX_ADDRESS, 5); // 寫TX節(jié)點(diǎn)地址, 地址寬度:5字節(jié),40位 Nrf24l01_WriteBuf(W_REGISTER + RX_ADDR_P0, (u8*)TX_ADDRESS, 5); // 設(shè)置TX節(jié)點(diǎn)地址,主要為了使能ACK,, 地址寬度:5字節(jié),40位 Nrf24l01_WriteReg(W_REGISTER + SETUP_RETR, 0x0A); // 設(shè)置自動(dòng)重發(fā)間隔時(shí)間:500us + 86us;最大自動(dòng)重發(fā)次數(shù):10次 0x1A Nrf24l01_WriteReg(W_REGISTER + EN_RXADDR, 0x01); // 使能通道0的接收地址 Nrf24l01_WriteReg(W_REGISTER + EN_AA, 0x01); // 使能通道0自動(dòng)應(yīng)答 Nrf24l01_WriteReg(W_REGISTER + RX_PW_P0, 32); // 選擇通道0的有效數(shù)據(jù)寬度 Nrf24l01_WriteReg(FLUSH_TX, 0xff); // 清除TX_FIFO Nrf24l01_WriteReg(W_REGISTER+STATUS, 0X7E); // 清除所有中斷,防止一進(jìn)去接收模式就觸發(fā)中斷 Nrf24l01_WriteReg(W_REGISTER+CONFIG, 0x0F); // 配置為接收模式 CE_HIGH; // CE置高,進(jìn)入狀態(tài)

    重點(diǎn):

    • CE引腳置低,方可配置NRF寄存器!? 各教程都這教的,但測試過不置低也可正常配置。
    • RF_CH,:頻道,2.4G為基址,1M為間隔值,如上面的30,代表使用2.430G的頻率進(jìn)行芯片間通信??稍O(shè)值0~125。
    • RF_SETUP: 發(fā)射功率可配置,說白了就是的耗電程度。接收狀態(tài)的功率是不能設(shè)置的,所以接收才是耗電的大頭。數(shù)據(jù)傳輸率,常說的空中速率,一般設(shè)置2M
    • 地址長度,5字節(jié),這個(gè)很獨(dú)特
    • TX_ADDR:數(shù)據(jù)要發(fā)送到的目標(biāo)地址
    • RX_ADDR_P0: 接收通道0的接收地址,接收這個(gè)地址設(shè)備發(fā)來的數(shù)據(jù),這里設(shè)為和TX_ADDR一致,是為了自動(dòng)應(yīng)答。
    • NRF共有6個(gè)接收通道,p0~p5, 可同時(shí)監(jiān)聽6個(gè)不同地址的信號,p0通道也用于作自動(dòng)應(yīng)答作用。
    • TX_FIFO, 發(fā)送數(shù)據(jù)緩沖區(qū),96字節(jié),32字節(jié)為一組,共3組,可理解為緩沖區(qū)可存放3組發(fā)送數(shù)據(jù)。
    • RX_FIFO, 同上,兩個(gè)FIFO相互獨(dú)立。 雖然是FIFO,雖然有3組,但最好還是一包一包收發(fā),狀態(tài)切換時(shí)間難把握。
    • 倒數(shù)第二行,配置為接收模式,注意,這個(gè)時(shí)候還沒開始工作的,還處于PownDown狀態(tài),狀態(tài)和模式是兩回事。
    • 最后一行,CE置高10us后,才進(jìn)入工作狀態(tài),因之前配置的是接收模式,所以將進(jìn)入接收狀態(tài)

    五、中斷處理函數(shù)

    為什么要先說中斷?感覺先了解了中斷,那么發(fā)送、接收就更好理解。

    其實(shí)不應(yīng)該叫中斷的,但這樣好理解,還是遵從約定俗成吧。

    中斷時(shí), IRQ電平被拉低,是由NRF控制產(chǎn)生的,三種情況可觸發(fā):發(fā)送成功、達(dá)到重發(fā)最大次數(shù)、接收到數(shù)據(jù)。

    發(fā)送成功:

    • 1:PTX發(fā)送數(shù)據(jù)后,馬上開始計(jì)時(shí),130us后切換到接收模式,此時(shí)計(jì)時(shí)還在繼續(xù)
    • 2:PRX在收到數(shù)據(jù)后,經(jīng)CRC校檢,數(shù)據(jù)完整后發(fā)回ACK信號
    • 3:PTX在規(guī)定時(shí)間內(nèi)收到ACK信號,則置位TX_DS標(biāo)志,IRQ引腳被拉低

    達(dá)到重發(fā)最大次數(shù):

    • 1:PTX發(fā)送數(shù)據(jù)后,馬上開始計(jì)時(shí),130us后切換到接收模式,此時(shí)計(jì)時(shí)還在繼續(xù)
    • 2:PTX在規(guī)定時(shí)間內(nèi),沒收到ACK信號,原因很多:如PRX沒收到數(shù)據(jù),CRC校驗(yàn)錯(cuò)誤....
    • 3:PTX再次發(fā)送一次數(shù)據(jù),重復(fù)步驟1
    • 4:SETUP_RETR寄存器可設(shè)置重發(fā)的次數(shù),達(dá)到最大次數(shù)后,MAX_RT位被置位,IRQ引腳被拉低。

    接收到數(shù)據(jù):

    • PRX收到數(shù)據(jù),經(jīng)CRC校檢,數(shù)據(jù)完整,有效數(shù)據(jù)存放到RX_FIFO,RX_DR位置高,IRQ引腳被拉低。

    說說清理中斷,要清理的中斷有兩處:

    • NRF的中斷位,上面的三種標(biāo)志中斷位,都在寄存器STATUS中,各位置1可清0,IRQ引腳即回到高電平。
    • 單片機(jī)mcu的中斷位,清理外部中斷線標(biāo)志位,否則會(huì)在中斷函數(shù)里死循環(huán)。

    中斷處理函數(shù)代碼:

    void NRF24L01_IRQ_IRQHANDLER(void) { u8 status=0 ;CE_LOW; // 拉低CE,以便讀取NRF中STATUS中的數(shù)據(jù) status = Nrf24l01_ReadReg(R_REGISTER + STATUS); // 讀取STATUS中的數(shù)據(jù),以便判斷是由什么中斷源觸發(fā)的IRQ中斷/*** 發(fā)送完成中斷 ***/if(status & STATUS_TX){ Nrf24l01_WriteReg(W_REGISTER+STATUS, STATUS_TX); // 清NRF中斷:發(fā)送完成Nrf24l01_WriteReg(FLUSH_TX, 0xff); // 清發(fā)送緩沖區(qū):TX_FIFOprintf("\r\n發(fā)送成功!!!!\r\n");vNrf24l01_RxMode (); // 切換為接收狀態(tài)}/*** 接收完成中斷 ***/if(status & STATUS_RX){ memset (NRF_RX_DATA , 0, 32); Nrf24l01_ReadBuf(R_RX_PAYLOAD, NRF_RX_DATA , RX_PAYLO_WIDTH); // 讀數(shù)據(jù)Nrf24l01_WriteReg(W_REGISTER+STATUS, STATUS_RX); // 清NRF中斷:收到數(shù)據(jù)Nrf24l01_WriteReg(FLUSH_RX,0xff); // 清除RX FIFO(注意:這句話很必要) printf("\r\n接收到數(shù)據(jù): %s\r\n", NRF_RX_DATA); vNrf24l01_RxMode (); // 切換為接收狀態(tài)}/*** 最大重發(fā)次數(shù)中斷 ***/if(status & STATUS_MAX){ Nrf24l01_WriteReg(W_REGISTER+STATUS, 0x70); // 清NRF中斷:三個(gè)Nrf24l01_WriteReg(FLUSH_TX, 0xff); // 清除TX_FIFO printf("\r\n發(fā)送失敗,達(dá)到最大重發(fā)次數(shù)!!!\r\n"); vNrf24l01_RxMode(); // 切換為接收狀態(tài)}EXTI->PR |= NRF24L01_IRQ_PIN ; // 清理外部中斷線標(biāo)志位 }

    六、發(fā)送數(shù)據(jù)

    NRF的數(shù)據(jù)收發(fā),是一包一包進(jìn)行的,一包(幀)數(shù)據(jù):包括了前導(dǎo)碼、目標(biāo)地址、包控制域、有效數(shù)據(jù)、CRC, 但我們只管有效數(shù)據(jù),其它的不用我們負(fù)責(zé),NRF發(fā)送時(shí)自動(dòng)打包,接收到數(shù)據(jù)時(shí)自動(dòng)拆包。

    每一包的有效數(shù)據(jù)最大為32個(gè)字節(jié)。當(dāng)然,也可以只發(fā)一個(gè)字節(jié)的數(shù)據(jù)。

    要發(fā)送的數(shù)據(jù)大于32字節(jié),就要分包進(jìn)行,自行手動(dòng)分包處理。

    因?yàn)樵谂渲貌糠謺r(shí),已配置好了頻道,速率,重發(fā)次數(shù)等各種參數(shù),在需要發(fā)送數(shù)據(jù)時(shí),只要往芯片寫入要發(fā)送的數(shù)據(jù)和地址,然后切換為發(fā)送狀態(tài),芯片就會(huì)自動(dòng)發(fā)送。

    發(fā)送成功(收到ack),會(huì)產(chǎn)生TX_DS中斷。

    發(fā)送失敗了(達(dá)到最大重發(fā)次數(shù)), 也會(huì)產(chǎn)生MAR_RT中斷。

    在中斷函數(shù)里,根據(jù)情況作處理就好。

    發(fā)送數(shù)據(jù)代碼:

    void vNrf24l01_TxPacket(u8 *txbuf) {CE_LOW; Nrf24l01_WriteBuf(W_TX_PAYLOAD, txbuf, 32); // 寫數(shù)據(jù)到TX_BUFF Nrf24l01_WriteBuf(W_REGISTER+TX_ADDR, (u8*)TX_ADDRESS, 5); // 寫入要發(fā)送的目標(biāo)地址 Nrf24l01_WriteBuf(W_REGISTER+RX_ADDR_P0, (u8*)TX_ADDRESS, 5); // 通道0的地址設(shè)為和目標(biāo)地址一致,以接收自動(dòng)回復(fù)auto_ack信號 Nrf24l01_WriteReg(W_REGISTER+CONFIG, 0x0E); // 設(shè)置為發(fā)送模式,開啟所有中斷 CE_HIGH; }

    發(fā)送就這幾句!

    重點(diǎn):RX_ADDR_P0的地址和TX_ARRD一樣,目的是自動(dòng)應(yīng)答。有個(gè)前提,在配置中已使能自動(dòng)應(yīng)答。

    把操作封裝成一個(gè)函數(shù),要發(fā)什么,就往函數(shù)里掉數(shù)據(jù)就好,每次不要大于32字節(jié)。


    七、接收數(shù)據(jù)

    當(dāng)系統(tǒng)或程序運(yùn)行時(shí),大部分時(shí)間是運(yùn)行在接收狀態(tài)下的。如:

    • 第四個(gè)部分配置步驟完成后,程序已處在接收狀態(tài)。
    • 第五個(gè)部分,在中斷處理函數(shù)中,三種中斷處理后,也切換為接收狀態(tài),當(dāng)然,也可以切換為更省電的待機(jī)狀態(tài)。

    NRF有6個(gè)接收通道,指在可同時(shí)監(jiān)聽接收同一個(gè)頻道,同一速率的6個(gè)不同設(shè)備的數(shù)據(jù)。

    常用的只是通道P0, 如果只使能了通道P0,那就只能接收到P0中地址設(shè)備發(fā)來的數(shù)據(jù)。

    可以使能全部6個(gè)通道,設(shè)置6個(gè)不同設(shè)備地址,就可以監(jiān)聽接收6個(gè)設(shè)備發(fā)來的數(shù)據(jù)(同一時(shí)間,只能接收其中1個(gè)設(shè)備的數(shù)據(jù));

    注意,接收數(shù)據(jù),指在接收中斷發(fā)生后,我們從RX_FIFO中把數(shù)據(jù)讀存到主機(jī)。而中斷發(fā)生前的監(jiān)聽接收,NRF自動(dòng)完成。

    接收數(shù)據(jù)的代碼:

    接收本來就是最簡單的,沒啥特別代碼,下面的代碼,只是在中斷處理函數(shù)里,再貼出來而已。

    Nrf24l01_ReadBuf(R_RX_PAYLOAD, NRF_RX_DATA , RX_PAYLO_WIDTH); // 讀數(shù)據(jù)到數(shù)組 Nrf24l01_WriteReg(W_REGISTER+STATUS, STATUS_RX); // 清NRF中斷:收到數(shù)據(jù) Nrf24l01_WriteReg(FLUSH_RX,0xff); // 清除RX FIFO(注意:這句話很必要)

    把接收到的數(shù)據(jù),先存放NRF_RX_DATA數(shù)組,再進(jìn)行處理,不要在中斷函數(shù)中處理。

    讀完后,記得要清理RX_FIFO,不然它一直占用NRF的緩沖區(qū)。RX_FIFO共96字節(jié),分成32字節(jié)3組,NRF每次接收到數(shù)據(jù)就存放到最后面的一組中,當(dāng)存滿了3組,后面再接收到的數(shù)據(jù),就會(huì)被NRF掉棄。


    八、代碼下載

    兩種方式,

    1:代碼已打包并上傳成CSDN下載資源:

    無線通信_NRF24L01.zip_nrf24l01發(fā)送前導(dǎo)碼-嵌入式文檔類資源-CSDN下載

    2:由于咨詢代碼的人多,已把代碼打包上傳到Q群,群文件夾里找吧:262901124.


    最后,如果你有更完善的代碼,或修改后的代碼,請回贈(zèng)我一份,謝謝~~~

    寫了三四個(gè)小時(shí),累~~~

    總結(jié)

    以上是生活随笔為你收集整理的STM32 + 无线通信模块 NRF24L01 数据收发的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。