正点原子H7R7开发板上面的NRF24L01接口是可以接一个NRF24L01模块的,原子论坛也提供了例程可供参考,但是是适配给原子自家的NRF24L01模块的,使用第三方模块厂出品的NRF24L01模块程序需要做一些细微调整,无法直接通用。
" V0 j/ B! |- z2 v
4 a! r9 P% A& T7 P5 d- i* Q- U* l
首先是初始化SPI接口,这个非常简单:; Q ]/ W9 g- L: i4 \/ J1 f
- SPI_HandleTypeDef g_spi_handle;
) V4 [ I, G$ s6 o! w# O/ w - " `8 b; n& v1 T/ N# }
- uint8_t SPI2_PD3_PC2_PC3_Read_Write_Byte(uint8_t txdata)
# U. ]8 V4 n) m - {
7 V# K% ~8 t# L/ E/ V# ` - uint8_t rxdata;
5 e9 n/ O7 ~! f8 u, Q& ]: x - HAL_SPI_TransmitReceive(&g_spi_handle , &txdata , &rxdata , 1 , 1000);+ D/ t& f+ Q+ ~% P
- return rxdata;
* F& c O& S ~. x( Y) b4 b% o$ | - }
9 a* _2 d2 W0 a# \" e# l# D2 C
, q! t% ^1 D. d, _+ y+ j* A8 M- void SPI2_PD3_PC2_PC3_Init(void)
& y8 x3 [ I( Y( o& ~ G - {
- b' K0 \) k+ F% A - GPIO_InitTypeDef gpio_init_struct = {0};3 Q1 ]# T7 u: n. ~* r
- RCC_PeriphCLKInitTypeDef rcc_periph_clk_init = {0};
: D) ?" p& w: a4 W) I
$ {! ^: p9 q/ z. H6 u) d- __HAL_RCC_SPI2_CLK_ENABLE();. g) t' L* r- a* z8 t1 M) y" K. f @
- __HAL_RCC_GPIOC_CLK_ENABLE();$ D& ?- P& o" x/ e, d
- __HAL_RCC_GPIOD_CLK_ENABLE();! K+ M* A( D: ^& f$ J# w9 _' f
-
- n" z1 @' u: G - rcc_periph_clk_init.PeriphClockSelection = RCC_PERIPHCLK_SPI23;& l' v. T) `9 e9 L" J E, M0 T
- rcc_periph_clk_init.Spi23ClockSelection = RCC_SPI23CLKSOURCE_PLL1Q; G4 ]# J6 z. [" d6 p% I
- HAL_RCCEx_PeriphCLKConfig(&rcc_periph_clk_init);
: m$ I0 @* p8 ]8 g: j# \7 g - 3 |) r; z. y, e2 k4 J
- gpio_init_struct.Mode = GPIO_MODE_AF_PP;+ j3 ?, A$ p! U8 D9 {' o' `
- gpio_init_struct.Pull = GPIO_PULLUP;2 L5 B4 E7 _7 L0 B5 q
- gpio_init_struct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
2 |% v8 H; z2 L9 R: { i - 7 {$ ]% {) V) O& O; m6 Y
- gpio_init_struct.Pin = GPIO_PIN_3;" i7 G j4 v! o3 [; A5 X9 x
- gpio_init_struct.Alternate = GPIO_AF5_SPI2;
/ ~& j5 T. ?: _# }& E4 h% K# Z - HAL_GPIO_Init(GPIOD , &gpio_init_struct);! Q7 [$ D+ ^. p. U
$ a$ p- M4 D2 M6 H* I0 v' L- gpio_init_struct.Pin = GPIO_PIN_2;. E" {# ]. L$ t! @) T
- gpio_init_struct.Alternate = GPIO_AF5_SPI2;/ A* B G% U* t& D7 o# n
- HAL_GPIO_Init(GPIOC , &gpio_init_struct);
: R4 u/ V4 T9 J: w -
5 c9 u2 I* Y! g$ c: I - gpio_init_struct.Pin = GPIO_PIN_3;' @ P3 c$ N* S' v
- gpio_init_struct.Alternate = GPIO_AF5_SPI2;
2 d- {0 F% {2 D: h% m, r* ~ - HAL_GPIO_Init(GPIOC , &gpio_init_struct);. v, A5 j8 R; L7 v
- - `# C( `6 a4 ^# G4 k7 ^6 r
- g_spi_handle.Instance = SPI2;2 q3 ~% E" `( B3 h |5 p; O3 p
- g_spi_handle.Init.Mode = SPI_MODE_MASTER;& E- d! A9 k1 C/ L# t5 X$ L; p
- g_spi_handle.Init.Direction = SPI_DIRECTION_2LINES;
! ^/ {) X, ^' h8 [% F: S p - g_spi_handle.Init.DataSize = SPI_DATASIZE_8BIT;
9 O: d& \5 k3 [4 i, E6 u8 A - g_spi_handle.Init.CLKPolarity = SPI_POLARITY_LOW;4 K+ J6 ~2 H$ u4 _% \ g7 c% i0 l
- g_spi_handle.Init.CLKPhase = SPI_PHASE_1EDGE;( w: s* C% ^ {5 L( I
- g_spi_handle.Init.NSS = SPI_NSS_SOFT;
# J! {. V* ?* l1 ^; _ - g_spi_handle.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
+ _8 u' Y$ ]# ]) N1 I - g_spi_handle.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE;
. @8 H: o+ X4 b$ _$ `8 S8 A" t) | - g_spi_handle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;
% s( O4 c, k6 {% G - g_spi_handle.Init.FirstBit = SPI_FIRSTBIT_MSB;; e: c7 s! P- h* T1 e
- g_spi_handle.Init.TIMode = SPI_TIMODE_DISABLE;
( D, m, S$ a% n$ q$ t5 F2 L# Y - g_spi_handle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
! w+ q4 s, [$ @/ \ - g_spi_handle.Init.CRCPolynomial = 7;; V. v6 k3 d: s. U; @" d
- HAL_SPI_Init(&g_spi_handle);3 g0 K0 l8 x5 w- s' ]
- - n( j. X; x5 {
- __HAL_SPI_ENABLE(&g_spi_handle);. v3 A7 Q7 G1 f
- SPI2_PD3_PC2_PC3_Read_Write_Byte(0Xff);1 P& G7 |) m4 {9 _
- }
复制代码 这里需要注意的是,H7R7的SPI接口时钟要设置为128分频或者256分频,因为SPI123三个接口的时钟直接挂在PLLQ上,分频太少的话,波形变形的程度使得NRF24L01无法识别,进而无法进行任何通信,然后就是时钟信号空闲时为低,第一个沿变开始传输数据,这个也是NRF24L01芯片的特性,不遵循这个设置无法进行通信。
# b3 r2 F( D: o# v' o
1 o. W. b$ Z, x7 z0 G k' INRF24L01还需要用CS CE IRQ三个脚,其中CS脚是片选,需要在传输数据时进行控制,CE脚常高表示使能,IRQ脚是发送时会用到:: z1 |) K" c1 u- j
- #define NRF24L01_CS_GPIO_PORT GPIOM( U! ?3 D ^6 x1 p7 F; X
- #define NRF24L01_CS_GPIO_PIN GPIO_PIN_13
' \; W9 T5 d0 x - #define NRF24L01_CS_GPIO_CLK_ENABLE __HAL_RCC_GPIOM_CLK_ENABLE();
2 ~& X$ L* Z8 D# } - #define NRF24L01_CS_HIGH HAL_GPIO_WritePin(NRF24L01_CS_GPIO_PORT , NRF24L01_CS_GPIO_PIN , GPIO_PIN_SET);
4 Q9 f2 K" W$ x6 W6 [" H0 `7 S - #define NRF24L01_CS_LOW HAL_GPIO_WritePin(NRF24L01_CS_GPIO_PORT , NRF24L01_CS_GPIO_PIN , GPIO_PIN_RESET);2 |; r6 \) ~% U
- 0 t E& s4 y; w
- #define NRF24L01_CE_GPIO_PORT GPIOM# l* {1 t ~" ]3 N
- #define NRF24L01_CE_GPIO_PIN GPIO_PIN_14
* D2 D$ a2 J* Y% W3 _ - #define NRF24L01_CE_GPIO_CLK_ENABLE __HAL_RCC_GPIOM_CLK_ENABLE();# T. Z0 O) }' {
- #define NRF24L01_CE_HIGH HAL_GPIO_WritePin(NRF24L01_CE_GPIO_PORT , NRF24L01_CE_GPIO_PIN , GPIO_PIN_SET);
8 M5 I+ M* H3 @) o6 }$ |7 d% B - #define NRF24L01_CE_LOW HAL_GPIO_WritePin(NRF24L01_CE_GPIO_PORT , NRF24L01_CE_GPIO_PIN , GPIO_PIN_RESET);6 w( G; I5 u+ V" m
/ `" D9 S6 S$ ]- O& Z- #define NRF24L01_IRQ_GPIO_PORT GPIOF
4 z( t. ]. a5 @2 `: O - #define NRF24L01_IRQ_GPIO_PIN GPIO_PIN_2
0 s4 D0 j4 N5 G3 L, n - #define NRF24L01_IRQ_GPIO_CLK_ENABLE __HAL_RCC_GPIOF_CLK_ENABLE();: B) n; M; p. t
- #define NRF24L01_IRQ_READ() HAL_GPIO_ReadPin(NRF24L01_IRQ_GPIO_PORT , NRF24L01_IRQ_GPIO_PIN)
) q" D1 I4 E* w* G6 W- D( O - 7 n( [" t- }1 Z$ Z
- void NRF24L01_GPIO_Init(void)
: G. R3 N: ~: s4 P4 z - {( L+ S0 z# ]# Z9 {7 ~
- GPIO_InitTypeDef gpio_init_struct;. L8 }( F2 v: r R: e1 A
- NRF24L01_CS_GPIO_CLK_ENABLE;# h" a' q0 F8 ]" [$ s
- NRF24L01_CE_GPIO_CLK_ENABLE;
8 o$ K) P1 a5 ]" M+ z9 J1 o7 i* T - NRF24L01_IRQ_GPIO_CLK_ENABLE;% l6 c* Z: \1 R- ~" t4 v0 z% b
- ! b0 L7 b/ j4 W( B( G4 [! o. Y
- gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;+ `) C& m/ F' { i6 D3 M, t) L
- gpio_init_struct.Pull = GPIO_PULLUP;: _7 P- O4 \( i' F% @1 u) A
- gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;( p2 b2 F7 t/ m1 [1 C
-
( R3 }( k! N, t5 p8 R) {# B( d - gpio_init_struct.Pin = NRF24L01_CS_GPIO_PIN;
' X4 R2 s- |6 ^0 g& Y. z$ d - HAL_GPIO_Init(NRF24L01_CS_GPIO_PORT , &gpio_init_struct);
- \, z0 C1 ~- K4 J* y3 n -
5 _$ _# b$ ?( v h) v; i4 e3 d6 M - gpio_init_struct.Pin = NRF24L01_CE_GPIO_PIN;
5 A9 w7 P' U. C4 \2 l$ W - HAL_GPIO_Init(NRF24L01_CE_GPIO_PORT , &gpio_init_struct);
( C% b$ j+ C/ i2 E$ d0 i9 L( z - 7 A6 f0 B% }# R' D
- gpio_init_struct.Mode = GPIO_MODE_INPUT; N; D! p. @$ s! t6 z8 ?+ q+ t, `: Z
- gpio_init_struct.Pin = NRF24L01_IRQ_GPIO_PIN;5 j; @4 H+ \5 P% q9 f$ q
- HAL_GPIO_Init(NRF24L01_IRQ_GPIO_PORT , &gpio_init_struct);0 I! |& S' G3 [) S% Y
-
0 a$ }# o3 {0 T: G! K5 S - NRF24L01_CE_LOW;8 W% q) r* `& c: Z+ X
- NRF24L01_CS_HIGH;% n" B% u6 h6 `& ~7 f0 }
- }
复制代码
0 B7 E C, _5 r2 w, B/ V, o& \% U
) X; w1 {# E. C6 W
6 {2 P" U8 V% b/ T, M3 rNRF24L01有五个寄存器是可以用来检测器件是否正常工作的:
- \/ F. k9 v% Y5 r0 a) ~$ {2 |+ ^ f3 H- uint8_t NRF24L01_Check(void)
7 a( H9 \; J( a( ?! P, t9 K) O - {. b! ~5 V$ x8 v2 f2 [% f) ?
- uint8_t buf[5] = {0xa5 , 0xa5 , 0xa5 , 0xa5 , 0xa5};6 X5 X) J6 e2 }& K
- uint8_t i;
9 [5 p( I4 @% \( p - NRF24L01_Write_Buf(NRF_WRITE_REG + TX_ADDR , buf , 5);, {3 }3 A) V* o& d
- NRF24L01_Read_Buf(TX_ADDR , buf , 5);4 }; N2 O( M, e' D8 D! Q
- for(i = 0 ; i < 5 ; i++)5 c. b9 F; C2 |% Y
- if(buf[i] != 0XA5)
8 r, L, G1 F1 t+ `# Y4 b+ v - break; ! i6 Q! \0 |. K- S3 O& m
- if(i!=5)" l5 L% x: u8 m5 \
- return 1;5 T8 D J4 c# G: {* A
- return 0;
( {' @5 o- ?* n( @0 H - }
复制代码
2 `9 a% S* N* |NRF24L01模块在同一时间只能设置为只接收或者只发送模式,属于半双工器件,要实现全双工收发需要两个模块:
4 O( j+ Q7 C2 |8 h; Y; W9 V1 m- void NRF24L01_RX_Mode(void)! y4 R* [2 s' p! c
- {
) J0 d( J9 S5 h8 \' J% i" S - NRF24L01_CE_LOW;
. o2 P2 z3 [( b S0 { - NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(uint8_t*)RX_ADDRESS,RX_ADR_WIDTH);5 n" B. j+ `/ t6 _' I3 o: s
- " Q% J; D9 [' }- n4 N V
- NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01); 9 |6 h& E% C' v" X7 V
- NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01);& ^ u/ B8 U( x' ~& O, \+ E5 y; m
- NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40);
3 M. @/ C. i4 J9 L3 E, h- r/ k8 X - NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);
, x( w" _4 r7 S" ?* q - NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f); w3 x; V0 S, J" l2 I
- NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG, 0x0f);
6 g5 }' }5 q7 Q% D - NRF24L01_CE_HIGH;
( K8 h5 j, L k# v: M0 M' H - }7 K/ Z0 K; E9 Y* m- H% ]
9 b( i- { _- T6 v7 _- void NRF24L01_TX_Mode(void)
2 ?6 G0 f7 U! n2 } - {
( f! G3 N# P- j9 J8 Z' t - NRF24L01_CE_LOW;& ~- z( o# [0 z$ g5 K
- NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(uint8_t*)TX_ADDRESS,TX_ADR_WIDTH);8 L. X* _9 k( A+ D' Y6 A$ U
- NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(uint8_t*)RX_ADDRESS,RX_ADR_WIDTH);
9 c& L0 l- e* G# G' H9 y - 1 a0 ]* i% g- B4 q; k. ^
- NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01);
' l$ J/ O9 V, V1 ~9 ]4 A - NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01);
- x, K! B$ Z" c5 L - NRF24L01_Write_Reg(NRF_WRITE_REG+SETUP_RETR,0x1a);/ l1 C0 A$ Y, U, {* u
- NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40);5 ], ` T/ f4 {
- NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);
8 w z$ H9 M" D) S0 i9 F - NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0e);( u1 O; ^+ ~) i5 \) o/ X" h5 v
- NRF24L01_CE_HIGH;, P: f- C/ q7 ^/ j. J4 J2 a0 y
- }: Q, ]& F8 a7 u
- ) j& W; `' B5 _8 x
- uint8_t NRF24L01_RxPacket(uint8_t *rxbuf)
4 }! N- X* d; \/ N* I1 @5 T - {
9 e( ^% O0 I5 M8 @ q - uint8_t sta;
) I3 M: O9 m( ]9 B7 l: Y; i - sta = NRF24L01_Read_Reg(STATUS);* j d8 t* V. O" p
- o0 T% a' t' `0 o# m: e, f- NRF24L01_Write_Reg(NRF_WRITE_REG + STATUS , sta);
. w8 @+ K g _+ I% X - - q: W) e0 c; s+ E3 b
- if(sta & RX_OK)# t5 J. I0 _) i8 t8 j5 M
- {
, X' a* P9 g5 h - printf("sta = 0x%x RX_OK.\n" , sta);
) L5 H! r7 ~5 [, T1 q2 c - NRF24L01_Read_Buf(RD_RX_PLOAD , rxbuf , RX_PLOAD_WIDTH);6 A/ \# _; ^" V* H7 e, o
- NRF24L01_Write_Reg(FLUSH_RX , 0xff);
+ u. A" d9 H ^7 B" u% p* A - return 0;1 {' k( r! l: V* o1 h; f( M
- }
: B" t# ^/ e7 i' G1 Y+ n - return 1;
! o9 X; C' R! ` - } 4 G) ^( l8 w4 h$ J
- / ?: W$ d6 q& @0 v1 D1 ]. f0 K
- uint8_t NRF24L01_TxPacket(uint8_t *txbuf)
5 H; |% v( {: f, m: y X - {8 ^! ^* |/ M6 P$ A* |% B
- uint8_t sta;
3 R# i) ^+ C( S* e9 w8 B - NRF24L01_CE_LOW;
/ N$ p A9 \- z - NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);' |* N# B; \0 B0 i
- NRF24L01_CE_HIGH;
6 x4 X& @/ k9 N) g, Z$ N! h - while(NRF24L01_IRQ_READ() != 0);
1 U; ^4 R- x; E& ?+ p5 j7 c6 c" i - sta = NRF24L01_Read_Reg(STATUS);1 c% R3 ]& i- m. U& X
- NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta);
- C- q- H5 w) Q" B - if(sta&MAX_TX)" Y+ u) _& F* x* ?# P* ]+ ~
- {- f% ?1 }, Y) {, l4 _' Q& z
- NRF24L01_Write_Reg(FLUSH_TX,0xff);
0 a& }! d/ Y, a - return MAX_TX;& u/ b$ \9 H( ^5 q
- }
, P9 V$ \3 w* e1 y9 X3 Y( b9 I - if(sta&TX_OK)8 C) y% z2 f$ |& _' _3 v
- {, G# E/ D1 O f1 ]( F6 j
- return TX_OK;) P1 U: b; t! {8 M. H
- }
$ X4 z5 M- H6 F' O2 Q/ N - return 0xff;8 k# ^! m6 r2 v
- }
复制代码 5 C- C) N8 N2 S" a3 P5 Z2 T' B( _
我这里在主界面创建一个flexButton用于控制NRF24L01模块发送一行数据:
% S4 N; ~% B# d" s+ H
4 A6 h) Z; S, c _9 t8 E* _& f
& F, W2 r; M' ^- W8 s
看看发送效果,按下fb之后,H7R7开发板会通过NRF24L01模块发送一行字符串,另一个设置了相同接收地址的NRF24L01开发板就会收到这个字符串:+ [( X' W3 m! T
5 e. A7 H0 o! h6 v然后是接收,接收就更简单了,只需要设置模块为接收模式后,在Tick事件回调函数调用即可:
7 E- z) k) u- v
2 Q- r) y) o! x$ `/ z- }
|