一. 简介" [) H1 V0 U9 I9 X. t
在各个无线通信模块中,由于NRF24L01价格便宜,而且体积小,以及不需要外接天线,传输距离约为10-20米,深受大家的喜爱。在遥控汽车,四轴飞行器中较为常见,在这里给大家分享其具体的使用。! Q$ @+ T. y; I% r; y
+ M: G' d. j6 m) s" G: ]
模块共用8个引脚, O8 e$ O' c+ k& H6 h2 g
通信方式为SPI接口,速率不能太高,最好在10M以内。
3 |' t5 \. N, z! o# T5 p& a
: z- D, X! n Y6 c7 x3 d! X ^0 B
e# {' c" \. b% H! l& H K; ~$ k9 ?, [4 X
IRQ : 中断输出,例如发送完成,或者接收完成。默认为高电平。/ n- j `6 Y" ~
CE : 芯片的使能引脚
' K4 _ `- x& ` o2 zCSN:SPI协议的使能引脚0 @% f2 n- V, g
二. 数据传输过程
3 a5 v- J/ @+ z% S+ Q- ~+ A从图中可以看出,数据传输的一些特征。CSN默认为高电平,SCK默认为低电平。数据在SCK的下降沿送出,在SCK的上升沿读取数据,先发送高位,再发送低位。如果使用硬件SPI的话,就可以基于这个来设置SPI极性的相关参数了。
$ k G, s9 |+ ]8 N. h8 W先发送指令(在发送指令的同时,nrf会返回状态值),然后后面就是写数据,或者是读数据了。! R& L1 D5 Z# d% f
: n( _! O- r1 v
- S: l% Y6 z* d$ @; j
. ^! U% y! v# t& Z: D$ D三. 协议实现
' E# ?+ z+ Z* g; n) D由于这里的SPI的速率不能太高,所以这里就采用软件的方式来实现这个传输过程(使用硬件的话,可以将分频设置大一点),这样就可以任意选择适合的引脚了。
3 B' q$ a7 R! }1 ?) q其中delay()是个空函数,可以加点延时,也可以不加。
; x A' t2 C; E( YCn :命令
; p' D7 m2 t$ Y& YData: 写入的数据
; x* R" [/ u7 H* d2 xsize : 数据的大小! `- }3 t0 `1 o$ z: _) t( l
8 H9 Q1 p9 k" W9 }5 i8 l+ `
代码的实现过程,是和上图一一对应起来的,就作详细的说明了。
2 Y% _* ?- k1 C v6 e
, H5 S4 e1 \( L o- void SPI_Write(unsigned char Cn,unsigned char *Data,unsigned char size){0 m2 F1 U0 n. n+ ?, A; d: T
- unsigned char i,j;' O0 E6 w5 _, d! P9 f
- CSN_LOW;' ^6 [ \9 i' W: T4 U2 {4 ~0 R j
- /*写操作符*/
( { }. k/ f# t& p, P$ K: M9 D - for(i = 0;i < 8; i++){+ ?7 _3 O/ }0 i$ q
- delay();
9 o! B: V8 V: q- h& t) U - SCK_LOW;: Y7 j) U0 X. [$ h+ f! w% A
- if(Cn & 0x80)0 o( i3 g; `6 M1 [* Y2 d* R4 O$ g
- MOSI_HIGH; y/ O1 Q5 A- G s" P8 p
- else
# v' {: }) z2 a n% M - MOSI_LOW;
) U* `, k" f% b - SCK_HIGH;. `# Y4 [4 m& x# b ?6 H
- Cn <<= 1;
3 X. W# g; f0 l4 J- ]/ B% P' v2 E - }
* s+ ^0 @; r) u7 T/ t& n - delay();* c# }7 X5 \8 Q5 l* n9 V
- /*写数据*/! @( j/ g- H. u* d6 S
- for(i = 0;i < size ;i++){" K! _8 M7 N. T: @8 f- \8 [
- delay();
0 v) l9 C2 e5 f% W. @ y. w - SCK_LOW;
V- {: H0 K, K - delay();6 [5 H4 v$ L2 {. u6 b9 J
- delay();
, K* Y& |$ l% `: w! ]5 j* a - unsigned char d = Data<i>;
4 F8 n7 z7 D% H - for(j = 0;j < 8;j++){# \9 b3 T- v q7 m& R/ X
- SCK_LOW;5 e, w+ \: h1 U+ G6 g
- if(d & 0x80){ 9 g, X9 ~9 q: H) B
- MOSI_HIGH;7 n/ U3 w; X$ ]- T/ L' ?( O
- }3 B9 U8 s3 Y, \# H9 v
- else{ / O% D {# n0 j/ e; q: @
- MOSI_LOW;5 N8 x- @. f v9 G' \7 [' r) m
- }% _* r3 x; L6 h9 D) h7 F5 x B; _
- SCK_HIGH;
7 j4 w! Z, P+ C4 ~8 y - d <<= 1;
; W( _; _ X4 _ t% e: G - SCK_HIGH; 0 v4 C9 g, H. S
- }6 f6 l! ^/ @$ z# V+ ?
- }1 |, a0 t& E+ x2 ]& m V" X
- CSN_HIGH;
. @3 r% v; `4 ?, h# _8 ] - SCK_LOW;4 ?, s, c% i+ f# E/ }3 Y* j6 z
- }</i>
复制代码
* z# s) Q- d- J O% o四. NRF24L01命令详解7 E" J0 \7 o) p$ J
, V5 n2 O) E, J8 o0 S% o
# e" I# @) X" U; D' C' X: I0 f- t9 O( g* e5 d k
通过上图,可以看到一共只有8个命令。其中常用的有前六个命令
7 z, a* L; a6 t6 m# jR/W_REGISTER: 读写寄存器命令,对同一个寄存器进行读写,命令只有第六位不一样,为1就是写,为0就是读。A就是具体的寄存器的地址了。这里有一点要注意,写寄存器是有要求的,只有在掉电或者待机模块下可写。可以简单理解为CE为0,就可以写。% i( f' ?6 @0 q4 x; X
R_RX_PAYLOAD : 读取接收到的数据! J l2 g$ `! K# @# `9 S
W_RX_PAYLOAD:将需要发送的数据写入fifo中,等待发送
3 d5 k- u. s- H/ i, P7 S, r) \" u: h. TFLUSH_TX/RX: 清空发送/接收数据的FIFO。
$ A8 o" s# l: N8 u8 t! s& q0 f8 P$ V3 v+ q
五. NRF24L01寄存器) M+ \# g3 {8 q0 d
一共有24个寄存器,这里就不一一列举出来了,具体对应的功能可以查看数据文档(是中文的哦)。 k& L+ w* H: m
: n+ W9 Z) d% ?2 A8 a# m3 B- struct Nrf24L01{
: {1 l+ \$ C/ N8 g$ `' b - uint8_t Control;
* H' s, `. |% o. r5 u - uint8_t EN_AA;
: L y; D/ l2 H8 V) W3 { - uint8_t EN_RXADDR;
% K, R# n7 m: o; M* T) B - uint8_t SETUP_AW;
# Y5 y; S2 @5 v: u8 y1 c+ G7 g7 C5 ? - uint8_t SETUP_RETR;
3 K1 Q/ s8 C6 Y& u - uint8_t RF_CH;
7 Y& r) S7 Z/ l& `/ t - uint8_t RF_SETUP;
/ d) R c$ b7 N, a) }) q$ e) p - uint8_t STATUS;8 E% p1 C8 ?+ E' y" o& y
- uint8_t OBSERVE_TX;0 q) \: ~ L W, d" `. j' D
- uint8_t CD;. e) z1 v6 J, e7 u
- uint8_t RX_ADDR_P0;5 [' \+ t; H! l7 M& T0 O' H
- uint8_t RX_ADDR_P1;' I, F a+ |. d, e' I% N1 T" K
- uint8_t RX_ADDR_P2;
( `9 {1 f( s5 K- b4 `, A$ c$ f! O - uint8_t RX_ADDR_P3;6 i5 W9 N# q* n6 G* p; p+ q1 N
- uint8_t RX_ADDR_P4;6 n8 ^* G: B( N& @ {% d; k
- uint8_t RX_ADDR_P5;
u! t, _4 J8 v( \ z% l; @5 ] - uint8_t TX_ADDR;
/ u; e" a: i" O* `8 Q - uint8_t RX_PW_P0;
5 W6 V8 v5 g D7 k1 L* w: Z* n$ B- `: T - uint8_t RX_PW_P1;
1 z2 r' t. B" L - uint8_t RX_PW_P2;
3 G6 a: L' m- X% s - uint8_t RX_PW_P3; v' w0 T1 S8 u0 o. @2 C$ G
- uint8_t RX_PW_P4;
6 H' h( l) D1 K+ p/ ]% w" a9 T - uint8_t RX_PW_P5;
* B" b- _ Q: l$ D9 \ - uint8_t FIFO_STATUS;
$ ~: X) X# N8 \% ]& _% Q - };
复制代码 & k& J3 n: ~4 V; J! _; S$ K
六. NRF24L01状态# _- B% u* j- R9 [; u+ o
通过下图,可以知道各个状态对应的功能。这里发送模型需要注意一下,' h( X4 `& A" {
CE为高10us后,就开始发送数据,如果这个时候把CE拉低了,还是会停留在发送模式,直到数据发送完成,然后到待机模式1" X' C: W! a. J' J) `1 l6 R/ X% x
( O7 U" O) J+ `2 L, u8 c' A
9 B4 R2 J! A, R6 w; y" m/ b
, ^4 I7 y' {1 r8 Q
# r5 s5 `; O$ e$ ~% e |