目录

NRF24L01+硬件资源

工作模式

接收地址与发送地址的理解

一对一模式(一收一发)

多对一模式(六发一收)

使用ACK自动回复带数据功能


NRF24L01+硬件资源

运行条件:

电压:最小值=1.9V;典型值=3.0V;最大值=3.6V; 有一些反映不小心接入5V的电,烧模块,只是经验,值得注意。如果要接入5V,需要使用电阻进行分压,可通过U=RI进行计算。 工作温度:-40℃——85℃。典型值=27℃

工作模式

上电之后,要等待100ms的时间让其渡过上电不稳定状态,进入TX/RX模式时,有130微秒的等待时间,一定要让PLL准备好,不然数据有可能乱码。

下图中,黑色粗框是官方推荐的模式转换线路,虚框是过渡状态,该状态下一定会转换到下一个状态。

接收地址与发送地址的理解

PTX端(发射端)需要用到的地址:TX_ADDR和RX_ADDR_P0。(使用P0通道进行通信,使用其他通道x,地址就写:RX_ADDR_Px。)

PRX端(接收端)需要用到的地址:RX_ADDR_P0。(使用P0通道进行通信或者Px)

PTX的职责:1、发送数据给接收端(PRX);2、接收PRX的应答信号(ACK)

PRX的职责:1、接收发送端的发送数据;2、发送应答信号(ACK)给PTX

所以:

①当我们写入5个字节的地址在TX_ADDR中时,PTX以TX_ADDR中的地址为目标,把FIFO中的数据发送到空中;

②PRX在空中收到信号后,把目的地址拿出来与RX_ADDR_P0中的地址对比(自动进行),匹配则说明时发送给自己的,并接收;

③PRX通道RX_ADDR_P0回复ACK;

④PTX接收ACK,目的地址与自身的RX_ADDR_P0对比,一致,则说明ACK发送给自己,最后确认收到ACK应答信号,通讯完成。

一对一模式(一收一发)

拿stm32f103为例,其他芯片可以参考其思路。

1、启用外设时钟:SPI1、GPIOA、AFIO(开启中断时)、USART1(使用串口时)

2、初始化SPI1的IO引脚,外部中断,串口

void GPIO_SPI1_Init(void)                         //SPI1引脚初始化
{GPIO_InitTypeDef pa;pa.GPIO_Mode=GPIO_Mode_AF_PP;                 //SCK(pa5)、MOSI(pa7)推挽复用pa.GPIO_Pin=GPIO_Pin_5|GPIO_Pin_7;pa.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&pa);pa.GPIO_Mode=GPIO_Mode_IPU;pa.GPIO_Pin=GPIO_Pin_6|GPIO_Pin_1;            //MISO(pa6)、IRQ(pa1)上拉输入pa.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&pa);pa.GPIO_Mode=GPIO_Mode_Out_PP;pa.GPIO_Pin=GPIO_Pin_2|GPIO_Pin_4;            //CE(pa2)、CSN(pa4)推挽输出pa.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&pa);GPIO_SetBits(GPIOA,GPIO_Pin_7|GPIO_Pin_4);GPIO_ResetBits(GPIOA,GPIO_Pin_5);
}
void EXTI1_Init(void)                   //外部中断初始化相关
{EXTI_InitTypeDef exti1;NVIC_InitTypeDef nvic;NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);GPIO_EXTILineConfig(GPIO_PortSourceGPIOA,GPIO_PinSource1);exti1.EXTI_Line=EXTI_Line1;exti1.EXTI_LineCmd=ENABLE;exti1.EXTI_Mode=EXTI_Mode_Interrupt;exti1.EXTI_Trigger=EXTI_Trigger_Falling;EXTI_Init(&exti1);nvic.NVIC_IRQChannel=EXTI1_IRQn;nvic.NVIC_IRQChannelCmd=ENABLE;nvic.NVIC_IRQChannelPreemptionPriority=2;nvic.NVIC_IRQChannelSubPriority=2;NVIC_Init(&nvic);
}
void USART1_Init(void)                   //串口初始化相关
{GPIO_InitTypeDef pa9,pa10;USART_InitTypeDef usart1;pa9.GPIO_Mode=GPIO_Mode_AF_PP;pa9.GPIO_Pin=GPIO_Pin_9;pa9.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&pa9);pa10.GPIO_Mode=GPIO_Mode_IN_FLOATING;pa10.GPIO_Pin=GPIO_Pin_10;pa10.GPIO_Speed=GPIO_Speed_50MHz;GPIO_Init(GPIOA,&pa10);usart1.USART_BaudRate=9600;usart1.USART_HardwareFlowControl=USART_HardwareFlowControl_None;usart1.USART_Mode=USART_Mode_Rx|USART_Mode_Tx;usart1.USART_Parity=USART_Parity_No;usart1.USART_StopBits=USART_StopBits_1;usart1.USART_WordLength=USART_WordLength_8b;USART_Init(USART1,&usart1);USART_Cmd(USART1,ENABLE);
}

3、初始化SPI1,并使能。

void SPI1_Init(void)
{SPI_InitTypeDef spi1;spi1.SPI_BaudRatePrescaler=SPI_BaudRatePrescaler_16;spi1.SPI_CPHA=SPI_CPHA_1Edge;spi1.SPI_CPOL=SPI_CPOL_Low;spi1.SPI_CRCPolynomial=7;                             spi1.SPI_DataSize=SPI_DataSize_8b;spi1.SPI_Direction=SPI_Direction_2Lines_FullDuplex;spi1.SPI_FirstBit=SPI_FirstBit_MSB;spi1.SPI_Mode=SPI_Mode_Master;spi1.SPI_NSS=SPI_NSS_Soft;SPI_Init(SPI1,&spi1);SPI_Cmd(SPI1,ENABLE);
}

4、初始化模块,进入Standby-I模式

void NRF24L01_TX_Init(void)
{TX_CE=0;TX_CSN=1;
}
/*
*TX_CE、TX_CSN已经通过宏定义到指定F103上的引脚。CE为工作模式选择,CSN为片选
*
/

5、配置模块工作状态,根据CONFIG寄存器的不同,有PTX,PRX模式可选

PTX_Mode初始化步骤 24L01 相关寄存器(节点地址、通信频率、发射参数、有效数据宽度、CRC、EN_AA都要与PRX一致)
1)写 Tx 节点的地址 TX_ADDR
2)写 Rx 节点的地址(主要是为了使能 Auto Ack) RX_ADDR_P0
3)使能 AUTO ACK EN_AA
4)使能 PIPE 0 EN_RXADDR
5)配置自动重发次数 SETUP_RETR
6)选择通信频率 RF_CH
7)配置发射参数(低噪放大器增益、发射功率、无线速率) RF_SETUP
8 ) 选择通道 0 有效数据宽度 Rx_Pw_P0
9)配置 24L01 的基本参数以及切换工作模式 CONFIG

PRX_Mode初始化步骤 24L01 相关寄存器
1)写 Rx 节点的地址 RX_ADDR_P0
2)使能 AUTO ACK EN_AA
3)使能 PIPE 0 EN_RXADDR
4)选择通信频率 RF_CH
5) 选择通道 0 有效数据宽度 Rx_Pw_P0
6)配置发射参数(低噪放大器增益、发射功率、无线速率) RF_SETUP
7)配置 24L01 的基本参数以及切换工作模式 CONFIG

void NRF24L01_TX_Mode(void)
{TX_CE=0;NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS,TX_ADR_WIDTH);NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH);NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01);NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01);NRF24L01_Write_Reg(NRF_WRITE_REG+SETUP_RETR,0x1A);NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40);NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0F);NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0E);TX_CE=1;delay_us(10);         //如果是连续发射,在初始化阶段就要拉高CE10us以上,一个一个包发送等到发送在拉高
}
void NRF24L01_RX_Mode(void)
{RX_CE=0;NRF24L01_RX_WRITE_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH);NRF24L01_RX_WRITE_Reg(NRF_WRITE_REG+EN_AA,0x01);NRF24L01_RX_WRITE_Reg(NRF_WRITE_REG+EN_RXADDR,0x01);NRF24L01_RX_WRITE_Reg(NRF_WRITE_REG+RF_CH,40);NRF24L01_RX_WRITE_Reg(NRF_WRITE_REG+RF_SETUP,0x0F);NRF24L01_RX_WRITE_Reg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);NRF24L01_RX_WRITE_Reg(NRF_WRITE_REG+CONFIG,0x0F);RX_CE=1;delay_us(130);        //开始进入接收模式,等待130us
}

6、处理中断,并发送/接收信号

/*这是PTX端的中断函数*/
void EXTI1_IRQHandler(void)
{u8 status;if(EXTI_GetITStatus(EXTI_Line1)!=RESET){status=NRF24L01_Read_Reg(STATUS);NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,status);if(status&MAX_TX){NRF24L01_Write_Reg(FLUSH_TX,NOP);printf("\r\nMAX_TX");}else if(status&TX_OK){printf("\r\nTX_OK");}else{        printf("\r\n0xF5");}EXTI_ClearITPendingBit(EXTI_Line1);}
}
/*这是PRX端的中断函数*/
void EXTI1_IRQHandler(void)
{u8 status;u8 rxbuf[32];                         //在main.c文件中引用该rxbuf变量if(EXTI_GetITStatus(EXTI_Line1)!=RESET){status=NRF24L01_RX_READ_Reg(STATUS);NRF24L01_RX_WRITE_Reg(NRF_WRITE_REG+STATUS,status);printf("\r\nZD");if(status&RX_OK){NRF24L01_RX_READ_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);NRF24L01_RX_WRITE_Reg(FLUSH_RX,NOP);printf("\r\n%s",rxbuf);}EXTI_ClearITPendingBit(EXTI_Line1);}
}

多对一模式(六发一收)

初始化阶段,跟一对一通讯一样。唯一的区别就是在与接收通道不一样。

通道0(PX_ADDR_P0)可以写入32字节的任意地址;

通道1(PX_ADDR_P1)也可以写入32字节的任意地址,但是会对之后的P2~P5有影响;

通道2~通道5(PX_ADDR_P2~PX_ADDR_P5),在写入地址之前,一定要先写入P1的通道的地址,P2~P5高4字节地址跟P1的地址一致,低1字节可以自己手动写入。

如果要开启ACK应答,设置EN_AA与EN_RXADDR寄存器,要使用通道x,前面的x-1通道也要开启。如要使用通道3,那么通道0~通道2都要开启功能。

/*PTX端使用P2通道通讯*/
void NRF24L01_TX_Mode(void)
{TX_CE=0;
//  NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS,TX_ADR_WIDTH);
//  NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH);/*P1通道,TX_ADDRESS_P1是自定义的32字节数组*/
//  NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS_P1,TX_ADR_WIDTH);
//  NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)TX_ADDRESS_P1,RX_ADR_WIDTH);  /*P2*/NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(u8*)TX_ADDRESS_P2,TX_ADR_WIDTH);NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)TX_ADDRESS_P2,TX_ADR_WIDTH); NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x3F);NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x3F);NRF24L01_Write_Reg(NRF_WRITE_REG+SETUP_RETR,0x1A);NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40);NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0F);NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0E);TX_CE=1;delay_us(10);         //如果是连续发射,在初始化阶段就要拉高CE10us以上,一个一个包发送就除外
}
/*进入接收模式*/
void NRF24L01_RX_Mode(void)
{RX_CE=0;NRF24L01_RX_WRITE_Buf(NRF_WRITE_REG+RX_ADDR_P0,(u8*)RX_ADDRESS,RX_ADR_WIDTH);NRF24L01_RX_WRITE_Buf(NRF_WRITE_REG+RX_ADDR_P1,(u8*)RX_ADDRESS_P1,RX_ADR_WIDTH);     //新增P1通道地址NRF24L01_RX_WRITE_Buf(NRF_WRITE_REG+RX_ADDR_P2,(u8*)RX_ADDRESS_P2,1);                //设置P2通道地址NRF24L01_RX_WRITE_Reg(NRF_WRITE_REG+EN_AA,0x3F);                                     //使能所有通道自动应答NRF24L01_RX_WRITE_Reg(NRF_WRITE_REG+EN_RXADDR,0x3F);                                 //使能所有通道接收地址NRF24L01_RX_WRITE_Reg(NRF_WRITE_REG+RF_CH,40);NRF24L01_RX_WRITE_Reg(NRF_WRITE_REG+RF_SETUP,0x0F);NRF24L01_RX_WRITE_Reg(NRF_WRITE_REG+DYNPD,0x3F);NRF24L01_RX_WRITE_Reg(NRF_WRITE_REG+FEATURE,0x06);NRF24L01_RX_WRITE_Reg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);  NRF24L01_RX_WRITE_Reg(NRF_WRITE_REG+RX_PW_P1,RX_PLOAD_WIDTH);                        //新增P1通道有效数据宽度NRF24L01_RX_WRITE_Reg(NRF_WRITE_REG+RX_PW_P2,RX_PLOAD_WIDTH);                        //新增P2通道有效数据宽度NRF24L01_RX_WRITE_Reg(NRF_WRITE_REG+CONFIG,0x0F);RX_CE=1;delay_us(130);
}

使用ACK自动回复带数据功能

使用ACK带数据回复,是一个十分有用的功能,让PTX/PRX能交换一些数据,而不用来回切换收/发角色。

在PRX端收到数据后,MCU如果能在130us内将数据写入到FIFO寄存器中,那么在回复ACK信号时,会将FIFO内的数据带上,传输回去给PTX,以下图形象的说明了经过。

配置过程,其他跟上面一样,区别在于启用ACK回复带数据功能

发送端和接收端配置要一致:

▝ 启用DPL功能,DYNPD寄存器写0x3F,开启所有通道

▝ 启用FEATURE寄存器,写0x06,激活DPL,EN_ACK_PAY

以下接收端设置:

使用W_ACK_PAYLOAD命令(10101xxx)在130us内,在对应通道写入回复数据

0xA8:通道0                 0xAB:通道3

0xA9:通道1                 0xAC:通道4

0xAA:通道2                 0xAD:通道5

/*进入接收模式*/
void NRF24L01_RX_Mode(void)
{RX_CE=0;
......NRF24L01_RX_WRITE_Reg(NRF_WRITE_REG+DYNPD,0x3F);      //开启所有通道NRF24L01_RX_WRITE_Reg(NRF_WRITE_REG+FEATURE,0x06);    //激活DPL,EN_ACK_PAY
......NRF24L01_RX_WRITE_Reg(NRF_WRITE_REG+CONFIG,0x0F);RX_CE=1;delay_us(130);
}/*PRX端的ACK回复*/
void EXTI1_IRQHandler(void)
{u8 status,receive_length;u8 ack_buf[32]={0x41,0x42,0x43,0x44,0x45,0x46,0x47,0x48,0x49,0x4A,0x4B,0x4C,0x4D,0x4E,0x4F,0x50,0x51,0x52,0x53,0x54,0x55,0x56,0x57,0x58,0x59,0x5A,0x5B,0x5C,0x5D,0x5E,0x60,0x61};if(EXTI_GetITStatus(EXTI_Line1)!=RESET){status=NRF24L01_RX_READ_Reg(STATUS);NRF24L01_RX_WRITE_Reg(NRF_WRITE_REG+STATUS,status);printf("\r\nZD");if(status&RX_OK){NRF24L01_RX_WRITE_Buf(0xAA,ack_buf,32);                  //在P2通道写入ack_bufNRF24L01_RX_READ_Buf(RD_RX_PLOAD,rxbuf,RX_PLOAD_WIDTH);  //读取接收数据NRF24L01_RX_WRITE_Reg(FLUSH_RX,NOP);                     //刷新接收缓存printf("\r\n%s",rxbuf);                                  //打印接收到的数据}EXTI_ClearITPendingBit(EXTI_Line1);}
}

ART回复时间
        在2Mbps模式下,ack有效载荷大于15字节,则ARD必须大于500us
        在1Mbps模式下,ack有效载荷大于5字节,则ARD必须大于500us
        在250kbps模式下,不论有没有有效载荷,ARD必须大于500us

对于250kbps模式,ART时间表如下:

ART

ACK有效载荷

1500us

全部有效载荷

1250us

≦24

1000us

≦16

750us

≦8

500us

空载荷也要预留时间

NRF24L01P(nrf24l01+)从入门到使用相关推荐

  1. 【年终盘点】2019上海人工智能发展十大事记

    可以说,上海人工智能就是中国人工智能发展的缩影. 12月2日,上海市经济和信息化发展研究中心发布<2019上海市智慧城市发展水平评估报告>.报告显示,目前,上海全市 人工智能重点企业已突破 ...

  2. STC89C52 STC89LE52 NRF24L01无线 教程 (二)

    原帖地址:http://www.dowellbbs.com/forum.php?mod=viewthread&tid=570&extra=page%3D1 程序下载地址:http:// ...

  3. nRF24L01 无线数传模块之间的区别 干货分析

    nRF2401A nRF2401A为nRF2401的改进型号(nRF2401AG为无铅工艺型号).nRF2401A工作在2.4GHz的国际通用ISM免申请频段GFSK调制的无线数传芯片.最高发射功率0 ...

  4. nRF24L01+不能接收或接收偶尔异常等问题实战分享

    nRF24L01+不能接收或接收偶尔异常等问题实战分享 nRF24L01+接收异常问题综述 如何快速判断nRF24L01+通信失败问题是出在接收端 正常接收数据时硬件电路必需的基本保障 现象1:一次也 ...

  5. NRF24L01+模块实现双向通信(带ACK payload)

    本文主要关于NRF24L01+ 2.4GHz无线模块的应用. 目录 说明 模块开发的大致步骤 使用方式 一.单向通信 二.双向通信(有应答包(ACK payload)) 寄存器配置 三.星状组网 注意 ...

  6. 讲解NRF24L01P无线收发模块(转载)

    [1]为什么使用2.4GHz频段https://www.arduino.cn/forum.php?mod=redirect&goto=findpost&ptid=86275&p ...

  7. 基于Arduino单片机的nRF24L01+无线遥控装置设计(爆肝制作)

    目录 前言 一.总体思路 二.硬件介绍 (一)主机 (二)从机 三.电路设计 (一)主机 (二)从机 四.程序代码 (一)主机 (二)从机 五.总结及改进 六.所用到的文献链接 前言 此文章只涉及单片 ...

  8. nRF24L01+基于51单片机的驱动(库)实战代码分享

    nRF24L01+基于51单片机的驱动(库)实战代码分享 关于代码来源 定义数据类型的头文件Type.h nRF24L01+驱动源代码文件nRF24L01P.c nRF24L01+驱动的头文件nRF2 ...

  9. AD入门学习—原理图的绘制3

    目录 2.4 CAN&24C02及DS18B20温度传感单元的绘制 2.5 USB单元的绘制 2.6 SD卡及TFT单元的绘制 2.7 NRF24L01单元的绘制 2.8 COM口及PS/2接 ...

最新文章

  1. Pandas 基础 (1)—— Series
  2. [项目过程中所遇到的各种问题记录]编辑器篇——FCKeditor自定义上传路径配置...
  3. centos更换网卡后怎么更新配置_CentOS安装
  4. python集合类型一般应用的场景包括_Python学习,数据类型,python,篇
  5. Android——列表选择框(Spinner)
  6. 线性空间与坐标空间的同构
  7. 1分钟链圈 | 硅谷和成都互设科技金融中心;帅初:区块链更容易落地游戏和版权行业;区块链底层技术布局基本完成
  8. Keras中verbose的作用
  9. Php 领域驱动 视频,.Net DDD 领域驱动学习视频教程
  10. 形态学填充孔洞的几个问题
  11. 专访中科云创周北川:用AI来做工业设备的故障诊断,目前还停留在“鸡尾酒疗法”阶段
  12. “云脑启智 开源赋能”2021年度AI盛会召开 PNEdit赋能人工智能产业发展
  13. tiktok广告推广怎么能精准展现?什么行业适合在tiktok投放广告?
  14. 云计算是什么意思?云计算管理平台有哪些?
  15. 自然语言处理(六)图的随机游走模型与噪声信道模型与条件随机场
  16. RUST——互斥锁的使用
  17. Object常用的几种方法
  18. 无线远程上下载PLC程序
  19. 做线上商城怎么维护老客户呢?
  20. 程序员高逼格指南--君君君哥哥丶

热门文章

  1. android load BKS error: wrong version of key store
  2. Pivotal Gemfire gfsh shell的使用(2)
  3. Javascript 执行上下文(ES3)
  4. IntelliJ IDEA 如何配置MySQL数据库
  5. 虚拟机中Centos更新内核
  6. 3.6.2数据库系统-范式判断:范式分类、第一范式、第二范式、第三范式、BC范式
  7. LVGL (7) 显示对接
  8. 【java】Deepin 解决JDK出现Picked up _JAVA_OPTIONS: -awt.useSystemAAFontSettings=gasp的问题
  9. CVPR2021跟踪算法STMTrack的配置(Template-free Visual Tracking with Space-time Memory Networks)
  10. Git学习之旅--撤销与删除