NRF24L01详细教程.docx
- 文档编号:8774903
- 上传时间:2023-02-01
- 格式:DOCX
- 页数:16
- 大小:22.38KB
NRF24L01详细教程.docx
《NRF24L01详细教程.docx》由会员分享,可在线阅读,更多相关《NRF24L01详细教程.docx(16页珍藏版)》请在冰豆网上搜索。
NRF24L01详细教程
NRF24L01详细教程
近来课程的项目需要用到NRF24L01,用来做基本的收发,虽然资料拿到不少,但是,很多资料并不是很清晰、所带的例程并不够简洁或有不少冗余的部分,再加上对应的中文数据手册部分没翻译出来,翻译出来的不够有条理,很多地方模糊,甚至关键的地方看一两次还看不出来,导致了在学NRF24L01时花费了较多时间,所以,学完NRF24L01后,萌生了写个尽量清晰的教程的想法。
教程中的例程虽然是库开发方式,但基本都是最底层的操作才用到库函数譬如发一字节数据、GPIO置位等,虽然用的STM32,但我在看其他板子的例程时,发觉内容与流程都是差不多的,只是不同板引脚不同所导致的引脚配置的不同,不管用什么方式开发,用什么芯片,了解清楚NRF24L01如何配置,了解清楚其收发流程,基本上就会开发了,所以此文档虽然写的是以STM32为例,但看完此文档用NRF24L01基本也没什么大问题了。
教程说明:
这教程是基于STMF103ZET6的,是野火的板子,例程也是从野火提供修改例程得来,用的是库开发的方式。
学习NRF24L01的步骤:
1.学习SPI,SPI就是NRF24L01传送数据到单片机的一种协议,类似于USB,
当然USB还是比较有难度的。
2.了解NRF24L01相关寄存器,结合中文数据手册了解NRF24L01的基本配置,收发数据前后的操作(如何启动发送接收、寄存器清空、标志位重置等)。
3.分析具体代码
SPI的简介:
具体的SPI教程,大家可以去野火的教程进行学习,在此只是简略介绍一下,SPI是一种一对多协议:
一个主机(MCU)对应对多个从机,可以分时与多个从机通讯
SPI总线包含4条总线,分别为SS、SCK、MOSI、MISO,其含义分别为
SS:
SlaveSelect,片选信号线,主机借此信号线选择一个从机,低电平有效。
MOSI:
MasterOutput,SlaveInput,主机数据从此线输出到从机,数据方向从主机到从机。
MISO:
MasterInput,SlaveOutput,主机从此线读取从机数据,数据方向从从机到主机。
SCK:
SerialClock,时钟频率线,主机时钟频率输出到从机。
对SPI的模式进行配置后(配置不算复杂,过程可以参照野火教程),通过SPI,MCU可以发送命令和数据与从机进行通信了。
SPI协议中,先发指令,再发送需要写入的数据(如果进行写操作的话),这些指令,对主机来说,只是它遵守最基本的通讯协议发送出的数据。
但设备把这些数据解释成不同的意义(指令编码),所以才成为指令。
介绍一下NRF24L01的管脚:
管脚名称说明
GND接地
VCCVCC脚接电压范围为1.9V~3.6V之间
CE置高会启动发送(发送模式下)或者接收(接收模式下)
CSN置低使能,SPI片选使能引脚,MCU的每条指令都要经历CSN从低到高
SCK时钟信号引脚
MOSI主机数据输出、从机数据输入线
MISO主机数据输入、从机数据输出线
IRQ中断引脚、当发送数据成功或者接收数据成功IRQ置低
管脚接法介绍:
GND与VCC对应板上的接即可,MISO、MOSI、SCK、CSN(有些SPI片选段写着的是SS)对应SPI模块相应引脚即可。
CE引脚接上一GPIO口,MCU通过此GPIO口控制CE高低电平即可,同理,IRQ引脚接上另一GPIO口,MCU通过此读取GPIO口的高低电平来判断是否中断。
下面介绍NRF24L01的工作模式和具体的发送与接收流程
工作模式:
NRF24L01有两种工作模式,一种ShockBurst™,一种是EnhancedShockBurst™,两种模式的差别仅在于EnhancedShockBurst™模式中在发送过程中会要求接收设备产生应答信号,以便发送方检测数据是否丢失,一旦丢失将重发丢失数据包将丢失的数据恢复。
也因为EnhancedShockBurst™模式有此优点,将很大程度上防止数据的丢失,因此较多选择EnhancedShockBurst™模式,注意:
选择EnhancedShockBurst™模式,无需自己再写代码设置接收模式接收应答信号或者写代码让其重发,产生应答信号与自动重发(如果数据丢失),都是在设置为EnhancedShockBurst™模式后自动进行的。
EnhancedShockBurst™的发送模式下的流程:
① MCU通过SPI对NRF24L01进行基本配置,,配置自动应答通道使能(发送完一包数据后自动进入接收应答信号状态,发送一次发一包数据,一包数据格式见文档最后),设置自动重发次数不为0(在此设置可以重发数据包)注:
此两步是开启EnhancedShockBurst™模式的关键。
设置为发送模式,还有其他配置等等
② MCU把要发送的数据和接收数据设备的地址通过SPI写入NRF24L01
③ CE引脚置高,启动发送
④ 此时有两种情况:
1.在有限时间内收到应答信号,则TX_DS置高(发送数据成功标志位),并引发IRQ中断(引脚IRQ置低),并清除TXFIFO(此为发送缓冲寄存器,自行写代码清除),IRQ中断需要写状态寄存器进行复位(因为此处IRQ由TX_DS引发,将TX_DS复位即可使IRQ复位)
2.重发数据次数超过设定值,则MAX_RT置高(达到最多重发次数标志位),并引发IRQ中断(引脚IRQ置低),不清除TXFIFO,IRQ中断需要写状态寄存器进行复位(因为此处IRQ由MAX_RT引发,将MAX_RT复位即可使IRQ复位)
⑤ 接收到应答信号产生中断或者达到最大重发次数产生中断后,NRF24L01继续发下一包数据。
⑥ 当TXFIFO为空时,进入待机模式二(当CE为高,TXFIFO为空时,进入待机模式二;NRF24L01的工作模式图表在最后,工作模式不需过多理会,只要在适当时候拉高CE进行发送即可,配置NRF24L01时CE置低)
EnhancedShockBurst™的接收模式下的流程:
① 与发送模式一样,一开始MCU通过SPI对NRF24L01进行基本配置,设置数据通道自动应答使能(在EN_AA寄存器进行设置,即收到数据后,向主机发送应答信号),注:
此步是开启从机EnhancedShockBurst™模式的关键。
还有进行接收数据通道使能(在EN_RXADDR寄存器配置,即选择六个接收通道的某一通道来接收数据,六个接收通道具体情况下面会说到),设置为接收模式,还有其他等配置。
② 拉高CE引脚(CE置高),启动接收状态
③ 接收到一个有效数据包后,数据存储在RXFIFO,并产生RX_DR中断(RX_DR为接收数据成功标志位,接收成功置1),中断和发送模式一样,同样需要复位。
④ 接收设备自动向发送设备发送确认信号(无需自己写代码)
⑤ 设置CE引脚为低,NRF24L01进入待机模式一
⑥ MCU通过SPI读取NRF24L01收到的数据
根据NRF24L01的发送数据流程与接收数据流程,我们可以归纳出编写NRF24L01发送代码与接收代码的流程
发送过程:
a.MCU通过SPI对NRF24L01进行基本配置,配置好NRF24L01
b.MCU将要发送的数据与接收数据设备的地址写入NRF24L01
c.CE引脚置高,启动发送
接收过程:
a.MCU通过SPI对NRF24L01进行基本配置,配置好NRF24L01
b.CE引脚置高,启动接收
c.MCU对NRF24L01进行数据读取
分析具体代码
发送模式:
首先我们来看一下例程发送模式下的mian.c文件
1#include"stm32f10x.h"
2#include"bsp_usart1.h"
3#include"bsp_spi_nrf.h"
4
5/*
6*PA2-PG8ce使能
7*PA1-PG15cs片选
8*PA3-PC4irq中断
9*/
10u8status;//用于判断接收/发送状态
11u8txbuf[4]={0,1,2,3};//发送缓冲
12u8rxbuf[4];//接收缓冲
13inti=0;
14
15/**
16*@brief主函数
17*@param无
18*@retval无
19*/
20intmain(void)
21{
22SPI_NRF_Init();
23
24/*串口1初始化*/
25USART1_Config();
26
27printf("\r\n这是一个NRF24L01无线传输实验\r\n");
28printf("\r\n这是无线传输主机端的反馈信息\r\n");
29
30
31
32
33NRF_TX_Mode();
34
35while
(1){
36printf("\r\n主机端进入自应答发送模式\r\n");
37
38
39/*开始发送数据*/
40status=NRF_Tx_Dat(txbuf);
41
42/*判断发送状态*/
43switch(status){
44caseMAX_RT:
45printf("\r\n主机端
46没接收到应答信号,发送次数超过限定次数
47,发送失败。
\r\n");
48break;
49
50caseERROR:
51printf("\r\n未知原因导致发送失败。
\r\n");
52break;
53
54caseTX_DS:
55printf("\r\n主机端接收到从机端
56的应答信号,发送成功!
\r\n");
57break;
58}
59
60
61}
62}
我们来分析一下mian函数里面的代码
开头的调用的第一个函数就是SPI_NRF_Init(),跟踪这个函数的内容,我们可以发现这函数主要是进行SPI的有关配置与NRF24L01引脚接入STM32GPIO的有关配置;有关SPI配置内容,读者可以前去SPI的有关教程了解,这里不展开了。
有关GPIO口的配置,这里不是重点,所以亦不展开,可以去读关于LED灯的配置,了解学习GPIO配置的内容。
同理调用的第二个函数USART1_Config()亦不作展开.
NRF_TX_Mode()函数的分析:
我们来看一下NRF_TX_Mode()这个函数,这是配置NRF24L01作为发送设备的函数,我们跟踪其定义可以看到如下代码:
1voidNRF_TX_Mode(void)
2{
3NRF_CE_LOW();
4
5SPI_NRF_WriteBuf(NRF_WRITE_REG+TX_ADDR,TX_ADDRESS,TX_ADR_WIDTH);
6//写TX节点地址
7
8SPI_NRF_WriteBuf(NRF_WRITE_REG+RX_ADDR_P0,RX_ADDRESS,RX_ADR_WIDTH);
9//设置TX节点地址,主要为了使能ACK
10
11SPI_NRF_WriteReg(NRF_WRITE_REG+EN_AA,0x01);
12//使能通道0的自动应答
13
14SPI_NRF_WriteReg(NRF_WRITE_REG+EN_RXADDR,0x01);
15//使能通道0的接收地址
16
17SPI_NRF_WriteReg(NRF_WRITE_REG+SETUP_RETR,0x1a);
18//设置自动重发间隔时间:
500us+86us;
19最大自动重发次数:
10次
20
21SPI_NRF_WriteReg(NRF_WRITE_REG+RF_CH,CHANAL);
22//设置RF通道为CHANAL
23
24SPI_NRF_WriteReg(NRF_WRITE_REG+RF_SETUP,0x0f);
25//设置TX发射参数,0db增益,2Mbps,
26低噪声增益开启
27
28SPI_NRF_WriteReg(NRF_WRITE_REG+CONFIG,0x0e);
29//配置基本工作模式的参数;PWR_UP,EN_CRC,
3016BIT_CRC,发射模式,开启所有中断
31
32}
函数第一行代码NRF_CE_LOW()根据函数名我们就可以获悉它的作用是将CE引脚置低,此作用是确保CE是低电平,处于待机模式一下进行配置
SPI_NRF_WriteBuf()函数分析:
第二行代码SPI_NRF_WriteBuf(NRF_WRITE_REG+TX_ADDR,TX_ADDRESS,TX_ADR_WIDTH)从函数我们可以得知其是向NRF24L01写入一串数据。
我们跟踪它,代码如下:
1/**
2*@brief用于向NRF的寄存器中写入一串数据
3*@param
4*@argreg:
NRF的命令+寄存器地址
5*@arg
6pBuf:
存储了将要写入写寄存器数据的数组,外部定义
7
8*@argbytes:
pBuf的数据长度
9*@retvalNRF的status寄存器的状态
10*/
11u8SPI_NRF_WriteBuf(u8reg,u8*pBuf,u8bytes)
12{
13u8status,byte_cnt;
14
15/*置低CSN,使能SPI传输*/
16NRF_CSN_LOW();
17
18/*发送寄存器号*/
19status=SPI_NRF_RW(reg);
20
21/*向缓冲区写入数据*/
22for(byte_cnt=0;byte_cnt 23SPI_NRF_RW(*pBuf++);//写数据到缓冲区 24 25/*CSN拉高,完成*/ 26NRF_CSN_HIGH(); 27 28return(status);//返回NRF24L01的状态 29} 第一行NRF_CSN_LOW()是将CSN置低,CSN是片选使能的作用,低电平有效,此在强调一下,NRF24L01的每一条指令的执行都要经过CSN置低后再置高,这就是为什么26行代码NRF_CSN_HIGH()置高CSN的原因。 SPI_NRF_RW(reg)函数分析: 19行代码status=SPI_NRF_RW(reg)调用了函数SPI_NRF_RW(reg)我们追踪其代码 1/** 2*@brief用于向NRF读/写一字节数据 3*@param写入的数据 4*@argdat 5*@retval读取得的数据 6*/ 7u8SPI_NRF_RW(u8dat) 8{ 9/*当SPI发送缓冲器非空时等待*/ 10while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)==RESET); 11 12/*通过SPI2发送一字节数据*/ 13SPI_I2S_SendData(SPI1,dat); 14 15/*当SPI接收缓冲器为空时等待*/ 16while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE)==RESET); 17 18/*ReturnthebytereadfromtheSPIbus*/ 19returnSPI_I2S_ReceiveData(SPI1); 20} 此函数用到了很多库函数,在此我们就不分析库函数了,我们了解此函数功能即可,从这函数的说明,我们就能知道,这函数是写入或者读取一字节数据用的。 回到SPI_NRF_WriteBuf(u8reg,u8*pBuf,u8bytes)函数,我们发觉,它向SPI_NRF_RW(reg)传入的参数是reg,SPI_NRF_WriteBuf()的函数介绍里,reg是指NRF的命令+寄存器地址,但是这是怎么回事,其实,这里传递的一个字节数据对NRF24L01来说是指令,上面的SPI简介就提到,一些数据对主机来说仅仅是数据,但对从机而言便是指令了。 下面了解一下NRF24L01的指令: 其中,读配置寄存器一个字节的指令后五位是该寄存器地址,写配置寄存器的一个字节指令后五位是该寄存器地址,第六位是1,这就是为什么SPI_NRF_WriteBuf()函数传入的参数是NRF_WRITE_REG+TX_ADDR了,其中NRF_WRITE_REG=0x20(即00100000),TX_ADDR就是寄存器的地址。 以上的NRF24L01其他指令,在以下的代码将有用到。 写入命令后,接下来u8SPI_NRF_WriteBuf(u8reg,u8*pBuf,u8bytes)的22、23代码即是向寄存器写数据的过程。 5SPI_NRF_WriteBuf(NRF_WRITE_REG+TX_ADDR,TX_ADDRESS,TX_ADR_WIDTH); 6//写TX节点地址 由此,我们了解次此两行代码的作用是写入TX的地址,即告知发送设备即将接收数据设备的地址。 8SPI_NRF_WriteBuf(NRF_WRITE_REG+RX_ADDR_P0,RX_ADDRESS,RX_ADR_WIDTH); 9//设置TX节点地址,主要为了使能ACK 同理是为了写明NRF24L01接收通道0的地址,接收通道0为接收应答信号用,在此说明NRF24L01在接收模式下可以接收6路不同的数据,有6个通道,6个通道的地址有5个通道地址有一定限制,详情参照数据手册。 11SPI_NRF_WriteReg(NRF_WRITE_REG+EN_AA,0x01); 12//使能通道0的自动应答 11行代码中使用了新的函数SPI_NRF_WriteReg()跟踪其定义发现其作用与SPI_NRF_WriteBuf()差别在于SPI_NRF_WriteReg()是写入一个字节的数据由此可知11行代码的功能是将EN_AA寄存器配置为0x01,查阅手册可知其是使能通道0自动应答。 14SPI_NRF_WriteReg(NRF_WRITE_REG+EN_RXADDR,0x01); 15//使能通道0的接收地址 同理可知其功能是使能接收通道0能够接收数据 17SPI_NRF_WriteReg(NRF_WRITE_REG+SETUP_RETR,0x1a); 18//设置自动重发间隔时间: 500us+86us; 19最大自动重发次数: 10次 此为有关重发次数和重发时间间隔的配置 21SPI_NRF_WriteReg(NRF_WRITE_REG+RF_CH,CHANAL); 22//设置RF通道为CHANAL 23 24SPI_NRF_WriteReg(NRF_WRITE_REG+RF_SETUP,0x0f); 25//设置TX发射参数,0db增益,2Mbps, 26低噪声增益开启 此处读者编程时按一般例程写即可,可不深究,注意接收设备与发送设备相等。 28SPI_NRF_WriteReg(NRF_WRITE_REG+CONFIG,0x0e); 29//配置基本工作模式的参数;PWR_UP,EN_CRC, 3016BIT_CRC,发射模式,开启所有中断 此处是对NRF24L01的配置寄存器进行配置,设置为发送状态,上电、允许所有中断(TX_DS、RX_DR、MAX_RT)等 至此,发送模式配置完毕。 NRF_Tx_Dat(txbuf)函数分析: 我们接着看main函数的39与40行代码 39/*开始发送数据*/ 40status=NRF_Tx_Dat(txbuf); 根据发送流程,大家都知道这是MCU写入数据到NRF24L01了,我们具体跟踪此函数代码,代码如下: 1/** 2*@brief用于向NRF的发送缓冲区中写入数据 3*@param 4*@arg 5txBuf: 存储了将要发送的数据的数组,外部定义 6*@retval发送结果,成功返回TXDS,失败返回MAXRT或ERROR 7*/ 8u8NRF_Tx_Dat(u8*txbuf) 9{ 10u8state; 11 12/*ce为低,进入待机模式1*/ 13 14/*写数据到TXBUF最大32个字节*/ 15SPI_NRF_WriteBuf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH); 16 17/*CE为高,txbuf非空,发送数据包*/ 18NRF_CE_HIGH(); 19 20/*等待发送完成中断*/ 21while(NRF_Read_IRQ()! =0); 22 23/*读取状态寄存器的值*/ 24state=SPI_NRF_ReadReg(STATUS); 25 26/*清除TX_DS或MAX_RT中断标志*/ 27SPI_NRF_WriteReg(NRF_WRITE_REG+STATUS,state); 28 29SPI_NRF_WriteReg(FLUSH_TX,NOP);//清除TXFIFO寄存器 30 31/*判断中断类型*/ 32if(state&MAX_RT)//达到最大重发次数 33returnMAX_RT; 34 35elseif(state&TX_DS)//发送完成 36returnTX_DS; 37else 38returnERROR;//其他原因发送失败 39} 40 14/*写数据到TXBUF最大32个字节*/ 15SPI_NRF_WriteBuf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH); 此两行代码即为写入要发送的数据。 17/*CE为高,txbuf非空,发送数据包*/ 18NRF_CE_HIGH(); 拉高CE,启动发送。 20/*等待发送完成中断*/ 21while(NRF_Read_IRQ()! =0); MCU启用查询的方式,等待中断发生。 (注: 例程暂时提供是查询的方式检测中断,在此,编者并不建议用查询的方式,因为这会占用CPU,使部分其他功能可能无法加入,建议用中断的方式进行。 ) 23/*读取状态寄存器的值*/ 24state=SPI_NRF_ReadReg(STATUS); 25 26/*清除TX_DS或MAX_RT中断标志*/ 27SPI_NRF_WriteReg(NRF_WRITE_REG+STATUS,state); 28 29SPI_NRF_WriteReg(FLUSH_TX,NOP);//清除TXFIFO寄存器 中断产生后,读取状态寄存器的值,判断中断的类型,此处SPI_NRF_ReadReg();函数为读寄存器函数,功能与操作与上面的函数类似,就不展开了。 读取后,并复位状态寄存器,清除中断,并
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- NRF24L01 详细 教程