一. 简介& A' m+ z( y( b' W7 T+ X
在各个无线通信模块中,由于NRF24L01价格便宜,而且体积小,以及不需要外接天线,传输距离约为10-20米,深受大家的喜爱。在遥控汽车,四轴飞行器中较为常见,在这里给大家分享其具体的使用。' N2 E+ C: q4 v! F" p7 t
. I* b. U/ l2 D
模块共用8个引脚
) v( Z/ J7 g! Y4 u$ W通信方式为SPI接口,速率不能太高,最好在10M以内。
9 \! N& d- h7 U1 p, z
1 }- a9 B% Z( Q. R, C" w& X
9 j- M$ s4 w) t/ ]( B/ _( p
5 V6 D/ N$ [- ]7 ]
IRQ : 中断输出,例如发送完成,或者接收完成。默认为高电平。
3 c e6 l+ R. U3 VCE : 芯片的使能引脚7 K# G- @- U. [$ s6 ]2 O* `
CSN:SPI协议的使能引脚0 {0 r) U/ j5 g0 g: c
二. 数据传输过程
6 t6 ?" e9 I N# g从图中可以看出,数据传输的一些特征。CSN默认为高电平,SCK默认为低电平。数据在SCK的下降沿送出,在SCK的上升沿读取数据,先发送高位,再发送低位。如果使用硬件SPI的话,就可以基于这个来设置SPI极性的相关参数了。; {: r/ A+ |0 q8 D* Q/ Z
先发送指令(在发送指令的同时,nrf会返回状态值),然后后面就是写数据,或者是读数据了。
1 S+ k4 O: k: w7 c, H* a8 o3 @! A6 @) x; b0 |- |6 X; w/ i7 G/ H$ S6 Q
/ v+ z4 E2 Z2 X1 a+ j3 s/ J; l
( V8 v/ R9 |' W) {+ z( q- y- X
三. 协议实现
7 X4 q2 {5 E* f* e+ x由于这里的SPI的速率不能太高,所以这里就采用软件的方式来实现这个传输过程(使用硬件的话,可以将分频设置大一点),这样就可以任意选择适合的引脚了。
& G5 |3 {, p* z; \) E9 e其中delay()是个空函数,可以加点延时,也可以不加。8 P( R: h4 z8 d3 ^+ v5 M* O9 i3 `
Cn :命令
9 C4 q) {; [4 S7 n0 o- P/ mData: 写入的数据' b) ~0 |( \9 W3 b1 t
size : 数据的大小3 u, q3 l/ g1 [) l. l: k/ B
# q) w ^+ ~6 i0 ~. {
代码的实现过程,是和上图一一对应起来的,就作详细的说明了。
' v5 u% O* O/ A3 A, r" N2 `' {4 Y# W( g
- void SPI_Write(unsigned char Cn,unsigned char *Data,unsigned char size){
3 B8 {( p7 t! q# ^/ \4 \8 Y/ Q* j - unsigned char i,j;
9 Z$ [3 V6 ^3 ^* q. [ - CSN_LOW;
+ U8 C# V3 O) X# ?+ C - /*写操作符*/! m7 v E, R3 t$ v8 t
- for(i = 0;i < 8; i++){) d' s& t) c8 L' N
- delay();- ^+ R- L1 }5 @7 i% m0 F2 H
- SCK_LOW;
" f# T* H0 e, ^6 V! ~) b. v' I2 x7 k - if(Cn & 0x80)) g- Q( J. B/ Q% ]6 h/ t) P
- MOSI_HIGH;" e3 D6 ?! Z- @
- else7 W- t' C+ Q" Z4 p L* h9 v
- MOSI_LOW;
3 q: Y8 M# k: P/ S$ Q' F - SCK_HIGH;3 { Z' g. k+ D
- Cn <<= 1;
/ Q- ?# c* M& h) M" r0 B, I# e - }
- U; P) F& S; s2 b$ p- j( W - delay();: v5 j) t; f2 T$ a% H
- /*写数据*/( h% ^% B( T6 J, b6 [
- for(i = 0;i < size ;i++){
" z. ^; ~6 B, r4 K1 w - delay();/ z, I l7 k4 r* r+ Y9 X
- SCK_LOW;
( P" R: D" h* H0 V - delay();$ U' y+ v" _! d' _9 A9 m
- delay();
# p9 H7 H ?9 v+ Z2 H5 @ - unsigned char d = Data<i>;% S. `- N; e6 K2 F! z8 H3 T4 l
- for(j = 0;j < 8;j++){" `- O4 {" {) H
- SCK_LOW;1 V* f. i9 C$ P5 ^( U4 \
- if(d & 0x80){ ; m" h$ h+ I* u! V3 E! [9 L
- MOSI_HIGH;
2 e7 Q! j( }* z& L - }/ E- t X5 r9 l3 U* d8 A$ ^* S# [7 p2 [
- else{
+ Y; y* v6 K& A8 I# U. U/ t/ x - MOSI_LOW;) Q% D1 y/ M( C2 n! j1 Z
- }' }* {$ ~% b: u3 |& s5 P F
- SCK_HIGH;# K8 Y9 G) f/ i
- d <<= 1;
% S3 E* C I( J. r - SCK_HIGH;
$ q' D) M9 q. Z; P+ c - }. q1 C6 a1 m' W/ @5 M
- }
$ J0 [3 z V2 Q9 Z4 l2 L0 l% A - CSN_HIGH;" H: U( j Z4 E. U' G
- SCK_LOW;
0 U' V! i, Q1 @2 [! Y) H - }</i>
复制代码
# {8 E- G9 p" H4 t$ T四. NRF24L01命令详解
( Q' f9 T9 N8 c' a- o4 Q0 `7 x- f4 A( O5 [7 O' p% h
5 b: B- ^+ M Q9 N+ v
' X6 F' N5 g: Q: W( L3 [0 }4 Y
通过上图,可以看到一共只有8个命令。其中常用的有前六个命令
2 r9 q S! @1 T* d1 s8 f+ Y5 j |+ j: }R/W_REGISTER: 读写寄存器命令,对同一个寄存器进行读写,命令只有第六位不一样,为1就是写,为0就是读。A就是具体的寄存器的地址了。这里有一点要注意,写寄存器是有要求的,只有在掉电或者待机模块下可写。可以简单理解为CE为0,就可以写。
$ H# F# M8 g- LR_RX_PAYLOAD : 读取接收到的数据% A, ?" X- `( ]% p
W_RX_PAYLOAD:将需要发送的数据写入fifo中,等待发送
- U, c; q+ B) ZFLUSH_TX/RX: 清空发送/接收数据的FIFO。
4 N( r/ }$ n0 Z# D% \4 i/ T/ b
& w9 D1 f4 Z) t* p C$ d五. NRF24L01寄存器* m& q* R4 W! p, o
一共有24个寄存器,这里就不一一列举出来了,具体对应的功能可以查看数据文档(是中文的哦)。9 W) c8 t2 e2 C2 m8 h1 Y
' }: [9 b0 S# F5 i
- struct Nrf24L01{
6 C/ A7 y+ @- a1 z! s; U8 s - uint8_t Control;4 N, ]+ f2 d' d
- uint8_t EN_AA;" |; Y. `1 @ p5 p; t; h' t
- uint8_t EN_RXADDR;1 J8 S, n1 q- O, v. j1 `- x
- uint8_t SETUP_AW;
" C4 _$ U$ _0 |( ?% U - uint8_t SETUP_RETR;
; r# D7 |' ]4 U+ J4 ?- C - uint8_t RF_CH;
( U8 ^6 m8 v [! ?( n - uint8_t RF_SETUP;
; f5 T, [! F3 S) j9 U! E- d7 h - uint8_t STATUS;
: J( P( L% L2 G0 \4 S0 l" y - uint8_t OBSERVE_TX;
( y7 h( g/ c0 m2 C1 S! s+ ~5 i3 | - uint8_t CD;% M J% l$ m, S$ G
- uint8_t RX_ADDR_P0;
2 S5 f, y& }' y. F - uint8_t RX_ADDR_P1;& o/ D$ o! y: S r; `) o
- uint8_t RX_ADDR_P2;
. h3 [, Z- b1 r- i& M5 W2 G4 W) }. Z - uint8_t RX_ADDR_P3;
3 b- m4 U4 L7 l8 P$ N& ?5 A0 S - uint8_t RX_ADDR_P4;
, e# U. ~4 t& l' a- |# q - uint8_t RX_ADDR_P5;
: | d. X, ]" f3 V5 j1 {# W - uint8_t TX_ADDR;! ~4 J1 B4 @, E9 b8 w/ j
- uint8_t RX_PW_P0;( h+ v+ c8 j' ? x
- uint8_t RX_PW_P1;% {: w/ N7 f5 Z4 L( y7 q. O
- uint8_t RX_PW_P2;8 X- ?1 M& {! y* i6 ~5 s
- uint8_t RX_PW_P3;
7 m6 K# p) C6 i; ?. t! D - uint8_t RX_PW_P4;- N) m1 l$ r3 G
- uint8_t RX_PW_P5;+ U$ [, o% r7 t9 ^2 Q
- uint8_t FIFO_STATUS;8 W$ C* j8 k9 n
- };
复制代码 ; L4 ]7 N! F6 G) O( h
六. NRF24L01状态2 a9 B+ T6 g/ c K' k. Q0 N
通过下图,可以知道各个状态对应的功能。这里发送模型需要注意一下,6 y+ U6 K+ ]0 W) s' K6 x9 |
CE为高10us后,就开始发送数据,如果这个时候把CE拉低了,还是会停留在发送模式,直到数据发送完成,然后到待机模式19 {# `- @, S3 c' w' R
3 V+ Z6 Z1 D" c( h
, Q) c( H3 e+ z2 g; \- ?! e" X
9 D7 P: \: B: e7 c4 u( i: w3 [
2 m% p0 D& d# t, f |