nrf24l01各通道频率多个接收通道数据存放问题

7652人阅读
实践中用到的
1、一个发送通道,6个接收通道。发送端发送通道地址寄存器中的地址指向的就是接收端哪个接收通道接收发送端的数据,所以发送端地址寄存器的值要与接收端需要接受数据的通道地址相同。
看一下无线数据传输的数据帧格式
第二部分的地址,就是接收端接收数据的通道地址,这个地址由发送端TX_ADDR寄存器搞定。
2、必须要搞清楚发送地址和接收地址的意义。下面两端描述的是一个意思。我的两次理解。
要先搞清楚TX_ADD和RRX_ADDR_PX。TX_ADD就一个,是发送数据帧格式中发送的地址信息,如上1所示,这个地址指定了向接收端接收数据通道的地址。
发送端的职责:1、发送:发送数据给接收端。2接收:接收某接收端的应答信号。
接收端的职责:1、接收:接收发送端发送的数据。2发送:发送应答信号给发送端。
所以整个过程发送端接收端都有发送和接收的功能。只是发送和接收的东西不一样。
NRF24L01发送端把数据发送给接收端,接收端在确认收到数据后记录发送端的地址,并以此地址为目标地址发送应答信号(这个是自动的,不是程序设置的,应属于硬件实现),(就是说接收端的发送地址寄存器TX_ADDR中存的地址就是发送端TX_ADDR中的地址,而发送端要以又要用通道0来接收应答,所以需要将通道0的地址设置为该地址,即发送端TX_ADDR中的值)。在发送端,数据通道0被用作接收应答信号,因此发送端通道0的接收地址要与发送地址端地址相等,以确保接收到正确的应答信号。
注意每个NRF24L01只有一个发送通道,用来指示向接收端NRF24l01的哪个接收通道发送数据,即TX_ADDR(即只有一个发送目标地址寄存器)不要被TX5迷惑,这里5是指第五个NRF24l01.但一个NRF24L01是有6个接收通道的,每个通道有自己的地址。所以一个2401可以接收6个2401发送来的数据。在发送模式下,发送端的2401会用自己接收通道0来接受 接收端的2401发送来的相应信号。但是接收端的2401发送应答信号的时候,也发送的地址就是接收端的某个接受通道的地址。所以发送端的接收通道0的地址要设置成这个地址。
TX5:TX_ADDR=0xB3B4B5B605
TX5:RX_ADDR_P0=0xB3B4B5B605
RX:RX_ADDR_P5=0xB3B4B5B605
两种数据双方向的通讯方式:
如果想要数据在双方向上通讯,PRIM_RX&寄存器必须紧随芯片工作模式的变化而变化。处理器必须保证PTX和PRX端的同步性。在RX_FIFO和TX_FIFO寄存器中可能同时存有数据。
另外还有自己的查阅的一些资料:
这是使用手册上的关于地址的图。
对于发送方他的Rx通道0要和他的发送地址配成一样的。对于接收方0~6必有的哥通道的地址配置为发送发的地址。就是其实所有的地址都是自己设置的,但是要配对的进行设置。
也有人这样理解:
发送方发送了一段代码,代码中携带地址(看做代码的身份证),
接收方接收代码,但接受方设置成了只接收特定身份代码的数据,也就是主机TX_ADDR和从机RX_ADDR要求设置成相同的原因吧。
从机接受完数据之后,将应答信号还发送给刚才设置的那个地址,
主机还是只识别与发送数据时携带的地址相同的数据。
其实,这么理解之后,发现主机和从机根本就没有地址,只是数据携带的地址(数据的身份证)将主机和从机联系起来的。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:48801次
排名:千里之外
转载:17篇
评论:15条
(3)(4)(2)(4)(1)(1)(1)(3)查看: 310|回复: 2
51 NRF24L01 收到的数据都是0 大神帮忙看下
发送端主函数& && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && && &&&
void main(void)
nRF24L01_Init();//NRF24L01初始化
&&DhtReadData();& &//读取传感器的数据&&这个函数没有问题的。
TX_Buffer[0]=H
nRF24L01_Set_TX_Mode(TX_Buffer);//发送数据
while(Check_Ack());//等待发送完成
delay_ms(2000);
接收端主函数
void main(void)
nRF24L01_Init();//NRF24L01初始化
ini_1602();
ini_play();
nRF24L01_Set_RX_Mode();
& &if(nRF24L01_RX_Data())
& & w_num(RX_Buffer[0]);& &
&&Buzzer_P=0;
&&delay_ms(150);
&&Buzzer_P=1;
delay_ms(2000);
收发模式设置的函数应该都没有问题吧& &我觉得。
//设置发送模式
void nRF24L01_Set_TX_Mode(uchar *TX_Data)
CE=0;//待机(写寄存器之前一定要进入待机模式或掉电模式)
SPI_W_DBuffer(W_REGISTER+TX_ADDR,TX_Addr,TX_ADDR_WITDH);//写寄存器指令+接收节点地址+地址宽度
SPI_W_DBuffer(W_REGISTER+RX_ADDR_P0,TX_Addr,TX_ADDR_WITDH);//为了接收设备应答信号,接收通道0地址与发送地址相同
SPI_W_DBuffer(W_TX_PLOAD,TX_Data,TX_DATA_WITDH);//写有效数据地址+有效数据+有效数据宽度
SPI_W_Reg(W_REGISTER+EN_AA,0x01);//接收通道0自动应答
SPI_W_Reg(W_REGISTER+EN_RX_ADDR,0x01);//使能接收通道0
SPI_W_Reg(W_REGISTER+SETUP_RETR,0x0a);//自动重发延时250US+86US,重发10次
SPI_W_Reg(W_REGISTER+RF_CH,0);//2.4GHZ
SPI_W_Reg(W_REGISTER+RF_SETUP,0x07);//1Mbps速率,发射功率:0DBM,低噪声放大器增益
SPI_W_Reg(W_REGISTER+CONFIG,0x0e);//发送模式,上电,16位CRC校验,CRC使能
CE=1;//启动发射
_delay_ms(5);//CE高电平持续时间最少10US以上
//检测应答信号
uchar Check_Ack(void)
sta=SPI_R_byte(R_REGISTER+STATUS);//读取寄存状态
if(TX_DS||MAX_RT)//如果TX_DS或MAX_RT为1,则清除中断和清除TX_FIFO寄存器的值
SPI_W_Reg(W_REGISTER+STATUS,0xff);
SPI_RW(FLUSH_TX);//如果没有这一句只能发一次数据,大家要注意
//接受模式
void nRF24L01_Set_RX_Mode(void)
CE=0;//待机
// SPI_W_DBuffer(W_REGISTER+TX_ADDR,TX_Addr,TX_ADDR_WITDH);
SPI_W_DBuffer(W_REGISTER+RX_ADDR_P0,TX_Addr,TX_ADDR_WITDH);
SPI_W_Reg(W_REGISTER+EN_AA,0x01);
SPI_W_Reg(W_REGISTER+EN_RX_ADDR,0x01);
SPI_W_Reg(W_REGISTER+SETUP_RETR,0x0a);
SPI_W_Reg(W_REGISTER+RX_PW_P0,RX_DATA_WITDH);
SPI_W_Reg(W_REGISTER+RF_CH,0);
SPI_W_Reg(W_REGISTER+RF_SETUP,0x07);
SPI_W_Reg(W_REGISTER+CONFIG,0x0f);
_delay_ms(5);
uchar nRF24L01_RX_Data(void)
sta=SPI_R_byte(R_REGISTER+STATUS);
SPI_R_DBuffer(R_RX_PLOAD,RX_Buffer,RX_DATA_WITDH);
SPI_W_Reg(W_REGISTER+STATUS,0xff);
SPI_RW(FLUSH_RX);
小弟看了好几天了& &不知道问题在哪里。本来就是想要把A系统采集的数据发送到B系统显示& & 结果B系统收到的数据都是0’
代码如上& &希望大神指点一二。感激不尽
 现在发送和接受的状态指示灯有变化吗?没有就把发送的延时适当延长试试。_delay_ms(5);加到200.试试
 楼主,你问题解决没,我遇到和你同样的问题,想向你请教一下
Powered by2013年4月 硬件/嵌入开发大版内专家分月排行榜第二2007年9月 硬件/嵌入开发大版内专家分月排行榜第二
2013年5月 硬件/嵌入开发大版内专家分月排行榜第三2012年9月 硬件/嵌入开发大版内专家分月排行榜第三2007年11月 硬件/嵌入开发大版内专家分月排行榜第三
本帖子已过去太久远了,不再提供回复功能。后使用快捷导航没有帐号?
来自ValentinRuhry的创意,这哥们用整整500
求助!!!nrf24l01接收不到数据后怎么让小车停下来
#include &reg52.h&
#include &intrins.h&
#define U8&&unsigned char
#define U16 unsigned int
#define TX_ADDR_WITDH 5 //发送地址宽度设置为5个字节
#define RX_ADDR_WITDH 5 //接收地址宽度设置为5个字节
#define TX_DATA_WITDH 1//发送数据宽度1个字节
#define RX_DATA_WITDH 1//接收数据宽度1个字节
#define&&R_REGISTER& && &0x00//读取配置寄存器
#define&&W_REGISTER& && &0x20//写配置寄存器
#define&&R_RX_PAYLOAD& &0x61//读取RX有效数据
#define&&W_TX_PAYLOAD&&0xa0//写TX有效数据
#define&&FLUSH_TX& &0xe1//清除TXFIFO寄存器
#define&&FLUSH_RX& &0xe2//清除RXFIFO寄存器
#define&&REUSE_TX_PL& &&&0xe3//重新使用上一包有效数据
#define&&NOP& && && && & 0xff//空操作
#define&&CONFIG& && && & 0x00//配置寄存器
#define&&EN_AA& & 0x01//使能自动应答
#define&&EN_RXADDR& && & 0x02//接收通道使能0-5个通道
#define&&SETUP_AW& && &&&0x03//设置数据通道地址宽度3-5
#define&&SETUP_RETR& && &0x04//建立自动重发
#define&&RF_CH& && && &&&0x05//射频通道设置
#define&&RF_SETUP& && &&&0x06//射频寄存器
#define&&STATUS& && && & 0x07//状态寄存器
#define&&OBSERVE_TX& && &0x08//发送检测寄存器
#define&&CD& && && && &&&0x09//载波
#define&&RX_ADDR_P0& && &0x0a//数据通道0接收地址
#define&&RX_ADDR_P1& && &0x0b//数据通道1接收地址
#define&&RX_ADDR_P2& && &0x0c//数据通道2接收地址
#define&&RX_ADDR_P3& && &0x0d//数据通道3接收地址
#define&&RX_ADDR_P4& && &0x0e//数据通道4接收地址
#define&&RX_ADDR_P5& && &0x0f//数据通道5接收地址
#define&&TX_ADDR& && && &0x10//发送地址
#define&&RX_PW_P0& && &&&0x11//P0通道数据宽度设置
#define&&RX_PW_P1& && &&&0x12//P1通道数据宽度设置
#define&&RX_PW_P2& && &&&0x13//P2通道数据宽度设置
#define&&RX_PW_P3& && &&&0x14//P3通道数据宽度设置
#define&&RX_PW_P4& && &&&0x15//P4通道数据宽度设置
#define&&RX_PW_P5& && &&&0x16//P5通道数据宽度设置
#define&&FIFO_STATUS& &&&0x17//FIFO状态寄存器
//NRF24L01
U8 NRFACK();
U8 NRFSPI(U8 date);
U8 NRFReadReg(U8 RegAddr);
U8 NRFWriteReg(U8 RegAddr,U8 date);
U8 NRFReadRxDate(U8 RegAddr,U8 *RxDate,U8 DateLen);
U8 NRFWriteTxDate(U8 RegAddr,U8 *TxDate,U8 DateLen);
U8 NRFRevDate(U8 *RevDate);
void NRFSetTxMode(U8 *TxDate);
void NRF24L01Int();
void NRFSetRXMode();
U8 CheckACK();
void Delay(U16 t);
void Delay_10ms(U16 del);
sbit CE =&&P1^0;
sbit CSN=&&P1^1;
sbit SCLK=&&P1^2;
sbit MOSI= P1^3;
sbit MISO= P1^4;
sbit IRQ = P1^5;
//sbit KEY=P3^4;
//sbit KEY1=P3^5;
//sbit KEY2=P3^6;
//sbit KEY3=P3^7;
U8 code TxAddr[]={0x34,0x43,0x10,0x10,0x01};//发送地址
U8& &//状态标志
sbit RX_DR=sta^6;
sbit TX_DS=sta^5;
sbit MAX_RT=sta^4;
void Delay(U16 t)
&&U16 x,y;
&&for(x=t;x&0;x--)
& &for(y=110;y&0;y--);
U8 NRFSPI(U8 date)
{& && && && && && && && && && && && && && && &
& & for(i=0;i&8;i++)& && && & // 循环8次
& &if(date&0x80)
& &&&MOSI=1;
& &&&MOSI=0;& &// byte最高位输出到MOSI
& && &date&&=1;& && && && & // 低一位移位到最高位
& && &SCLK=1;
& &if(MISO)& && && && && &// 拉高SCK,nRF24L01从MOSI读入1位数据,同时从MISO输出1位数据
& && &&&date|=0x01;& && &&&// 读MISO到byte最低位
& && &SCLK=0;& && && && & // SCK置低
& & return(date);& && && && &// 返回读出的一字节
void NRF24L01Int()
Delay(2);//让系统什么都不干
CE=0; //待机模式1&&
U8 NRFReadReg(U8 RegAddr)
& &U8 BackD
& &CSN=0;//启动时序
& &NRFSPI(RegAddr);//写寄存器地址
& &BackDate=NRFSPI(0x00);//写入读寄存器指令
& &return(BackDate); //返回状态
U8 NRFWriteReg(U8 RegAddr,U8 date)
& &U8 BackD
& &CSN=0;//启动时序
& &BackDate=NRFSPI(RegAddr);//写入地址
& &NRFSPI(date);//写入值
& &return(BackDate);
U8 NRFReadRxDate(U8 RegAddr,U8 *RxDate,U8 DateLen)
{&&//寄存器地址//读取数据存放变量//读取数据长度//用于接收
& & U8 BackDate,i;
CSN=0;//启动时序
BackDate=NRFSPI(RegAddr);//写入要读取的寄存器地址
for(i=0;i&DateLi++)
& && &RxDate=NRFSPI(0);
& & CSN=1;
& &return(BackDate);
U8 NRFWriteTxDate(U8 RegAddr,U8 *TxDate,U8 DateLen)
{ //寄存器地址//写入数据存放变量//读取数据长度//用于发送
& &U8 BackDate,i;
& &BackDate=NRFSPI(RegAddr);//写入要写入寄存器的地址
& &for(i=0;i&DateLi++)
& &&&NRFSPI(*TxDate++);
& &return(BackDate);
void NRFSetTxMode(U8 *TxDate)
{//发送模式
& & NRFWriteTxDate(W_REGISTER+TX_ADDR,TxAddr,TX_ADDR_WITDH);//写寄存器指令+接收地址使能指令+接收地址+地址宽度
NRFWriteTxDate(W_REGISTER+RX_ADDR_P0,TxAddr,TX_ADDR_WITDH);//为了应答接收设备,接收通道0地址和发送地址相同
NRFWriteTxDate(W_TX_PAYLOAD,TxDate,TX_DATA_WITDH);//写入数据
& &NRFWriteReg(W_REGISTER+EN_AA,0x01);& && & // 使能接收通道0自动应答
& &NRFWriteReg(W_REGISTER+EN_RXADDR,0x01);& &// 使能接收通道0
& &NRFWriteReg(W_REGISTER+SETUP_RETR,0x0a);&&// 自动重发延时等待250us+86us,自动重发10次
& &NRFWriteReg(W_REGISTER+RF_CH,0x40);& && && &// 选择射频通道0x40
& &NRFWriteReg(W_REGISTER+RF_SETUP,0x07);& & // 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益
NRFWriteReg(W_REGISTER+CONFIG,0x0e);& && &// CRC使能,16位CRC校验,上电
Delay(5);//保持10us秒以上
//主要接收模式
void NRFSetRXMode()
& &NRFWriteTxDate(W_REGISTER+RX_ADDR_P0,TxAddr,TX_ADDR_WITDH);&&// 接收设备接收通道0使用和发送设备相同的发送地址
& &NRFWriteReg(W_REGISTER+EN_AA,0x01);& && && && && &// 使能接收通道0自动应答
& &NRFWriteReg(W_REGISTER+EN_RXADDR,0x01);& && && &&&// 使能接收通道0
& &NRFWriteReg(W_REGISTER+RF_CH,0x40);& && && && && &&&// 选择射频通道0x40
& &NRFWriteReg(W_REGISTER+RX_PW_P0,TX_DATA_WITDH);&&// 接收通道0选择和发送通道相同有效数据宽度
& &NRFWriteReg(W_REGISTER+RF_SETUP,0x07);& && && && &// 数据传输率1Mbps,发射功率0dBm,低噪声放大器增益*/
& &NRFWriteReg(W_REGISTER+CONFIG,0x0f);& && && && &&&// CRC使能,16位CRC校验,上电,接收模式
& &CE = 1;
Delay(5);//保持10us秒以上& &
U8 CheckACK()
{&&//用于发射
sta=NRFReadReg(R_REGISTER+STATUS);& && && && && && &&&// 返回状态寄存器
if(TX_DS||MAX_RT) //发送完毕中断
& & NRFWriteReg(W_REGISTER+STATUS,0xff);&&// 清除TX_DS或MAX_RT中断标志
& & CSN=0;
& & NRFSPI(FLUSH_TX);//用于清空FIFO !!关键!!不然会出现意想不到的后果!!!大家记住!!
& && & CSN=1;
& & return(0);
& & return(1);
//用于接收模式
U8 NRFRevDate(U8 *RevDate)
& &&&U8 RevFlags=0;
&&sta=NRFReadReg(R_REGISTER+STATUS);//发送数据后读取状态寄存器
& &&&if(RX_DR)& & // 判断是否接收到数据
& &&&CE=0;& & //SPI使能
&&NRFReadRxDate(R_RX_PAYLOAD,RevDate,RX_DATA_WITDH);// 从RXFIFO读取数据
&&RevFlags=1;& & //读取数据完成标志
&&NRFWriteReg(W_REGISTER+STATUS,0xff); //接收到数据后RX_DR,TX_DS,MAX_PT都置高为1,通过写1来清楚中断标
&&return(RevFlags);
void Delay_10ms(U16 del)
for(i=0; i& i++)
for(j=0; j&1827; j++)& &&&//这个是通过软件仿真得出的数
U8 TxDate[1]={0};
NRF24L01Int();
switch (K)
& & & & case 0x7f:& &
& & & & Delay_10ms(2);
& & TxDate[0]=0x08;//发射按键标识值
& & NRFSetTxMode(TxDate);
& & while(CheckACK());
& & TxDate[0]=0;
& & & & case 0xbf:
& & & & Delay_10ms(2);
& & TxDate[0]=0x09;//发射按键标识值
& & NRFSetTxMode(TxDate);
& & while(CheckACK());
& & TxDate[0]=0;
& & & & case 0xdf:
& & & & Delay_10ms(2);
& & TxDate[0]=0x10;//发射按键标识值
& & NRFSetTxMode(TxDate);
& & while(CheckACK());
& & TxDate[0]=0;
& & & & case 0xef:
& & & & Delay_10ms(2);
& & TxDate[0]=0x0a;//发射按键标识值
& & NRFSetTxMode(TxDate);
& & while(CheckACK());
& & TxDate[0]=0;
& & & & case 0xff://不按任何键是一直发送数据的
& & & & Delay_10ms(2);
& & TxDate[0]=0x0b;//发射按键标识值
& & NRFSetTxMode(TxDate);
& & while(CheckACK());
& & TxDate[0]=0;
U8 RxBuf[1]={0};
NRF24L01Int();
Delay(60);
& &NRFSetRXMode();
&&NRFRevDate(RxBuf);
&&x=RxBuf[0];
//&&if(!RX_DR)
//& & & & stop();
//&&& & & & RxBuf[0]=0;&&
//&&}& & & & & & & &
&&if(x==0x08)//0x08为发射部分所发送的按键标识
& & & & go();
&&& & & & RxBuf[0]=0;
& & & && &&&
&&& & & & if(x==0x0b)
&&& & & & {
& & & & stop();
&&& & & & RxBuf[0]=0;
&&& & & & }
if(x==0x09)//0x08为发射部分所发送的按键标识
& & & & back();
&&& & & & RxBuf[0]=0;
&&if(x==0x10)//为发射部分所发送的按键标识
& & & & left();
&&& & & & RxBuf[0]=0;
& & & && &
&&if(x==0x0a)//发射部分所发送的按键标识
& & & & right();
&&& & & & RxBuf[0]=0;
& & & && &&&
&&}& & & &
& & if(x==0x0b)
&&& & & & {
& & & & stop();
&&& & & & RxBuf[0]=0;
&&& & & & }
& && &CSN=0;
& & NRFSPI(FLUSH_RX);//用于清空FIFO&&
& && & CSN=1;
补充:怎么在任何一个模块坏了或者接收不到信号后怎么让小车停下来
延时不需要太多,只要足够他反应的时间即可,本来通信就要判断的,开个定时器不就行了?和延时一样啊,这样哈
看花开花落 发表于
如果用延时函数判断的话肯定会影响程序运行的效率,如果用计时器的话,我也不知道怎么编程
延时不需要太多,只要足够他反应的时间即可,本来通信就要判断的,开个定时器不就行了?和延时一样啊,这样哈
没细看,主要是我还要复习,给个思路吧,现在最有效的是反馈,怎么知道你收没收到,你回个信就好了,每次发送信息完毕,就等待对方返回数据,收到标志,比如约定发送@_@表示通信成功,收到后处理即可,如果超时没有收到,则判定通信失败等等,思路而已,希望可以帮到你
gazelle 发表于
没细看,主要是我还要复习,给个思路吧,现在最有效的是反馈,怎么知道你收没收到,你回个信就好了,每次发 ...
如果用延时函数判断的话肯定会影响程序运行的效率,如果用计时器的话,我也不知道怎么编程
表示同意楼上意见
如果突然接收不到数据了,让小车停下来,还真是个难题,暂时没有主意
等楼下高手
看花开花落 发表于
如果用延时函数判断的话肯定会影响程序运行的效率,如果用计时器的话,我也不知道怎么编程
whille(int&&i=10000&&flag ==0)
我用C#写的,您应该能理解,实际上I随便你去多大,标志位一到,立马走了,没到延时就要执行完毕,所以呢,延时药取得妙啊
gazelle 发表于
whille(int&&i=10000&&flag ==0)
好的,明天我到实验室试试去,谢谢超版
着东西不懂只能帮忙顶下
ozhaojie 发表于
着东西不懂只能帮忙顶下
谢谢啦。。。。。。
gazelle 发表于
延时不需要太多,只要足够他反应的时间即可,本来通信就要判断的,开个定时器不就行了?和延时一样啊,这 ...
超版,功能已经实现,谢谢超版的建议,我用的就是定时器,定时器2S产生中断,中断开始检测flag
Copyright &
Powered by

我要回帖

更多关于 nrf24l01多通道 的文章

 

随机推荐