|
最近在接了一個(gè)項(xiàng)目,要求各個(gè)設(shè)備能夠聯(lián)網(wǎng)(不是互聯(lián)網(wǎng))控制。nrf24l01剛好有這個(gè)功能。但是之前只做過(guò)一對(duì)一的通信,還是用例程的那一種。我在想,用兩個(gè)地址,共用同一個(gè)通道應(yīng)該也可以完成。后來(lái)他又要求發(fā)過(guò)去的數(shù)據(jù)還要能回傳,這下我只好來(lái)研究多通道通信了。
多機(jī)通信和一對(duì)一通信基本上相同,就是要配置其他通道的地址和使能其他通道的有效數(shù)據(jù)寬度,還有自動(dòng)應(yīng)答。
這是接收機(jī)的:
void NRF24L01_Init_RX(void)
{
CE=0;
CSN=1;
SCK=0;
SPI_Write_Buf(WRITE_REG + TX_ADDR, RX_ADDRESS, TX_ADR_WIDTH);
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH);
SPI_Write_Buf(WRITE_REG + RX_ADDR_P1, RX_ADDRESS1, RX_ADR_WIDTH);
SPI_Write_Reg(WRITE_REG + EN_AA, 0x3f);
SPI_Write_Reg(WRITE_REG + EN_RXADDR, 0x3f);
SPI_Write_Reg(WRITE_REG + RF_CH, 40);
SPI_Write_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH);
SPI_Write_Reg(WRITE_REG + RX_PW_P1, RX_PLOAD_WIDTH);
SPI_Write_Reg(WRITE_REG + RF_SETUP, 0x0F);
SPI_Write_Reg(WRITE_REG + CONFIG, 0x0f);
}
由于我用的是KeilC51和MDK5共存的,所以注釋復(fù)制過(guò)來(lái)之后就成了亂碼,在此貼圖一張:
NRF24L01_Init_Rx(void)
下面就到了發(fā)送機(jī)了的配置了:
void NRF24L01_Init_TX(uint8_t *ADDRn)
{
CE=0;
CSN=1;
SCK=0;
SPI_Write_Buf(WRITE_REG + TX_ADDR, (uint8_t*)ADDRn, TX_ADR_WIDTH);
SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, (uint8_t*)ADDRn, RX_ADR_WIDTH);
SPI_Write_Reg(WRITE_REG + EN_AA, 0x3f);
SPI_Write_Reg(WRITE_REG + EN_RXADDR, 0x3f);
SPI_Write_Reg(WRITE_REG + RF_CH, 40);
SPI_Write_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH);
SPI_Write_Reg(WRITE_REG + RX_PW_P1, RX_PLOAD_WIDTH);
SPI_Write_Reg(WRITE_REG + SETUP_RETR, 0xff);
SPI_Write_Reg(WRITE_REG + RF_SETUP, 0x0f);
SPI_Write_Reg(WRITE_REG + CONFIG, 0x0E);
}
同樣:
NRF24L01_Init_TX(uint8_t *ADDRn)
發(fā)送給其他通道,只要改成其他通道的地址就可以了,不用改通道號(hào),現(xiàn)在還不知道為什么。
接下來(lái)就是發(fā)送函數(shù):
uint8_t nRF24L01_TxPacket(unsigned char * tx_buf)
{
uint8_t Return_Flag=0;
CE=0;
SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH);
Delayms(2);
Return_Flag = Check_ACK(1);
return Return_Flag;
}
由于我是通過(guò)電腦串口控制上位機(jī),發(fā)給某一個(gè)下位機(jī),然后再發(fā)回到我的上位機(jī)中,最后回傳到電腦,所以沒(méi)有數(shù)據(jù)搶答的問(wèn)題。
最后再說(shuō)一句,要配置第N個(gè)的通道,前N個(gè)通道也必須被配置,要不然配置不成功。
最后貼上上位機(jī)程序:
- #include <stc12c5a.H>
- #include <intrins.h>
- #include "nrf24l01.h"
- #include "delay.h"
- #define uint32_t unsigned int
- #define uint8_t unsigned char
- uint8_t const RX_ADDRESS[TX_ADR_WIDTH]= {0x01,0x13,0x5C,0x0C,0x03}; //本地地址
- uint8_t const RX_ADDRESS1[TX_ADR_WIDTH]={0x02,0x13,0x5C,0x0C,0x03}; //本地地址1
- extern uint8_t Rx_Buf[32];
- extern uint8_t Tx_Buf[32];
- /**********************************RNF24L01狀態(tài)標(biāo)志位************************************************/
- uint8_t bdata sta;
- sbit RX_DR =sta^6;
- sbit TX_DS =sta^5;
- sbit MAX_RT =sta^4;
- /**********************************NRF24L01管腳與單片機(jī)接口定義**************************************/
- sbit MISO =P3^4;
- sbit MOSI =P3^6;
- sbit SCK =P3^3;
- sbit CE =P3^2;
- sbit CSN =P3^5;
- sbit IRQ =P3^7;
- /***************************************************************************
- 函數(shù)名稱:uchar SPI_RW(uint8_t dat)
- 函數(shù)功能:NRF24L01的SPI寫時(shí)序
- 函數(shù)備注:
- ***************************************************************************/
- uint8_t SPI_RW(uint8_t dat)
- {
- uint8_t i;
- for(i=0;i<8;i++)
- {
- MOSI = (dat & 0x80);
- dat = (dat << 1);
- SCK = 1;
- dat |= MISO;
- SCK = 0;
- }
- return(dat);
- }
- /***************************************************************************
- 函數(shù)名稱:uint8_t SPI_Read(uint8_t cmd_reg)
- 函數(shù)功能:NRF24L01的SPI讀時(shí)序
- 函數(shù)備注:
- ***************************************************************************/
- uint8_t SPI_Read(uint8_t cmd_reg)
- {
- uint8_t value;
-
- CSN = 0;
- SPI_RW(cmd_reg);
- value = SPI_RW(0);
- CSN = 1;
-
- return(value);
- }
- /***************************************************************************
- 函數(shù)名稱:void SPI_Write_Reg(uint8_t cmd_reg, uint8_t value)
- 函數(shù)功能:寫入NRF24L01寄寄存器和從NRF24L01寄存器中讀出
- 函數(shù)備注:
- ***************************************************************************/
- void SPI_Write_Reg(uint8_t cmd_reg, uint8_t value)
- {
- CSN = 0;
- SPI_RW(cmd_reg);
- SPI_RW(value);
- CSN = 1;
- }
- /***************************************************************************
- 函數(shù)名稱:uint8_t SPI_Read_Buf(uint8_t cmd_reg, uint8_t *pBuf, uint8_t num)
- 函數(shù)功能:從NRF24L01寄存器中讀出數(shù)據(jù)
- 函數(shù)備注:reg:為寄存器地址,pBuf:為待讀出數(shù)據(jù)地址,uint8_t:讀出數(shù)據(jù)的個(gè)數(shù)
- ***************************************************************************/
- uint8_t SPI_Read_Buf(uint8_t cmd_reg, uint8_t *pBuf, uint8_t num)
- {
- uint8_t status,i;
-
- CSN = 0;
- status = SPI_RW(cmd_reg);
- for(i=0;i<num;i++) pBuf[i] = SPI_RW(0);
- CSN = 1;
-
- return(status);
- }
- /***************************************************************************
- 函數(shù)名稱:void SPI_Write_Buf(uint8_t cmd_reg, uint8_t *pBuf, uint8_t num)
- 函數(shù)功能:在NRF24L01寄存器中寫入數(shù)據(jù)
- 函數(shù)備注:reg:為寄存器地址,pBuf:為待寫入數(shù)據(jù)地址,uint8_t:寫入數(shù)據(jù)的個(gè)數(shù)
- ***************************************************************************/
- void SPI_Write_Buf(uint8_t cmd_reg, uint8_t *pBuf, uint8_t num)
- {
- uint8_t i;
- CSN = 0; //SPI使能
- SPI_RW(cmd_reg);
- for(i=0; i<num; i++) SPI_RW(*pBuf++);
- CSN = 1; //關(guān)閉SPI
- }
- /***************************************************************************
- 函數(shù)名稱:uint8_t nRF24L01_RxPacket(uint8_t* rx_buf)
- 函數(shù)功能:數(shù)據(jù)讀取后放入rx_buf接收緩沖區(qū)中
- 函數(shù)備注:
- ***************************************************************************/
- uint8_t nRF24L01_RxPacket(uint8_t* rx_buf)
- {
- uint8_t flag;
- CE = 1; //很重要!啟動(dòng)接收!
- Delayms(1);
- sta=SPI_Read(READ_REG+STATUS); // 讀取狀態(tài)寄存其來(lái)判斷數(shù)據(jù)接收狀況 //寄存器前面要加是讀還是寫
- if(RX_DR) // 判斷是否接收到數(shù)據(jù) 如果置1則說(shuō)明接到數(shù)據(jù)并且放置在接收緩存器
- {
- CE = 0;
- SPI_Read_Buf(RD_RX_PLOAD,rx_buf,RX_PLOAD_WIDTH); //這本來(lái)就是指令,不用加,意思說(shuō)去緩存器里讀
- flag =1; //讀取數(shù)據(jù)完成標(biāo)志
- }
- SPI_Write_Reg(WRITE_REG+STATUS,sta); //接收到數(shù)據(jù)后RX_DR,TX_DS,MAX_PT都置高為1,通過(guò)寫1來(lái)清楚中斷標(biāo)志
- return flag;
- }
- /**************************************************
- 函數(shù):Check_ACK(bit clear)
- 描述:檢查接收設(shè)備有無(wú)接收到數(shù)據(jù)包,設(shè)定沒(méi)有收到應(yīng)答信
- 號(hào)是否重發(fā)
- /**************************************************/
- uint8_t Check_ACK(bit clear)
- {
- while(IRQ);
- sta = SPI_RW(NOP); // 返回狀態(tài)寄存器
- if(MAX_RT)
- if(clear) // 是否清除TX FIFO,沒(méi)有清除在復(fù)位MAX_RT中斷標(biāo)志后重發(fā)
- SPI_RW(FLUSH_TX); //清空寄存器,很重要!!!
- SPI_Write_Reg(WRITE_REG + STATUS, sta); // 清除TX_DS或MAX_RT中斷標(biāo)志
- IRQ = 1;
- if(TX_DS)
- return(0x01);
- else
- return(0x00);
- }
- /***************************************************************************
- 函數(shù)名稱:void nRF24L01_TxPacket(unsigned char * tx_buf)
- 函數(shù)功能:發(fā)送 tx_buf中數(shù)據(jù)
- 函數(shù)備注:
- ***************************************************************************/
- uint8_t nRF24L01_TxPacket(unsigned char * tx_buf)
- {
- uint8_t Return_Flag=0;
- CE=0; //StandBy I模式
- SPI_Write_Buf(WR_TX_PLOAD, tx_buf, TX_PLOAD_WIDTH); // 裝載數(shù)據(jù) WR_TX_PLOAD本來(lái)就是指令 不用加 將數(shù)據(jù)放入發(fā)送緩存器
- CE=1; //置高CE,激發(fā)數(shù)據(jù)發(fā)送
- Delayms(2);
- Return_Flag = Check_ACK(1);
- return Return_Flag;
- }
- /***************************************************************************
- 函數(shù)名稱:void NRF24L01_Init_TX(void)
- 函數(shù)功能:初始化NRF24L01
- 函數(shù)備注:在調(diào)用NRF24L01作為發(fā)射時(shí),都要先調(diào)用該函數(shù)對(duì)NRF24L01進(jìn)行初始化
- ***************************************************************************/
- void NRF24L01_Init_TX(uint8_t *ADDRn)
- {
- /*待機(jī)模式*/
- CE=0;
- CSN=1;
- SCK=0;
- /*裝載數(shù)據(jù)*/
- SPI_Write_Buf(WRITE_REG + TX_ADDR, (uint8_t*)ADDRn, TX_ADR_WIDTH);//寫TX節(jié)點(diǎn)地址
- SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, (uint8_t*)ADDRn, RX_ADR_WIDTH); //設(shè)置TX節(jié)點(diǎn)地址,主要為了使能ACK
- /*配置寄存器*/
- SPI_Write_Reg(WRITE_REG + EN_AA, 0x3f); //使能通道所有的自動(dòng)應(yīng)答
- SPI_Write_Reg(WRITE_REG + EN_RXADDR, 0x3f);//使能通道所有的接收地址
- SPI_Write_Reg(WRITE_REG + RF_CH, 40);//設(shè)置RF通道為40 收發(fā)必須一致!
- SPI_Write_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //選擇通道0的有效數(shù)據(jù)寬度
- SPI_Write_Reg(WRITE_REG + RX_PW_P1, RX_PLOAD_WIDTH); //選擇通道1的有效數(shù)據(jù)寬度
- SPI_Write_Reg(WRITE_REG + SETUP_RETR, 0xff);//自動(dòng)重發(fā) 4000+86us 重發(fā)15次
- SPI_Write_Reg(WRITE_REG + RF_SETUP, 0x0f); //設(shè)置TX發(fā)射參數(shù),0db增益,2Mbps,低噪聲增益開(kāi)啟 收發(fā)必須一致!
- SPI_Write_Reg(WRITE_REG + CONFIG, 0x0E); //配置基本工作模式的參數(shù);PWR_UP,EN_CRC,16BIT_CRC,接收模式,開(kāi)啟所有中斷
- }
- /***************************************************************************
- 函數(shù)名稱:void NRF24L01_Init_RX(void)
- 函數(shù)功能:初始化NRF24L01
- 函數(shù)備注:在調(diào)用NRF24L01作為接收時(shí),都要先調(diào)用該函數(shù)對(duì)NRF24L01進(jìn)行初始化
- ***************************************************************************/
- void NRF24L01_Init_RX(void)
- {
- /*待機(jī)模式*/
- CE=0;
- CSN=1;
- SCK=0;
- /*裝載數(shù)據(jù)*/
- SPI_Write_Buf(WRITE_REG + TX_ADDR, RX_ADDRESS, TX_ADR_WIDTH);//寫TX節(jié)點(diǎn)地址
- SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); //設(shè)置TX節(jié)點(diǎn)地址,主要為了使能ACK
- SPI_Write_Buf(WRITE_REG + RX_ADDR_P1, RX_ADDRESS1, RX_ADR_WIDTH); //設(shè)置TX節(jié)點(diǎn)地址,主要為了使能ACK
- /*配置寄存器*/
- SPI_Write_Reg(WRITE_REG + EN_AA, 0x3f);//使能通道0的自動(dòng)應(yīng)答
- SPI_Write_Reg(WRITE_REG + EN_RXADDR, 0x3f); //使能通道0的接收地址
- SPI_Write_Reg(WRITE_REG + RF_CH, 40); //設(shè)置RF通道為40 收發(fā)必須一致!
- SPI_Write_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //選擇通道0的有效數(shù)據(jù)寬度
- SPI_Write_Reg(WRITE_REG + RX_PW_P1, RX_PLOAD_WIDTH); //選擇通道1的有效數(shù)據(jù)寬度
- SPI_Write_Reg(WRITE_REG + RF_SETUP, 0x0F); //設(shè)置TX發(fā)射參數(shù),0db增益,2Mbps,低噪聲增益開(kāi)啟 收發(fā)必須一致!
- SPI_Write_Reg(WRITE_REG + CONFIG, 0x0f); //配置基本工作模式的參數(shù);PWR_UP,EN_CRC,16BIT_CRC,接收模式,開(kāi)啟所有中斷
- }
復(fù)制代碼
|
-
-
1發(fā)2發(fā)1.zip
2015-6-4 13:54 上傳
點(diǎn)擊文件名下載附件
下載積分: 黑幣 -5
309.64 KB, 下載次數(shù): 553, 下載積分: 黑幣 -5
評(píng)分
-
查看全部評(píng)分
|