专注电子技术学习与研究
当前位置:单片机教程网 >> MCU设计实例 >> 浏览文章

关于射频芯片nRF24L01的一点知识(中文译文)

作者:佚名   来源:本站原创   点击数:  更新时间:2013年04月12日   【字体:

写在前面的话:  

最近在做毕业设计,有一项任务是翻译英文资料,要求翻译成汉文约5K字。我以前从未做过翻译工作,不过还是硬着头皮做了下来。下面与大家分享一下我的译文,如果大家能够从我的译文弄懂关于nRF24L01的一些知识,说明我的翻译还是成功的;如果大家感到一头雾水说明我还要继续努力了。(当然要是IT相关的人才行,学文科的估计是看不懂的,嘿嘿)。对于nRF24L01,我是做毕设时要用才学习的,刚接触,具体的我也不是很了解,所以才选了两篇介绍nRF24L01的英文文章翻译的。希望有高手不吝赐教!

 

 

第二章 :带有增强型Shockburst的Sweet硬件链路层

引言

现在我有两份有关学习24L01的放映片已经做好,而你仍然跟着我学习的话,这再好不过了!在这一章,我们将探讨关于24L01的带有增强型Shockburst的集成链路层。

 

开始之前应该了解的

在我们开始之前,你要知道这一章是建立在已经授完的第一章的基础上的。事实上,对于每个主程序只有大约5行代码或者更少是不同的。由于这个原因,如果你先打算让这章代码运行的话,最好在开始这章之前你已经将第一章的代码运行过了。如果你只是想了解一些背景而不想要完全测试代码,那么不考虑这些而继续学习也是可以的。

差不多这一章与第一章的不同仅仅在于,在这一章,我们将用增强型的Shockburst模式去处理nRF24L01的硬件链路层。这种模式允许我们让 24L01能自动的处理应答信号和重发数据。这种功能的实现不需要额外的硬件甚至不需要额外的代码,这使得我们工作的链路层功能比以前更为强劲。唯一不好的是如果采用这种模式,链路的速度会稍微有所下降,但是只要你不需要24L01提供带宽的每一个部分,增强型的Shockburst模式显然是非常合适的。

 

Nutshell中的增强型Shockburst

你也许想知道增强型Shockburst到底是什么。它实质上是24L01硬件中可以被执行的一种模式,这种模式下系统会接受数据接收的应答信号,并且在数据丢失的情况下系统会自动的重发。当需要一个强劲的链路使得传输大部分数据的时候,增强型Shockburst模式可以将用户从繁重的软件工作中解脱出来。

如果你非常熟知英特网协议,那么使用增强型Shockburst模式很像使用TCP,而常规的Shockburst就像是网络协议中的UDP。然而增强型 Shockburst并不像TCP那样建立和关闭一个连接,它提供的是某种可以使你的数据顺利传输的不完全担保。和TCP类似,增强型 Shockburst对于没有应答(这种应答是由接收端的增强型Shockburst发出的)的数据,会重发很多次直到达到它设置的最大重复次数而形成中断标志。

有一些寄存器和控制增强型Shockburst模式有关。EN_AA寄存器通过置1和置0打开或者关闭每个数据通道的自动应答功能。当一个发送的数据没有应答的时候,可以在SETUP_RETR寄存器的ARC区域设置你想要重发的次数(设置成0000代表不重发)。在SETUP_RETR寄存器的ARD区域可以设置两次重发操作之间的时间间隔(数值越低,时间越短)。你可以利用CONFIG寄存器的MAX_RT中断使能位将MAX_RT中断的状态传达给 IRQ针脚。你也可以利用STATUS寄存器的MAX_RT位来判断MAX_RT是否中断。

增强型Shockburst的设置很简单。首先,你需要确定在发射设备中,通道0的接收地址(在RX_ADDR_P0 寄存器)和你的发射地址(在TX_ADDR寄存器)要相同。这是因为是通过发射设备中的通道0来接收应答信号的。其次,你要确保发射设备的通道0的自动应答和接收端的某一个你用来接收信号的通道正常工作。最后,你要在发射端的SETUP_RETR寄存器中设置最大重复次数和重发延迟时间。

一旦增强型Shockburst模式设置完毕后,一切都变得明朗了,因为所有的操作都是自动完成的。你真正要做的是你要观察MAX_RT中断或者观察 TX_DS中断,因为某一时刻你得到的是二者之一的结果,而二者不会同时中断。如果数据被发送并且接收到了应答信号,然后TX_DS就会中断。如果没有收到数据发送成功的应答信号,在达到设置的最大重发次数之前,MAX_RT也会中断。

在这里,增强型Shockburst模式和常规Shockburst模式有一个非常重要的区别需要引起注意。在增强型Shockburst模式中,如果数据被成功发送,TX_DS中断后,像在常规Shockburst模式下一样,TX FIFO中的数据就会被清除;然而,如果数据被发送后没有收到应答信号,然后MAX_RT中断,但是数据并不会从TX FIFO中清除。换句话说,如果你想要重发数据,你只需重置CE就可以重发了。然而,如果你想要丢弃这个数据,在你加载任何新的数据之前,你必须清除TX FIFO。否则,24L01会尝试发送原本未发送成功的数据和你后来加载的要发送的数据,这样会扰乱你的发送进程。

 

本章我所用的硬件

本章我用的硬件和在第一章里用的是一样的。没有任何增减,只要你在学第一章的时候让硬件工作,那么在这一章里你肯定可以让它工作。

 

本章软件描述

情况和需要的硬件类似,本章所需要的软件和第一章的是一样的,如果你已经运行过了,那么在本章中,你将有非常清晰的思路。

 

本地主文件:maintutorial2local.c

假如你看过第一章,那么这个文件对你来说极其熟悉。除了要加上用来支持增强型Shockburst的代码外,操作方式和在运行第一章程序时一样。

在进入主程序之前的部分是相同的。仍然要调用Initialize()函数,但是考虑到增强型Shockburst模式的使用,这里会稍有不同:当我们调用nrf24l01_intialize_debug()函数的时候,可以给第三个参数赋值,这样就可以使数据通道0工作在增强型Shockburst模式下。

现在我们来进入程序的主循环。在这我们接收从USART来的数据,然后就像第一章我们做的那样把字节发送出去。然而,这里就是程序的不同之处。当你使用增强型Shockburst模式,你必须留意MAX_RT中断,这个中断会被加入到检查数据是否发送成功的while循环中。在增强型Shockburst 模式下传输数据,如果数据没有传输成功,TX_DS是不会中断的。这就是你为什么两个中断都要观察。

有一点还需要另外说明。当我们检测MAX_RT是否中断的时候,如果没有中断我们就像第一章那样处理数据;然而,如果中断了,这表示数据没有被成功的接收,我们添加一个调试字符“*”来反映这种信息。当数据从本地单位发出后如果没有收到应答信号,通过那种方式我们可以判断出在接收端是否数据被传输到了远程单位。正如我上面讨论的那样,当MAX_RT中断后,数据仍留在TX FIFO。由于这个原因,我们调用nrf24l01_flush_tx()函数来清除数据。最后我们清除中断,让循环继续,这样我们就可以继续接受来自 USART的数据了。

 

远程主文件:maintutorial2remote.c

就像本地主文件一样,远程主文件和第一章用的基本一样,它也是只在其中加入了使增强型Shockburst模式启动并运行的部分。

在主程序之前的所有声明和定义和第一章中的远程主文件是一样的。进入主程序,我们也要调用Initialize()函数,但是考虑到增强型 Shockburst模式的使用,这里会稍有不同:当我们调用nrf24l01_intialize_debug()函数的时候,可以给第三个参数赋值来启动增强型Shockburst模式,这和在本地主文件中的情况是一样的。

调用Initialize()函数后。我们进入主程序循环。在这,我们等待并接收数据。一旦接收到数据,我们通过RF链路将数据发送。一旦我们将数据发送后,我们必须注意TX_DS和MAX_RT中断,保证它们没有被屏蔽。无论数据被成功的发送或者发送失败被忽略(TX_DS和MAX_RT都能够正常中断),我们清除中断,程序又回到循环的开始。

 

程序输出

在图一里,你可以看到终端的窗口里的程序正在运行。24L01互相之间距离很近(大约是6英寸),所以有极高的数据发送成功率。事实上只有一个数据没有发送成功。这个数据在程序的第三行第三个字节的“*”处,而这个星号代表发生了MAX_RT 中断。

 

  图一:终端的输出窗口

 

结论

现在,你应该对增强型Shockburst有了更深刻的了解。如果你有任何问题,可以在合适的时候发Email给我:brennen@diyembedded.com


 

第三章:多通道通信

                          

 

引言

在这一章,我将向你们展示怎么样设置nRF24L01来利用它的六个数据通道进行通信。这对你们中的要做网状网络和其他应用的人来讲是很急迫的。和以前的要求一样,在继续学习之前,你要熟知前面的章节(尤其是第零章、第一章)。

 

数据通道的构架

通道的概念非常容易理解。每一个通道实质上就是一个接受数据的地址(当处于接受模式时)。这就意味着24L01可以同时成为六个不同的数据接受者。

你会问,这对你有什么好处呢?虽然有一些多通道通信的用途,但是我能立即想起来的却不多。你可以将一个通道设置成数据通道,同时你可以将另一个设置成控制通道。你也可能让一个接受通道有不同的功能,让它完成相当于它接受数据的那个通道的工作。你的想象也仅限于此。

当你使用多通道时有几点要时刻注意。首先,所有的通道到用相同的RF信道(无论用哪个信道都可以在RF_CH寄存器中设置)。如果你使用增强型 Shockburst模式。为了收到应答信号,发送端的发送地址和通道0的接受地址(分别存在TX_ADDR和RX_ADDR_P0寄存器中)必须相同。这是一项繁琐的工作,因为你想要将数据发往不同的地址必须要改变两个地址。但是如果使用nRF24L01程序库,若你准备改变发送地址,则只需要几行代码就可以改变RX_ADDR_P0寄存器中的地址。正如旁白所言,在本章并不使用增强型Shockburst模式但一样可以将问题解释的尽可能清楚。

 

多输入多输出

在本章,所有的设置和在第一章或者第二章中是一样的。这包括将一个计算机网络的节点(uC 和 24L01))连接到你PC机上的型号为9600-N-1的串口,并且没有流量控制。其他的节点基本上是独立的。

在本章,我们的目标是测试远程单位的每一个从本地单元发来的数据,并且把统计结果显示出来。在操作中,本地单元会将它的发射地址和远程单元通道0的接收地址设置成一样的。然后发送一个字节,等待接收方将字节发回。如果返回字节和发送字节是一样的,那么就可以说我们的测试是成功的。这样的操作会连续做5次,整个进程是对24L01的其它五个通道进行测试,结果都会被记录下来。最后,全部的统计结果会按照进行计算,24L01会将每个数据通道传输的结果和全部得分显示在屏幕上。

 

本章我所用的硬件

本章我用的硬件和在第一章里用的是一样的。没有任何增减,只要你在学第一章的时候让硬件工作,那么在这一章里你肯定可以让它工作。

本章软件描述

情况和需要的硬件类似,本章所需要的软件和第一章的是一样的,如果你已经运行过了,那么在本章中,你将有非常清晰的思路。

本地主文件:maintutorial2local.c

这个是本地单位的主驱动文件。这个文件是在第一章的主文件的基础上编制而成。因为要使用多通道通信,所以文件中有相当一部分是需要修改的。

首先,头文件和宏定义是一样的。从程序的34行开始,我们会添加一些新的代码。第一个要添加的是Ping()函数。它会按照刚才我们叙述的那样工作:向发送端发送一个字节的数据,然后等待对方回发。除了用发送字节0xFF的操作代替读取从UART传来的数据的操作外,其他的本程序的内容和第一章的内容是一样的。在程序的36行和37行要进行一些设置,包括:进行测试的次数,每个通道进行测试的次数,以及在两个测试之间的时间间隔。

在主函数中,我们通过定义一些变量来计算次数、存储每个通道的成功测试的结果、当前的发送地址以及总共的成功测试。仍然要调用Initialize() 函数,对本地24L01的设置和第一章的是一样的(包括发送地址,发送数据一个字节,常规Shockburst模式)。

调用Initialize() 函数后,我们要修改一下主程序循环。首先,我们将每个通道成功测试次数设置为0。然后打出一条信息,让用户知道我们已经开始检测了。

接下来的循环是用来执行对每个通道的检测的。循环要执行六次,每一次检测一个通道。首先,switch语句设定了要重复的次数,在每次重复的时候让本地单位的发射地址和远程单位的接收通道的地址一致。通道0和通道1的地址都需要进行设定,但是对于通道2-5只需要对最低有效位(LSB)进行设置,因为它们地址的高位和通道1是一样的,而通道1的地址已经加载到了TX_ADDR寄存器中。发送地址设置完成后,检测通道的次数赋值在变量NUM_PINGS中(默认值是5)。如果测试成功一次,计数的变量就会加1。最后通道检测的统计结果会显示出来。

一旦所有的通道检测完毕后,我们打出一条信息来说明对于总共的测试共有多少次是成功的。然后我们将变量PING_DELAY中的延时时间增加用LED来显示循环结束。重复执行主循环即可。

 

远程主文件:maintutorial3remote.c

和第二章的远程主文件一样,maintutorial3remote.c和第一章所用的主文件基本类似。唯一的不同是在这里我们使得六个数据通道都能够工作,这样可以进行多通道通信。

这些差异表现在程序的71行到91行。首先要调用nrf24l01_initialize()函数。在调用函数的第一行,我们对CONFIG寄存器进行设置:以字节为单位的循环冗余校验,选定上电模式,接收模式。第二行取值为真时,RX功能就能够立即启动。第三行设置各通道为非自动应答,第四行开通所有通道。除了RX_PW_P*寄存器,剩余的寄存器都保持在它们的默认初态。将它们设置成能接收一个字节的数据存量,这样就能用它们接收数据了。

如果你没有学习过第一章,这里有一个对程序的详细说明。等到24L01接收到数据程序就开始工作。接收数据完毕后,它会向本地单位的通道0回发数据。然后程序回到循环的开始继续等待数据。

远程单位可以通过所有的通道接收数据,对数据处理的差异根据接收数据通道的不同而不同(当然在这里这个例子不会演示)。程序中是这样实现的,函数 nrf24l01_read_rx_payload()会返回状态寄存器的值,值中包含当前通信数据的数据通道的数量。将这个值赋给函数 nrf24l01_get_rx_pipe_from_status(),这样就可以根据发送来的数据返回给变量pipe一个数值。考虑下面的这个例子:

unsigned char data, status, pipe;

status = nrf24l01_read_rx_payload(&data, 1);

pipe = nrf24l01_get_rx_pipe_from_status(status);

switch(pipe)

{

case 0://process case 0

break;

case 1://process case 1

break;

case 2://process case 2

break;

default://process any other pipe

}

这段代码可以读取发送过来的数据(假定它是存在的,所以你应该编制代码来确保RX FIFO寄存器中有数据)和状态寄存器中的状态值。然后就得到了基于状态寄存器的通道编号,用switch语句就可处理这些数据。我很喜欢用switch语句来处理离散的数值问题。当然,你也可以用if语句或者C语言中的其它结构语句。

程序输出

在图一里,你可以看到终端的窗口里的程序正在运行。24L01互相之间距离很近(大约是6英寸),所以有极高的数据发送成功率(和第一章、第二章的情况一样)。可以看到对通道的所有测试结果。

 

图一:终端输出窗口

结论

现在,你应该对24L01提供的六个数据通道进行多通道通信有了更深刻的了解。如果你有任何问题,可以在合适的时候发Email给我:brennen@diyembedded.com

关闭窗口

相关文章