正点原子H7R7开发板上面的NRF24L01接口是可以接一个NRF24L01模块的,原子论坛也提供了例程可供参考,但是是适配给原子自家的NRF24L01模块的,使用第三方模块厂出品的NRF24L01模块程序需要做一些细微调整,无法直接通用。8 Z; l8 Q& p- [4 j3 d( l3 L2 l
" Z8 E2 y1 k0 @3 ^+ S4 X* r首先是初始化SPI接口,这个非常简单:) n- a/ `- f( Y9 A; l6 m
- SPI_HandleTypeDef g_spi_handle;
+ W$ `7 b& |) X
' {# X( @ u t- uint8_t SPI2_PD3_PC2_PC3_Read_Write_Byte(uint8_t txdata)* ^; ~* |0 H! k, G, A5 f! L
- {# H) S% K( O# C, Y6 m6 S+ p! ^
- uint8_t rxdata;
2 K- t3 M; X) h+ E - HAL_SPI_TransmitReceive(&g_spi_handle , &txdata , &rxdata , 1 , 1000);
. w9 q+ [5 `+ ]3 `, H' J6 i9 U; b - return rxdata; |6 |0 M/ T; @- x0 l t9 [# `
- }
; C9 z0 ?5 z$ J6 _) H - $ c3 o( ^ s8 z8 @$ H$ l
- void SPI2_PD3_PC2_PC3_Init(void)0 d; h7 S: B6 R
- {$ Y3 h, W" ^! q
- GPIO_InitTypeDef gpio_init_struct = {0};; p6 D! H5 X, _7 ^
- RCC_PeriphCLKInitTypeDef rcc_periph_clk_init = {0};5 w Q6 H; W2 u
- + ]4 X+ ^! W( D
- __HAL_RCC_SPI2_CLK_ENABLE();2 {- ~; R5 S9 H* [4 I! ?. B
- __HAL_RCC_GPIOC_CLK_ENABLE();
% D* M& {; R3 o- q8 @1 F; G. X - __HAL_RCC_GPIOD_CLK_ENABLE();/ O' _$ s5 v8 C$ d. [8 {. N
- ) z3 c4 i+ R5 |0 J% V4 c
- rcc_periph_clk_init.PeriphClockSelection = RCC_PERIPHCLK_SPI23;8 I1 I, j* }+ o$ n$ {4 @
- rcc_periph_clk_init.Spi23ClockSelection = RCC_SPI23CLKSOURCE_PLL1Q;
$ R& d$ ?' C( K% V/ n& G5 U - HAL_RCCEx_PeriphCLKConfig(&rcc_periph_clk_init);
' l5 { r$ B, ] - % N1 a/ Y$ ?* }8 ?& Q
- gpio_init_struct.Mode = GPIO_MODE_AF_PP;
) M4 L0 L8 D. R( F$ k1 w0 { - gpio_init_struct.Pull = GPIO_PULLUP;
' k( L* u3 ?8 v5 T5 Z5 J7 a+ B" A - gpio_init_struct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
& [2 p! z: }9 I% L* Z
L, `; t( V- `" ~- gpio_init_struct.Pin = GPIO_PIN_3;
. w( P6 K, u+ F4 `) p+ g" f - gpio_init_struct.Alternate = GPIO_AF5_SPI2;
6 D5 k8 Q, [1 r" ]$ m, e: f) Z* | - HAL_GPIO_Init(GPIOD , &gpio_init_struct);( X5 G6 W* k' Q
6 r0 E& O" D3 j- gpio_init_struct.Pin = GPIO_PIN_2;; J# c0 P9 [5 s* H! H- R
- gpio_init_struct.Alternate = GPIO_AF5_SPI2;0 Q( r. u! H& y5 t; U: b
- HAL_GPIO_Init(GPIOC , &gpio_init_struct);
$ w( [' ^9 q+ h -
]7 Y7 M M7 l3 @8 L& K/ | - gpio_init_struct.Pin = GPIO_PIN_3;
+ d [. k# ~5 ?: p - gpio_init_struct.Alternate = GPIO_AF5_SPI2;9 ]4 \% K/ g& |& G7 O
- HAL_GPIO_Init(GPIOC , &gpio_init_struct);
$ Z2 D) ?! |" @, S: q' [9 }: S
/ i% L; ?2 H8 h o- g_spi_handle.Instance = SPI2;
+ D% K0 w$ F" V+ `# _% r* F - g_spi_handle.Init.Mode = SPI_MODE_MASTER;, {' G Q1 F b
- g_spi_handle.Init.Direction = SPI_DIRECTION_2LINES;3 C. T+ p3 k6 y: O5 b: j, J3 y7 n
- g_spi_handle.Init.DataSize = SPI_DATASIZE_8BIT;# h4 d1 v3 L5 h4 |
- g_spi_handle.Init.CLKPolarity = SPI_POLARITY_LOW;
7 o( ]6 @1 r- Q& J - g_spi_handle.Init.CLKPhase = SPI_PHASE_1EDGE;
& f5 E4 {) Q9 q$ y9 Y1 g - g_spi_handle.Init.NSS = SPI_NSS_SOFT;
" e) K% v: `9 D8 U7 ` E& S E% V- h - g_spi_handle.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;: A7 y+ i" b) S" u) R# i; |$ A
- g_spi_handle.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE;
" J. X2 z5 @* _6 E+ Z4 w - g_spi_handle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;+ U5 j+ n3 q Q
- g_spi_handle.Init.FirstBit = SPI_FIRSTBIT_MSB;) s3 Y7 Y5 s& r# P5 j
- g_spi_handle.Init.TIMode = SPI_TIMODE_DISABLE;6 Y- f# \) H4 d! k9 Q3 f
- g_spi_handle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
, [1 [: f5 Y' S4 Q - g_spi_handle.Init.CRCPolynomial = 7;. t7 Y! m/ X# x- [% Y+ O
- HAL_SPI_Init(&g_spi_handle);
+ k- c' Z7 z4 Q7 ]5 j - # U) [9 l" u) M! h3 L3 }% J/ m
- __HAL_SPI_ENABLE(&g_spi_handle);5 [7 |2 g" G7 H7 g; t: Z* Z
- SPI2_PD3_PC2_PC3_Read_Write_Byte(0Xff);
) p, z9 P6 o& F! q& [0 G% ] - }
复制代码 这里需要注意的是,H7R7的SPI接口时钟要设置为128分频或者256分频,因为SPI123三个接口的时钟直接挂在PLLQ上,分频太少的话,波形变形的程度使得NRF24L01无法识别,进而无法进行任何通信,然后就是时钟信号空闲时为低,第一个沿变开始传输数据,这个也是NRF24L01芯片的特性,不遵循这个设置无法进行通信。
0 b$ P& L, m# L$ X. K
) x5 A* L* }& \. UNRF24L01还需要用CS CE IRQ三个脚,其中CS脚是片选,需要在传输数据时进行控制,CE脚常高表示使能,IRQ脚是发送时会用到: a2 l% C1 e) Q
- #define NRF24L01_CS_GPIO_PORT GPIOM
5 ^) p$ @6 c8 h1 Q( }# v$ j6 ` - #define NRF24L01_CS_GPIO_PIN GPIO_PIN_13
8 S& S/ D5 K% l5 V. t0 ?2 d, U3 e - #define NRF24L01_CS_GPIO_CLK_ENABLE __HAL_RCC_GPIOM_CLK_ENABLE();
$ g; ~$ j& r0 d7 } - #define NRF24L01_CS_HIGH HAL_GPIO_WritePin(NRF24L01_CS_GPIO_PORT , NRF24L01_CS_GPIO_PIN , GPIO_PIN_SET);9 e) d2 L/ i3 W0 ?
- #define NRF24L01_CS_LOW HAL_GPIO_WritePin(NRF24L01_CS_GPIO_PORT , NRF24L01_CS_GPIO_PIN , GPIO_PIN_RESET);
. c; @) m0 O4 s' m1 M8 d& }5 g: G; P
; C* S4 z) P* y i* z- #define NRF24L01_CE_GPIO_PORT GPIOM7 K: `) b; d1 B* T% d( Y6 R% b$ s
- #define NRF24L01_CE_GPIO_PIN GPIO_PIN_14
1 J" R, u2 a3 @ - #define NRF24L01_CE_GPIO_CLK_ENABLE __HAL_RCC_GPIOM_CLK_ENABLE();
! b- ?' G. K4 H6 D - #define NRF24L01_CE_HIGH HAL_GPIO_WritePin(NRF24L01_CE_GPIO_PORT , NRF24L01_CE_GPIO_PIN , GPIO_PIN_SET);+ s: q0 X, V) H
- #define NRF24L01_CE_LOW HAL_GPIO_WritePin(NRF24L01_CE_GPIO_PORT , NRF24L01_CE_GPIO_PIN , GPIO_PIN_RESET);
3 G- X. {7 n5 _4 n# l
8 k2 Q1 C0 n5 ]; ` q4 G2 B3 y- #define NRF24L01_IRQ_GPIO_PORT GPIOF
1 i- }' l8 P1 m - #define NRF24L01_IRQ_GPIO_PIN GPIO_PIN_28 O* q$ g- @0 U4 \+ |2 R
- #define NRF24L01_IRQ_GPIO_CLK_ENABLE __HAL_RCC_GPIOF_CLK_ENABLE();
( ^* @$ o; W# S% t7 s: ?' K7 b - #define NRF24L01_IRQ_READ() HAL_GPIO_ReadPin(NRF24L01_IRQ_GPIO_PORT , NRF24L01_IRQ_GPIO_PIN)
7 ~9 T* v" P, x
9 h v' F1 ?9 Y- Z& H1 D6 x- void NRF24L01_GPIO_Init(void)
( ]# c+ N& e& n+ {" x6 K4 W - {7 s. n# h( \. D6 A5 z5 L8 L7 T
- GPIO_InitTypeDef gpio_init_struct;
- ] C. z# M' o2 W8 @* V0 x - NRF24L01_CS_GPIO_CLK_ENABLE; e9 w. b* e9 U2 P+ z- z
- NRF24L01_CE_GPIO_CLK_ENABLE;) Y' u- Y, g! Y8 l2 p
- NRF24L01_IRQ_GPIO_CLK_ENABLE;6 T" ]4 ?+ `: l3 h
-
5 W8 m6 m& {1 X: }9 i' ^5 _/ T! J5 l - gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;9 z: l4 D# w0 a! B+ W
- gpio_init_struct.Pull = GPIO_PULLUP;
, X; _6 n3 b; T4 Q/ Y+ | - gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;( E0 w5 X: S& S; H! e, I6 v5 U
-
O+ P5 `* L: p: R6 ?- D - gpio_init_struct.Pin = NRF24L01_CS_GPIO_PIN;
7 D7 y4 f R9 Q2 J1 q' P2 f - HAL_GPIO_Init(NRF24L01_CS_GPIO_PORT , &gpio_init_struct);: z* y; U* ~) H" x/ r* e9 a1 F
-
# a) b7 \% \0 O* q - gpio_init_struct.Pin = NRF24L01_CE_GPIO_PIN;
1 A% n$ U/ R/ ^+ a% `# a - HAL_GPIO_Init(NRF24L01_CE_GPIO_PORT , &gpio_init_struct);
9 [4 p" @3 F4 b8 F - ; c+ }. D5 j2 I2 {+ A0 Q& ]
- gpio_init_struct.Mode = GPIO_MODE_INPUT;
4 m! `/ k# F' G# j8 L: @7 t - gpio_init_struct.Pin = NRF24L01_IRQ_GPIO_PIN;/ P7 D q: P7 M; N
- HAL_GPIO_Init(NRF24L01_IRQ_GPIO_PORT , &gpio_init_struct);# \3 T% R' R. z& x3 W
-
$ i. I5 A! Q! m1 l# L) @ - NRF24L01_CE_LOW;
5 r+ f4 |' r3 f! l7 a6 b; D - NRF24L01_CS_HIGH;
! W- |5 W/ w" H+ S! o% _/ N - }
复制代码 5 W: l% \4 \: i
4 K z S6 O1 {1 |5 s. p" }7 u
8 ~: T& Y4 l* r* v1 A+ n3 h2 P r l
NRF24L01有五个寄存器是可以用来检测器件是否正常工作的:' _8 a% K6 l' _! h/ l5 L/ _4 V
- uint8_t NRF24L01_Check(void)6 r0 b4 ?- g' Y3 L, P
- {! k+ U0 r% y. S
- uint8_t buf[5] = {0xa5 , 0xa5 , 0xa5 , 0xa5 , 0xa5};; Z8 M3 V( a" B
- uint8_t i;& f2 @6 d3 `2 x. X( l
- NRF24L01_Write_Buf(NRF_WRITE_REG + TX_ADDR , buf , 5);+ ^; E9 r' |3 W3 a, @& s1 i3 f/ K) E
- NRF24L01_Read_Buf(TX_ADDR , buf , 5);
- Q; \$ A4 R8 ^. h7 ` - for(i = 0 ; i < 5 ; i++)9 Q. {6 Z8 u- A
- if(buf[i] != 0XA5)$ i! U' {% S* T, F9 q4 o; T1 h
- break; 4 O' a4 z4 X+ J8 r+ L: Q% f2 H( C
- if(i!=5)9 g! ^, o0 V6 w5 l) s( G$ a
- return 1;
. O% o, C! V E( x/ \ - return 0;
- c+ E U8 }/ M& U$ o - }
复制代码
' S# T w- G& \NRF24L01模块在同一时间只能设置为只接收或者只发送模式,属于半双工器件,要实现全双工收发需要两个模块:
' n" N6 O2 U) o- I* G4 v t4 U. K- void NRF24L01_RX_Mode(void)( y* b P' Z' s& T9 U; x
- {9 S; F0 k1 b1 K4 B5 }
- NRF24L01_CE_LOW;; k& Z. `; q, Q: M( G+ A3 d* q
- NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(uint8_t*)RX_ADDRESS,RX_ADR_WIDTH);5 V/ |1 J% y3 Z6 w7 n
-
# L7 ?/ F' W1 G& o' D( E1 I - NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01);
' W, E6 l6 p0 a - NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01);
& D8 d' M+ `9 c+ V6 B - NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40); x" c' L/ T, \ I" R- [5 A+ y8 P
- NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);' v5 v) G6 A+ M4 H
- NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);
$ h9 Q, `; k6 n- ~ - NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG, 0x0f);
3 U, q D. P- P, I! V - NRF24L01_CE_HIGH;" B7 v' d0 g: f4 L
- }& D/ y) k" d, k$ F5 [$ q
' R, L$ z! s- x ]; L% A2 K1 J- void NRF24L01_TX_Mode(void)
& t) u+ L3 L: g% n! Y# Z - {
5 g. h! \5 ]9 g4 v - NRF24L01_CE_LOW;
7 \2 @ c) O7 K# t2 D - NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(uint8_t*)TX_ADDRESS,TX_ADR_WIDTH);, [' s& R! f% A( b: D' |. w
- NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(uint8_t*)RX_ADDRESS,RX_ADR_WIDTH);3 G( g6 k; x; g3 @3 S
- ; P. J$ P! V" O1 `& \" \' w8 X
- NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01);& \. c1 M! j" q8 v1 Q4 M# x" |5 Q& M
- NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01);
4 u) V( K% ]" e3 o; O+ E - NRF24L01_Write_Reg(NRF_WRITE_REG+SETUP_RETR,0x1a);' e) l6 O& y6 |% G+ t) a* W' C
- NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40);
# C& z2 n# g: s- h" F: n* ] - NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);
5 w: L( y; N/ \" n2 V - NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0e);2 p% M* j* G; Z
- NRF24L01_CE_HIGH;- e3 Y: H J! Z- o
- } b% q6 Q# K( c* }! Y" b
, s( D) [: y: c3 r" T) H ?6 _- uint8_t NRF24L01_RxPacket(uint8_t *rxbuf)2 N- \0 J* q4 T) {
- {
& U- n4 u9 ]$ B- B; u# u, F0 O - uint8_t sta;
% A0 R1 t* } k; W z - sta = NRF24L01_Read_Reg(STATUS);
1 ]% G( e6 z& a, S
2 b3 h2 ]6 X6 e0 @) t- NRF24L01_Write_Reg(NRF_WRITE_REG + STATUS , sta);
- Y3 _5 f% S) q3 _ -
" k* O# i' G5 ?, Y5 z/ |. y; } - if(sta & RX_OK)! d2 ^0 D" a/ I( ~7 I7 E+ p* m) O
- {, R# y/ R7 e4 }: E1 Z+ P0 r
- printf("sta = 0x%x RX_OK.\n" , sta);; {4 e7 V, R8 X# R) B5 ?8 _
- NRF24L01_Read_Buf(RD_RX_PLOAD , rxbuf , RX_PLOAD_WIDTH);: g! S; C; ?% V9 R! h; @7 l
- NRF24L01_Write_Reg(FLUSH_RX , 0xff);
( e5 P# f- t! G6 m5 c* W- Q - return 0;" P9 d/ o$ ~5 T- s6 D
- } $ I2 v1 \7 i I4 j# {( {
- return 1;) G8 o. S! [3 D6 {# M
- } ' p3 o9 [% j3 ^& w
" `5 n7 k8 g4 [) m) m/ n- uint8_t NRF24L01_TxPacket(uint8_t *txbuf)1 ~7 F% S% T* L) z6 A* K- W
- {& s( O8 h1 a. ? N7 X, q% D
- uint8_t sta;
- p9 g5 d8 l- Y - NRF24L01_CE_LOW;
8 C( Y4 k) I1 K, R: }/ Y6 P - NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);
/ ` Y4 n! L: Q - NRF24L01_CE_HIGH;
$ `+ T# N! |5 Y) O0 q/ } - while(NRF24L01_IRQ_READ() != 0);
$ ]& O0 h+ `, Y8 a6 ~1 G - sta = NRF24L01_Read_Reg(STATUS);
5 N& Q$ c; t; }7 H, T - NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta);2 r# L0 `2 _: T7 p& s- U1 @8 d
- if(sta&MAX_TX)5 g* z! J, m0 b# h$ f7 U( N# d
- {* p+ w1 _3 k( C+ M2 t
- NRF24L01_Write_Reg(FLUSH_TX,0xff);
1 F1 g9 e$ {7 @ - return MAX_TX;4 S0 h7 D4 T! m" }4 k$ @3 R
- }
' P1 e8 A% Q! c; _' ? - if(sta&TX_OK)+ r" x8 `& V) ]$ v; n
- {
4 ~7 q6 U# s$ i6 j. ?7 z - return TX_OK;# ^4 [) C6 c' h4 P4 t u0 ^0 s
- }
: q2 c' W" D' s, D) u. L0 ~ - return 0xff;$ _0 d: z0 q1 @8 i# Y3 g
- }
复制代码
; a) W' \7 g( ~ z! {我这里在主界面创建一个flexButton用于控制NRF24L01模块发送一行数据:
, K+ R& v6 n& ~8 `: \6 y6 d5 ]( R
( b0 c" w7 l9 Z$ w8 ~9 s: s
q" x9 a% q7 ^" C7 f) X( Q看看发送效果,按下fb之后,H7R7开发板会通过NRF24L01模块发送一行字符串,另一个设置了相同接收地址的NRF24L01开发板就会收到这个字符串:8 y" D. I5 V, u
$ y6 m0 }; ?2 X9 G- ?然后是接收,接收就更简单了,只需要设置模块为接收模式后,在Tick事件回调函数调用即可:
5 Y. K3 E7 o3 b; ?6 ]4 n: c! f
8 X: `! {! h, m3 Z% r1 A
|