|
最近在接了一个项目,要求各个设备能够联网(不是互联网)控制。nrf24l01刚好有这个功能。但是之前只做过一对一的通信,还是用例程的那一种。我在想,用两个地址,共用同一个通道应该也可以完成。后来他又要求发过去的数据还要能回传,这下我只好来研究多通道通信了。
多机通信和一对一通信基本上相同,就是要配置其他通道的地址和使能其他通道的有效数据宽度,还有自动应答。
这是接收机的:
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共存的,所以注释复制过来之后就成了乱码,在此贴图一张:
NRF24L01_Init_Rx(void)
下面就到了发送机了的配置了:
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)
发送给其他通道,只要改成其他通道的地址就可以了,不用改通道号,现在还不知道为什么。
接下来就是发送函数:
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;
}
由于我是通过电脑串口控制上位机,发给某一个下位机,然后再发回到我的上位机中,最后回传到电脑,所以没有数据抢答的问题。
最后再说一句,要配置第N个的通道,前N个通道也必须被配置,要不然配置不成功。
最后贴上上位机程序:
- #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状态标志位************************************************/
- uint8_t bdata sta;
- sbit RX_DR =sta^6;
- sbit TX_DS =sta^5;
- sbit MAX_RT =sta^4;
- /**********************************NRF24L01管脚与单片机接口定义**************************************/
- sbit MISO =P3^4;
- sbit MOSI =P3^6;
- sbit SCK =P3^3;
- sbit CE =P3^2;
- sbit CSN =P3^5;
- sbit IRQ =P3^7;
- /***************************************************************************
- 函数名称:uchar SPI_RW(uint8_t dat)
- 函数功能:NRF24L01的SPI写时序
- 函数备注:
- ***************************************************************************/
- 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);
- }
- /***************************************************************************
- 函数名称:uint8_t SPI_Read(uint8_t cmd_reg)
- 函数功能:NRF24L01的SPI读时序
- 函数备注:
- ***************************************************************************/
- 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);
- }
- /***************************************************************************
- 函数名称:void SPI_Write_Reg(uint8_t cmd_reg, uint8_t value)
- 函数功能:写入NRF24L01寄寄存器和从NRF24L01寄存器中读出
- 函数备注:
- ***************************************************************************/
- void SPI_Write_Reg(uint8_t cmd_reg, uint8_t value)
- {
- CSN = 0;
- SPI_RW(cmd_reg);
- SPI_RW(value);
- CSN = 1;
- }
- /***************************************************************************
- 函数名称:uint8_t SPI_Read_Buf(uint8_t cmd_reg, uint8_t *pBuf, uint8_t num)
- 函数功能:从NRF24L01寄存器中读出数据
- 函数备注:reg:为寄存器地址,pBuf:为待读出数据地址,uint8_t:读出数据的个数
- ***************************************************************************/
- 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);
- }
- /***************************************************************************
- 函数名称:void SPI_Write_Buf(uint8_t cmd_reg, uint8_t *pBuf, uint8_t num)
- 函数功能:在NRF24L01寄存器中写入数据
- 函数备注:reg:为寄存器地址,pBuf:为待写入数据地址,uint8_t:写入数据的个数
- ***************************************************************************/
- 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; //关闭SPI
- }
- /***************************************************************************
- 函数名称:uint8_t nRF24L01_RxPacket(uint8_t* rx_buf)
- 函数功能:数据读取后放入rx_buf接收缓冲区中
- 函数备注:
- ***************************************************************************/
- uint8_t nRF24L01_RxPacket(uint8_t* rx_buf)
- {
- uint8_t flag;
- CE = 1; //很重要!启动接收!
- Delayms(1);
- sta=SPI_Read(READ_REG+STATUS); // 读取状态寄存其来判断数据接收状况 //寄存器前面要加是读还是写
- if(RX_DR) // 判断是否接收到数据 如果置1则说明接到数据并且放置在接收缓存器
- {
- CE = 0;
- SPI_Read_Buf(RD_RX_PLOAD,rx_buf,RX_PLOAD_WIDTH); //这本来就是指令,不用加,意思说去缓存器里读
- flag =1; //读取数据完成标志
- }
- SPI_Write_Reg(WRITE_REG+STATUS,sta); //接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标志
- return flag;
- }
- /**************************************************
- 函数:Check_ACK(bit clear)
- 描述:检查接收设备有无接收到数据包,设定没有收到应答信
- 号是否重发
- /**************************************************/
- uint8_t Check_ACK(bit clear)
- {
- while(IRQ);
- sta = SPI_RW(NOP); // 返回状态寄存器
- if(MAX_RT)
- if(clear) // 是否清除TX FIFO,没有清除在复位MAX_RT中断标志后重发
- SPI_RW(FLUSH_TX); //清空寄存器,很重要!!!
- SPI_Write_Reg(WRITE_REG + STATUS, sta); // 清除TX_DS或MAX_RT中断标志
- IRQ = 1;
- if(TX_DS)
- return(0x01);
- else
- return(0x00);
- }
- /***************************************************************************
- 函数名称:void nRF24L01_TxPacket(unsigned char * tx_buf)
- 函数功能:发送 tx_buf中数据
- 函数备注:
- ***************************************************************************/
- 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); // 装载数据 WR_TX_PLOAD本来就是指令 不用加 将数据放入发送缓存器
- CE=1; //置高CE,激发数据发送
- Delayms(2);
- Return_Flag = Check_ACK(1);
- return Return_Flag;
- }
- /***************************************************************************
- 函数名称:void NRF24L01_Init_TX(void)
- 函数功能:初始化NRF24L01
- 函数备注:在调用NRF24L01作为发射时,都要先调用该函数对NRF24L01进行初始化
- ***************************************************************************/
- 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);//写TX节点地址
- SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, (uint8_t*)ADDRn, RX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACK
- /*配置寄存器*/
- SPI_Write_Reg(WRITE_REG + EN_AA, 0x3f); //使能通道所有的自动应答
- SPI_Write_Reg(WRITE_REG + EN_RXADDR, 0x3f);//使能通道所有的接收地址
- SPI_Write_Reg(WRITE_REG + RF_CH, 40);//设置RF通道为40 收发必须一致!
- SPI_Write_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //选择通道0的有效数据宽度
- SPI_Write_Reg(WRITE_REG + RX_PW_P1, RX_PLOAD_WIDTH); //选择通道1的有效数据宽度
- SPI_Write_Reg(WRITE_REG + SETUP_RETR, 0xff);//自动重发 4000+86us 重发15次
- SPI_Write_Reg(WRITE_REG + RF_SETUP, 0x0f); //设置TX发射参数,0db增益,2Mbps,低噪声增益开启 收发必须一致!
- SPI_Write_Reg(WRITE_REG + CONFIG, 0x0E); //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式,开启所有中断
- }
- /***************************************************************************
- 函数名称:void NRF24L01_Init_RX(void)
- 函数功能:初始化NRF24L01
- 函数备注:在调用NRF24L01作为接收时,都要先调用该函数对NRF24L01进行初始化
- ***************************************************************************/
- void NRF24L01_Init_RX(void)
- {
- /*待机模式*/
- CE=0;
- CSN=1;
- SCK=0;
- /*装载数据*/
- SPI_Write_Buf(WRITE_REG + TX_ADDR, RX_ADDRESS, TX_ADR_WIDTH);//写TX节点地址
- SPI_Write_Buf(WRITE_REG + RX_ADDR_P0, RX_ADDRESS, RX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACK
- SPI_Write_Buf(WRITE_REG + RX_ADDR_P1, RX_ADDRESS1, RX_ADR_WIDTH); //设置TX节点地址,主要为了使能ACK
- /*配置寄存器*/
- SPI_Write_Reg(WRITE_REG + EN_AA, 0x3f);//使能通道0的自动应答
- SPI_Write_Reg(WRITE_REG + EN_RXADDR, 0x3f); //使能通道0的接收地址
- SPI_Write_Reg(WRITE_REG + RF_CH, 40); //设置RF通道为40 收发必须一致!
- SPI_Write_Reg(WRITE_REG + RX_PW_P0, RX_PLOAD_WIDTH); //选择通道0的有效数据宽度
- SPI_Write_Reg(WRITE_REG + RX_PW_P1, RX_PLOAD_WIDTH); //选择通道1的有效数据宽度
- SPI_Write_Reg(WRITE_REG + RF_SETUP, 0x0F); //设置TX发射参数,0db增益,2Mbps,低噪声增益开启 收发必须一致!
- SPI_Write_Reg(WRITE_REG + CONFIG, 0x0f); //配置基本工作模式的参数;PWR_UP,EN_CRC,16BIT_CRC,接收模式,开启所有中断
- }
复制代码
|
评分
-
查看全部评分
|