完善资料让更多小伙伴认识你,还能领取20积分哦, 立即完善>
nrf24l01带数据返回的ack,并且可以实现变数据长度收发
三个缓冲区,先进先出 first in – first out,第一个截图最后说了,要是保证缓存的就是要发送的,请清除FLUSH_TX If the TX FIFO (PRX) contains more than one payload to a PTX, payloads are handled using the first in – first out principle. The TX FIFO (PRX) is blocked if all pending payloads are addressed to a PTX where the link is lost. In this case, the MCU can flush the TX FIFO (PRX) by using the FLUSH_TX command.也就是修改下面这个函数 void NRF24L01_PacketAckData(u8*pBuf,u8 Len)//发送数据包,用于发送模式2/4? { NRF24L01_CE=0; NRF24L01_Write_Buf(W_ACK_PAYLOAD,pBuf,Len); NRF24L01_CE=1; } void NRF24L01_PacketAckData(u8*pBuf,u8 Len)//发送数据包,用于发送模式2/4? { NRF24L01_CE=0; NRF24L01_Write_Reg(FLUSH_TX, 0xff); NRF24L01_Write_Buf(W_ACK_PAYLOAD,pBuf,Len); NRF24L01_CE=1; } 不过也仅限于提前装载ack数据的方案 4:参考的例子很多才搞好,参考的例子就不附带了 |
|
相关推荐
27个回答
|
|
|
|
|
|
看论坛上您对2401研究比较深,
上次关于延时滴达的问题也向您请教过, 真的是收益不少. 最近,我空闲也研究了一下2401, 有的时候真的是被它搞的很头疼, 一对一的时候问题不大, 但一对多的时候, 会莫名的失联, 其它我数传量并不大, 大概10秒多传一组32字节都行. 试验时距离近, 传输应该很通畅, 但时常会发生MAX_RT(或者是其它)的问题, 表现在通信网络不稳定, 莫名地就与某一成员失联. 有什么经验之谈或是要特别注意的问题吗? |
|
|
|
一对一问题不大是有问题还是没问题?
多对一,你这种数据量这么小,假如是单向,发送端直接发送就可以了 假如是双向,就主机轮训吧,最可靠 时常发生MAX_RT,那就是你的代码还是有问题 不过最简单的就是从机相互之间对着主机乱发,用32的数据中的某一位区分从机地址 |
|
|
|
你说的这种乱发, 是不带ACK应答的吧.
我用的是带ACK的. 基本相当于是轮询了. 比如一对二, 主机采集一些信息, 分别对两个从机进行分发, 从机各占一个地址, 主机开两个通道, 对1机发送时切换到1机地址(包括P0也同步改变) 对2机发送时切换到2机地址(包括P0也同步改变) 每一次发送结束都恢复P0和P1两个通道对两从机的接收 两个从机很少主动发信息, 偶尔发送简单控制或配置信息, 所有各终端都采用中断方式(但发送时还是等待发送结果再往下进行的) |
|
|
|
//以下为中断相关的参考例程 *************************************************************
extern unsigned char Ttmp_buf[33]; extern unsigned char Rtmp_buf[33]; u8 NRF2401_Tx_is_OK=0; u8 NRF2401_Rx_is_OK=0; u8 NRF2401_MAX_TX=0; //接受到数据后产生中断以及发送完成产生中断(或达最大重发数产生中断),中断是相对于MCU主机而言, // 对于NRF24L01只是产生一个低电平,由MCU的中断服务程序去进行相关处理 void EXTI15_10_IRQHandler(void) { // u8 temp[80]; // static u16 RxPakCt=0; //调试用, 显示记录接收包总数用 unsigned char sta; SoftDelay_us(800); //据说延时一下很重要: 在接收时,延时一下等待ACK发送完成再处理数据 //否则,在收到数据后2401正在自动发送ACK期间,此时处理数据清除RX FIFO寄存器的话,有可能 //无法再接收后续数据了 if(EXTI_GetITStatus(NRF24L01_STATUS_LINE)!=RESET) { Clr_NRF24L01_CE; LedBlinkControl=1; LED_BLINK_Timer=2;//以LED闪烁2秒(无等待延时)显示已进入一次中断; SPIx_SetSpeed(SPI_SPEED_16); //spi速度为9Mhz(24L01的最大SPI时钟为10Mhz) sta=NRF24L01_Read_Reg(STATUS); //读取状态寄存器的值 NRF24L01_Write_Reg(NRF24L01_WRITE_REG+STATUS,0x70); //清除中断标志,0x70即4/5/6位写1清除三个可能的中断 if(sta&TX_OK)//发送完成 { NRF2401_Tx_is_OK=1; NRF24L01_Write_Reg(NRF24L01_FLUSH_TX,0xff);//清除TX FIFO寄存器 RX_Mode(); //转换为收模式 SoftDelay_us(15); //粗略等待15us,不调用滴答定时器影响整体时序 } if(sta&RX_OK)//接收到数据 { NRF24L01_Read_Buf(NRF24L01_RD_RX_PLOAD,Rtmp_buf,RX_PLOAD_WIDTH);//从RX FIFO读取数据到缓存 Rtmp_buf[32]=(sta&0x0f)>>1; //接收数据的通道号保存在缓存的最末字节 //接收到数据后,通过检查该字节,就可以知道是来自哪一个节点(0-5)的报文,从而进行相关处理 NRF24L01_Write_Reg(NRF24L01_FLUSH_RX,0xff);//清除RX FIFO寄存器 NRF2401_Rx_is_OK=1; } if(sta&MAX_TX)//达到最大重发次数 { NRF2401_MAX_TX=1; //注意: NRF24L01_StatusReset(); //复位收发器状态 RX_Mode(); //转换为收模式 SoftDelay_us(15); //粗略等待15us,不调用滴答定时器影响整体时序 } Set_NRF24L01_CE;//CE为高 EXTI_ClearITPendingBit(NRF24L01_STATUS_LINE); } } |
|
|
|
对了达到MAX_TX近中断还可能就是接受还没来得及处理,你发的太快了,就会进中断,你可以把if(sta&MAX_TX)//达到最大重发次数里面价格延时10ms,给接收端反应时间,假如进MAX_TX,并不会丢数据就不用管,(例如主函数while循环,知道发成功才跳出来)发不成功就一直发,直到成功
你说的网络不稳定没描述请是丢数据还是发送不成功 |
|
|
|
我的发送程序是这样的:
void Send_Data_to_Slaver(void) { static u8 NoMasterCt=0; //发送失败计数 TX_Mode(); //切换到发射模式, 发送到地址0x31,即Slaver的接收通道1地址,同时本机的P0也置为该地址用于接收ACK NRF2401_Tx_is_OK=0; NRF2401_TimeOut=MaxDataSendTimeOut; //超时计时3秒 NRF2401_MAX_TX=0; NRF24L01_TxNoWaiting(Ttmp_buf); while(!NRF2401_Tx_is_OK) { if((!NRF2401_TimeOut) || NRF2401_MAX_TX ) //超时或达最大重发次数 { // Show_Str(0,440,400,16,"MAX_RepeatTX_Num !! ",16,0); //此句调试显示用 if(++NoMasterCt>MaxConnectingTimes) //连续5次发送失败才标记对端已失效 {NoNRF2401Receiver=1; // Show_Str(0,440,400,16,"NoNRF2401Receiver!!",16,0); //此句调试显示用 NoMasterCt=0;} break; //失败停止等待 } } if(NRF2401_TimeOut && !NRF2401_MAX_TX) //未超时或未达最大重发次数, 失败计数清0 { NoMasterCt=0; // Show_Str(0,440,400,16,"Tx is OK!!! ",16,0); //此句调试显示用 } NRF2401_Tx_is_OK=0; //发送结束产生中断后, 将会及时切换回接收模式, 故下两句略去 NRF24L01_StatusReset(); RX_Mode(); //切换回正常接收状态 // LED0_TOGGLE; //LED0翻转状态一次 } |
|
|
|
我说的不稳定是:
我在上述的发射函数中, 超时计时3秒, 当连续5次出现(超时或达最大重发次数才判定对端失效), 这个条件应该是宽松了(距离近无干扰的情况下) 但还是有可能通联1小时后, 某从机被主机标记为失联的情况, 而我觉得这是不应该发生的事情. 注意是连续5次, 只要中间有发射成功的, 5次计数清0 |
|
|
|
1:你NRF24L01_TxNoWaiting(Ttmp_buf); 发送后进while 就不发了,不知道怎么会MAX_TX,假如没发成功,超时感觉应该是必然的,不过看不到你处理NRF2401_TimeOut的代码
2:发送MAX_TX的时候,延时一会继续发,这样最好 |
|
|
|
mark,学习学习
|
|
|
|
虽然进去while 就不发了,但模块收不到ACK会自动重发,所以还是可能会发多次,甚至达到MAX_TX的
至于超时的处理, 其实我是不再重启发射(也就是本包数据丢失),但会用static变量作失败次数的累计, 当连续5次失败,则标记为对端失效, 后续的数据分发就不会轮到这个从机了. 但对该从机的接收通道一直有效, 如果该从机向主机发送一次数据, 则会重新激活对该从机的数据分发. |
|
|
|
在您的这个提示下,我又想了想,
虽然模块会自动重发, 但我的这个超时设计是不合适的 帧格式为: 前导1字节+地址3-5字节+包控制域9比特+报文0-32字节+CRC校验1-2字节 最大约42字节算50字节, 在1M速率下传输时间为400us, 自动重发间隔设置为500us+86us, 也就是说重发一次约需1ms, 这样的话, 设置为重发10次总共耗时也就10ms, 而我设计的超时是3秒, 永远不可能达到!!! 所以, 结果可能正好和您说的相反, 如果发送不成功, 必然是MAX_TX. 我那个超时设计完全是个笑话. 所以跳出这个while, 只能有两种情况: 一是发送成功; 二是MAX_TX已达. |
|
|
|
是的,发送不成功必然会MAX_TX,一般是在MAX_TX时给个延时,这次发送失败了就等会再发再试一下,不然可能还是MAX_TX
还有一种情况是,接收端处理不过来fifo在满着也会发送失败,不过你这频率低又是中断处理应该不会出现这种情况 最好的双向通讯,数据量不大就用带数据的ack,这样不用来回切换收发,减少出错 |
|
|
|
是啊, 可能带数据的ACK效率比较高,改天我也试一试.
但我还是一直疑惑我的错误在什么地方? 我上面的程序中,其实出现MAX_TX我就不再发送该数据了(即允许了丢包) 并且连续5次失败才标记对端失效, 应该相当宽松了, 注意是连续!!! 用的是static变量, 这5次可是不同的数据包, 这些不同的数据包之间可能也有比较大的间隔的 |
|
|
|
请教一下, 你上传的代码中,
下面这两句是什么意思? NRF24L01_ReadWriteByte(0x50); NRF24L01_ReadWriteByte(0x73); |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
我看的是共78页的英文手册
|
|
|
|
只有小组成员才能发言,加入小组>>
如何使用STM32+nrf24l01架构把有线USB设备无线化?
2458 浏览 7 评论
请问能利用51单片机和nRF24L01模块实现实时语音无线传输吗?
2232 浏览 5 评论
3001 浏览 3 评论
2683 浏览 8 评论
为什么ucosii上移植lwip后系统进入了HardFault_Handler?
2653 浏览 4 评论
请教各位大咖:有没有接收频率32M左右的芯片推荐的?先感谢啦!
437浏览 1评论
706浏览 0评论
780浏览 0评论
487浏览 0评论
297浏览 0评论
小黑屋| 手机版| Archiver| 电子发烧友 ( 湘ICP备2023018690号 )
GMT+8, 2024-9-1 07:32 , Processed in 1.189046 second(s), Total 83, Slave 76 queries .
Powered by 电子发烧友网
© 2015 bbs.elecfans.com
关注我们的微信
下载发烧友APP
电子发烧友观察
版权所有 © 湖南华秋数字科技有限公司
电子发烧友 (电路图) 湘公网安备 43011202000918 号 电信与信息服务业务经营许可证:合字B2-20210191