NRF905参考程序参考教程包含多个实例和解释Word文件下载.docx
《NRF905参考程序参考教程包含多个实例和解释Word文件下载.docx》由会员分享,可在线阅读,更多相关《NRF905参考程序参考教程包含多个实例和解释Word文件下载.docx(33页珍藏版)》请在冰豆网上搜索。
![NRF905参考程序参考教程包含多个实例和解释Word文件下载.docx](https://file1.bdocx.com/fileroot1/2023-1/3/6dabded3-643c-4d42-b5dd-8d067a206eec/6dabded3-643c-4d42-b5dd-8d067a206eec1.gif)
TXEN=0;
TRX_CE=1;
Delay
(1);
//delayformodechange(>
=650us)
}
设置发送模式,这里会有疑问,在于TRX_CE=0;
。
这里给出的解释是,如果我们直接写TRX_CE=1;
这样模块立即将其内部所写好的数据发送出去。
而对于编程的人员来说编出的程序五花八门,就比如说这条,改程序员的意图并不想让设置发送模式时,数据就被立即发出,所以写了TRX_CE=0;
如果看后面的完整程序,你会发现在发送时,有TRX_CE=1;
这一步。
所以说,刚才那个图表没有问题。
这里可以认为是准备发送模式,而不是发送模式,一旦TRX_CE=1;
那么数据立即被发送。
voidSetTxMode(void)
TRX_CE=0;
TXEN=1;
关于图表中前两种模式中,实例程序所应用的是第二种,即待机spi编程模式。
不管应用两种的哪一种,都是为了spi编程(通过spi通信配置905寄存器)。
那么给出这个模式的应用程序段:
有这么做引脚赋予各种电平先不用管他,我们看到PWR=1;
TRX_CE=0;
TXEN=0;
这三个,在待机spi模式中TXEN=x;
即可以为任何值。
说明现在是待机且spi编程模式。
程序段中其他引脚功能罗列下:
Csn:
spi的有效与否的引脚,低电平有效。
如果只是单纯的设置模式,该引脚并没用处,只是后期程序的编写,所以做下配置。
Sck:
spi的时钟,现在只是设置模式,还没开始spi通信,所以付个低电平。
DR:
数据是否准备好,现在没有什么可准备的。
AD,CD也是一样,等到spi通信的时候才需关系。
这里做个引子吧。
voidnRF905Init(void)
CSN=1;
//Spidisable
SCK=0;
//Spiclocklineinitlow
DR=0;
//InitDRforinput
AM=0;
//InitAMforinput
CD=0;
//InitCDforinput
PWR=1;
//nRF905poweron
//SetnRF905instandbymode
//setradioinRxmode
Nrf905寄存器的配置
配置905寄存器的意思是,通过spi传输一个值,放入905的寄存器中,这个值可以让905传输数据时,产生各种你想要的效果,类似于你用手调节耳机音量,你的手就相当于配置耳机的寄存器。
那么我先给出主要需配置的寄存器然后再解释.
如下面这个程序段:
unsignedcharidataRFConf[11]=
0x00,//配置命令//
0x4c,//CH_NO,配置频段在430MHZ
0x0c,//输出功率为10db,不重发,节电为正常模式
0x44,//地址宽度设置,为4字节
0x04,0x04,//接收发送有效数据长度为32字节
0xCC,0xCC,0xCC,0xCC,//接收地址
0x58,//CRC充许,8位CRC校验,外部时钟信号不使能,16M晶振
};
0x00,//配置命令//后面的讲解中会说,所以大家从第二个开始看。
CH_NO的意思如下,通过以下解释设置不同的值,可以让905工作在不同频段,这个需要的话再做详解,不需要,可以照搬默认值,或者程序。
CH_NO
9
和HFREQ_PLL一起进行平率设置(默认值=001101100b=108d).fRF=(422.4+CH_NOd/10)*(1+HFREQ_PLLd)MHz
于是乎相关的就引出以下这个寄存器
HFREQ_PLL
使PLL工作于433或868/915MHz模式(默认值=0).
'
0'
–工作于433MHz频段
1'
–工作于868or915MHz频段
在这里给出个表格,如需更改该值可以参照:
工作频率
HFREQ_PLL
430.0MHz
[0]
[001001100]
433.1MHz
[001101011]
433.2MHz
[001101100]
434.7MHz
[001111011]
862.0MHz
[1]
[001010110]
868.2MHz
[001110101]
868.4MHz
[001110110]
869.8MHz
[001111101]
902.2MHz
[100011111]
902.4MHz
[100100000]
927.8MHz
[110011111]
这里做下说明:
我们拆分看看这段话。
@输出功率为10db
@不重发
@节电为正常模式
输出功率为10db,这个对于的寄存器是:
如下表,二进制10db应该是11
PA_PWR
2
输出功率(默认值=00).
“00”-10dBm
“01”-2dBm
“10”+6dBm
“11”+10dBm
不重发,针对的寄存器是:
不管怎么说,部分都不自动重发(一般情况),故二进制是0
AUTO_RETRAN
如果TRX_CE和TXEN为高时,自动重发(默认值=0).
–不重发'
–数据包重发
节电为正常模式,针对的寄存器是:
如下表,要是正常模式则二进制是0
RX_RED_PWR
接收方式节能,工作电流1.6mA.灵敏度降低(默认值=0).
–正常工作'
–节能模式
那么如下结论:
输出功率为10db--------------------11
不重发-----------------------------0
节电为正常模式---------------------0
按顺序写则是:
1100---》00001100———》0x0C
0x44,//地址宽度设置,为4字节
如下面两个表:
收地址宽度:
4字节的2进制是100
RX_AFW
3
接收地址宽度(默认值=100).
001'
–1byteRX地址
100'
–4byteRX地址
发地址宽度:
TX_AFW
发送地址宽度(default=100)
.'
–1byteTX地址
–4byteTX地址
于是乎:
100并上100,可认为是0100并上0100,可认为是4并上4,则可认为是0x44.
这条命令是我擅自更改的,更改前是2字节,如是0x04这是32字节。
这样可以使905在一个数据包内传输更多信息。
那么我给出两个寄存器。
RX_PW
6
接收数据宽度(默认=100000).
000001'
–1byte接收数据宽度
000010'
–2byte接收数据宽度
100000'
–32byte接收数据宽度
TX_PW
发送数据宽度(默认=100000).
–1byte发送数据宽度
–2byte发送数据宽度.
–32byte发送数据宽度
这里要把码补全,100000——》00100000——0x40这里实际是0x40一点没错但是程序中写的是0x04,仔细想想,也没什么特别的问题。
这里我水平有限,不做说明了。
0xCC,0xCC,0xCC,0xCC,//接收地址
一看就知道,地址被从新改了下,默认地址是E7这种。
RX_ADDRESS
32
发送地址标识,使用字节取决于RX_AFW(默认值=E7E7E7E7h).
0x58,//CRC充许,8位CRC校验,外部时钟信号不使能,16M晶振
CRC_EN
CRC校验可用(默认值=1).
–不可用'
–可用
CRC_MODE
CRC模式选择端(默认值=1).
–8位'
–16位
UP_CLK_EN
输出时钟可用(默认值=1)
–外面没有可用的时钟信号
–外面有可用的时钟信号
XOF
晶振频率端,必须与外部的晶振频率相对应(默认值=100).
000'
–4MHz'
–8MHz'
010'
–12MHz
011'
–16MHz'
–20MHz
这块看着有点乱的话,请继续往后看。
我们既然把相关寄存器的配置解释了一边,但是如果对于一个编程序的人,或者程序开发来说,这样的罗列虽然我们能弄懂每个寄存器是咋回事,但是实际编程并自己配置寄存器的话,难度是很大的。
幸好,开发手册解决一切问题,下面是一个表,表的后面我有解释。
寄存器内容射频器配置寄存器(R/W)
字节
位内容[7:
0],最高有效位[7]
初始值
CH_NO[7:
0]
0110_1100
bit[7:
6]notused,AUTO_RETRAN,RX_RED_PWR,PA_PWR[1:
0],HFREQ_PLL,CH_NO[8]
0000_0000
bit[7]notused,TX_AFW[2:
0],bit[3]notused,RX_AFW[2:
0100_0100
6]notused,RX_PW[5:
0010_0000
4
6]notused,TX_PW[5:
5
RX_ADDRESS(deviceidentity)byte0
E7
RX_ADDRESS(deviceidentity)byte1
7
RX_ADDRESS(deviceidentity)byte2
8
RX_ADDRESS(deviceidentity)byte3
CRC_MODE,CRC_EN,XOF[2:
0],UP_CLK_EN,UP_CLK_FREQ[1:
1110_0111
解释:
这是手册中的一张表,假设寄存器的配置值是如图给的这些。
那么他的传输是从0字节开始到9字节截止,按顺序把16进制码传进去,你的工作就完成了。
而你需要对那个寄存器进行微小的改动,只需找到手册相关寄存器的说明进行改动就可以了。
我们从上表中摘出一个小表看,小表如下:
bit[7]就是该值得第七位,第七位没用上。
TX—AFW【2:
0】意思是有三位被这个寄存器用了。
等等。
通过这种字节的划分,将寄存器的配置变成了传多个2位十六进制数,使得寄存器的配置变得博大精深,新手上手困难。
不过对于驱动其他芯片也一样,配置寄存器就是这样配置的。
像是某些器件如saa7113等芯片,配置寄存器时,前面还有地址,弄得更加复杂。
所以大家要通过学习nrf905了解芯片的驱动方法这才是关键。
spi通信:
如何实现spi通信,在这个问题上,如果说正常学习应该是,先知晓spi的协议,spi的时序,spi写和读的时序和协议。
但是如果将其看成程序的话就比较方便。
咱们用程序谈这件事情。
该程序段式spi的写程序:
从MOSI=(bit)(b&
0x80);
我们分析下。
假设b=abcdefgh
那b&
0x80就是abcdefgh&
10000000可以想象a被提取了出来。
至于bit,其实可以没有,这里可以参考c51语言关于‘与‘有两个做法,一个是&
,另一个是&
&
,即位与和整个值得与。
之后我们观察sck的变化,sck是spi的时钟,我们发现从0到1然后回到0,这是sck的变化。
在sck变到1之前,mosi已经有了一个值,那么当sck=1;
的时候,也就是所谓的上升沿,mosi被写入,这里可以认为是写入905的内部了。
b<
<
=1;
这个语句等同于b=b《1;
意思是b左移一位的新值付给b,
比如b=abcdefgh左移一位,那么b=bcdefgh0,再左移一位,那么b=cdefgh00,以此类推左移8次之后b=00000000.
因为每移出一位,就代表着移进一位,移进的是0。
那么观察一下0x80——》10000000
这个数10000000与上abcdefgh之后会提取出a
左移之后,再次进行与运算,就会提取出b,循环往复abcdefgh就都提取出来了。
并在每一次都把这个值付给了mosi。
我想通过梳理,大家应该能看懂了,至于spi的通信协议,大家可以参考下网上资料,我想看懂了程序,再看看资料应该能彻底明白了。
voidSpiWrite(ucharb)
uchari=8;
while(i--)
{
Delay(10);
MOSI=(bit)(b&
SCK=1;
}
读Spi程序段:
_nop_();
是延时,延时是一个指令周期的时间。
说白了,就是延时一段时间。
ucharddata=0;
这条语句意味着ddata是完全为0的。
且注意一个事情ddata的定义是uchar,那么他的值最大能到0xff。
ddata|=MISO;
等同于ddata=ddata|miso;
miso是一个引脚的电平。
经过这条语句后ddata的最低位就是miso当时的电平了,这时左移再次提取新的miso电平,当八个电平都提取之后,ddata的值就提取完成了。
同样sck是spi时钟,想提取下一个miso的值必须让时钟波动一次。
ucharSpiRead(void)
ucharddata=0;
ddata<
_nop_();
returnddata;
到此为止,905的基本问题讲完了。
那么我们把它串联在一起。
我们先宏观的看下。
以发送流程为例
905现处于待机spi编程状态——》向905中传送寄存器值
————》@——》将905的状态设置为发送状态————》成功发出-----》待机状态
如果想再发个数据,那么他的流程将变成
@——》将905的状态设置为发送状态————》成功发出————》待机状态
由此看来对同一个对象进行发送,如果大家的设置都没改的话,寄存器的值只需设置一次。
剩下的就是重复发送到待机这个环节了。
那么在@之前的问题,大家都了解了,剩下的就是@到把数据发送这一块了。
这里我分为三个部分说这件事情。
向905传输一个命令
向905装入待发送的数据、
把数据发出去
向905传输命令:
这里定义了这些命令,先在语法上说下#defineWC0x00的意思等价于wc=0x00;
那么我们先解释下这几个命令,大家理解下。
#defineWC0x00
#defineRC0x10
#defineWTP0x20
#defineRTP0x21
#defineWTA0x22
#defineRTA0x23
#defineRRP0x24
如下是wc的解释:
在讲解配置寄存器是有个值我没有讲解先在我告诉大家
指令名称
指令格式
操作
W_CONFIG
(WC)
0000AAAA
写配置寄存器AAAA指明哪个字节。
写操作从哪个字节开始取决于地址AAAA
0x00,//配置命令//这就意味着wc=0x00,意思就是从0字节开始进行写操作。
举个例子看下,0字节代表的是哪个寄存器,
写之后的操作就是开始写1字节,这点上没什么问题最后写到第九字节。
前面有这个表的完整版,大家可以翻着看。
#defineRC0x10的解释如下:
这个看表就知道不做解释了跟wc意思差不多。
R_CONFIG
(RC)
0001AAAA
读配置寄存器AAAA指明哪个字节。
读操作从哪个字节开始取决于地址AAAA
后几个命令都好理解我就都列出来大家自己吸收下:
那么到此,命令部分就说完了,能用的就这几个命令。
向905装入待发送数据:
向905装入数据这件事情和刚才的命令结合着说。
先看以下程序段:
SpiWrite(WTP);
//Writepayloadcommand
for(i=0;
i<
4;
i++)
SpiWrite(TxRxBuf[i]);
//Write32bytesTxdata
先传了wtp命令,之后把txrxbuf数组中的前4字节传了进去。
那么执行外这条之后,数据就被传到905中了(还没有进行发送)。
观察此函数,发现调用了spiwrite这个函数,说明装入命令和装入数据都是通过spi通信进行传输的。
观察以下程序段:
SpiWrite(WTA);
//Writeaddresscommand
i++)//Write4bytesaddress
SpiWrite(TxAddress[i]);
TxAddress[i]和SpiWrite(WTA);
是其中的要素,wta是写地址命令,那么TxAddress[i]就是地址咯,地址前面说过了,程序中除了那个config数组中有地址的说法,另外在程序段中被单独列出的地方是codeTxAddress[4]={0xcc,0xcc,0xcc,0xcc};
那么通过这个程序段,功能就是把地址写进去。
以上的两个程序段完成了数据和地址的写入,这时只要设置成发送状态,数据就可以被发出了。
那么从现在开始是重点部分,就是以上两段程序的组合,并加以延伸。
仔细看下面这段程序,主要关注红字部分。
程序之后有我的相关解释。
voidTxPacket(uchar*TxRxBuf)
uchari;
//Config905();
CSN=0;
}//Spienableforwriteaspicommand
//Spidisable
//Spienableforwriteaspicommand
//SetTRX_CEhigh,startTxdatatransmission
//while(DR!
=1);
//SetTRX_CElow
上面这段程序,如果被main调用了之后,出现的效果是将txrxbuf数组中的