正点原子H7R7开发板上面的NRF24L01接口是可以接一个NRF24L01模块的,原子论坛也提供了例程可供参考,但是是适配给原子自家的NRF24L01模块的,使用第三方模块厂出品的NRF24L01模块程序需要做一些细微调整,无法直接通用。/ G* r/ _/ k" c9 W( \) M
3 @3 f N; Z6 g2 e* ]/ h7 y# ^: d3 p首先是初始化SPI接口,这个非常简单:- SPI_HandleTypeDef g_spi_handle;2 V/ Y+ n8 K, R& O( O
- - t, L X( a7 }! }5 F) D7 j7 e, r
- uint8_t SPI2_PD3_PC2_PC3_Read_Write_Byte(uint8_t txdata)
* I: ^: E. ^3 t5 F - {9 Z1 U2 e# b" a R, t% u0 e
- uint8_t rxdata;4 R. \7 Q/ t4 L3 R. q' X
- HAL_SPI_TransmitReceive(&g_spi_handle , &txdata , &rxdata , 1 , 1000);/ c* x! ]8 N' N {; I
- return rxdata;! S n/ m, Y# |) Y/ J4 t% q" Q! O
- }
1 h, x. S, t8 y1 G - ; b$ p0 r+ u0 B/ M8 o
- void SPI2_PD3_PC2_PC3_Init(void)
. m, N4 ^" H9 O' o b( u - {
/ w6 O' f0 O- j2 J. ~) f4 O - GPIO_InitTypeDef gpio_init_struct = {0};
/ s# ~( Q( a. ]$ @. R! n* D - RCC_PeriphCLKInitTypeDef rcc_periph_clk_init = {0};& e H" T9 H& ]+ l. H5 p: l9 @ a
- ; b3 Z! }/ v' Y) U
- __HAL_RCC_SPI2_CLK_ENABLE();
5 ?+ a+ y! ]3 @) L o/ j2 @ - __HAL_RCC_GPIOC_CLK_ENABLE();2 |9 i% ?' Z% V' y' m: _% L
- __HAL_RCC_GPIOD_CLK_ENABLE();
" p! w& Z, [; _) ]" Y y - 8 \! i6 {& J2 i
- rcc_periph_clk_init.PeriphClockSelection = RCC_PERIPHCLK_SPI23;
! K, L$ X8 m9 ~( c - rcc_periph_clk_init.Spi23ClockSelection = RCC_SPI23CLKSOURCE_PLL1Q;
* P1 N% F& L% @- M% @& R7 Z - HAL_RCCEx_PeriphCLKConfig(&rcc_periph_clk_init);
' \ l7 ]$ c o& u
. u. o0 S) a# L. t) K- gpio_init_struct.Mode = GPIO_MODE_AF_PP;
2 w, N3 @! L# ~) R! G4 { - gpio_init_struct.Pull = GPIO_PULLUP;
2 v' j: _: z: x+ {6 J& h - gpio_init_struct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;1 Q9 @$ @; n) k1 H7 J) j) f; S
- z' f+ _% N0 R- gpio_init_struct.Pin = GPIO_PIN_3;
. {+ a( C1 ~+ @" m5 y5 Q$ R - gpio_init_struct.Alternate = GPIO_AF5_SPI2;5 b( ^: d/ C7 b, G8 _
- HAL_GPIO_Init(GPIOD , &gpio_init_struct);
& t8 M' h C& s! |3 d
$ E3 q3 y$ w+ ?% L8 v6 G- gpio_init_struct.Pin = GPIO_PIN_2;
! ]$ j' u; w4 \9 c& ~9 s - gpio_init_struct.Alternate = GPIO_AF5_SPI2;* `: }+ x& j8 C) g
- HAL_GPIO_Init(GPIOC , &gpio_init_struct);& ?4 i; Q$ O2 i9 j% A6 Q
-
, c2 }/ f) {# b2 ?" O, e2 B! w - gpio_init_struct.Pin = GPIO_PIN_3;; n3 b) m7 H6 j) B- C. ]
- gpio_init_struct.Alternate = GPIO_AF5_SPI2;
9 i( ~: Z Q' I* I - HAL_GPIO_Init(GPIOC , &gpio_init_struct);$ _ X) W9 c4 M. |
- 2 t- b2 ^, b: c
- g_spi_handle.Instance = SPI2;" F( B! M* L# y- W8 f% R- I9 G
- g_spi_handle.Init.Mode = SPI_MODE_MASTER;' G8 Y5 K6 T% Q4 P
- g_spi_handle.Init.Direction = SPI_DIRECTION_2LINES;
; n* h; i4 T$ B J - g_spi_handle.Init.DataSize = SPI_DATASIZE_8BIT;- X: n3 ]+ l- _+ U
- g_spi_handle.Init.CLKPolarity = SPI_POLARITY_LOW;
! R5 |' ~: \2 S. d) }' m/ J - g_spi_handle.Init.CLKPhase = SPI_PHASE_1EDGE;
/ Y; J2 C H. h$ ?; H - g_spi_handle.Init.NSS = SPI_NSS_SOFT;
4 K. w& \( ~8 D* x - g_spi_handle.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
- x" O) X' D% e1 H - g_spi_handle.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE;
: g# @8 ~3 @+ Y - g_spi_handle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;8 \4 Z+ c4 _1 K, S# M( S2 E- T
- g_spi_handle.Init.FirstBit = SPI_FIRSTBIT_MSB;
0 M1 E# E" @+ g( E" e$ L1 D - g_spi_handle.Init.TIMode = SPI_TIMODE_DISABLE;
- E$ A$ m* v& b - g_spi_handle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;
0 I7 w5 L1 j% D" c- w# ~% U7 o - g_spi_handle.Init.CRCPolynomial = 7;
! G: l& K. |* Q: z2 Z* |: m9 y T - HAL_SPI_Init(&g_spi_handle);: K) j$ S- u2 `) B- r4 T( H% Y1 E% ~9 b
$ H% h7 S, \+ S$ Z- __HAL_SPI_ENABLE(&g_spi_handle);# Q3 x6 X C) I
- SPI2_PD3_PC2_PC3_Read_Write_Byte(0Xff);0 t. I: F1 z4 |% ] g
- }
复制代码 这里需要注意的是,H7R7的SPI接口时钟要设置为128分频或者256分频,因为SPI123三个接口的时钟直接挂在PLLQ上,分频太少的话,波形变形的程度使得NRF24L01无法识别,进而无法进行任何通信,然后就是时钟信号空闲时为低,第一个沿变开始传输数据,这个也是NRF24L01芯片的特性,不遵循这个设置无法进行通信。
6 q! e2 h% k* ^' A+ ^& _) K
6 |$ x/ u; J# RNRF24L01还需要用CS CE IRQ三个脚,其中CS脚是片选,需要在传输数据时进行控制,CE脚常高表示使能,IRQ脚是发送时会用到:
2 _' R3 W# b4 ~( A6 x; W, K1 r- #define NRF24L01_CS_GPIO_PORT GPIOM
; f7 H' \, Y, R+ A - #define NRF24L01_CS_GPIO_PIN GPIO_PIN_13
: w E% Q# Z$ O: ]0 G - #define NRF24L01_CS_GPIO_CLK_ENABLE __HAL_RCC_GPIOM_CLK_ENABLE();$ ~, n# v3 B: R" X0 s! k' d
- #define NRF24L01_CS_HIGH HAL_GPIO_WritePin(NRF24L01_CS_GPIO_PORT , NRF24L01_CS_GPIO_PIN , GPIO_PIN_SET);* L+ U7 @3 C7 z% U
- #define NRF24L01_CS_LOW HAL_GPIO_WritePin(NRF24L01_CS_GPIO_PORT , NRF24L01_CS_GPIO_PIN , GPIO_PIN_RESET);
6 s1 w+ A* k: x! L/ s) o3 y
& \: ], i8 d: g, n. n- z- #define NRF24L01_CE_GPIO_PORT GPIOM
! c' x5 q; c6 u - #define NRF24L01_CE_GPIO_PIN GPIO_PIN_14, u4 i, N1 Y! y2 Q9 I+ q$ z
- #define NRF24L01_CE_GPIO_CLK_ENABLE __HAL_RCC_GPIOM_CLK_ENABLE();
$ G- x0 `; k. }: X0 Q - #define NRF24L01_CE_HIGH HAL_GPIO_WritePin(NRF24L01_CE_GPIO_PORT , NRF24L01_CE_GPIO_PIN , GPIO_PIN_SET);
" Z" k7 Y: ?+ A p* G - #define NRF24L01_CE_LOW HAL_GPIO_WritePin(NRF24L01_CE_GPIO_PORT , NRF24L01_CE_GPIO_PIN , GPIO_PIN_RESET);4 C4 ?# L& B' @* f' Y
8 q4 n t) g, Z1 q/ O+ g+ J8 p# F7 c- #define NRF24L01_IRQ_GPIO_PORT GPIOF& D e6 s" @1 A+ b
- #define NRF24L01_IRQ_GPIO_PIN GPIO_PIN_21 }# S1 f! x" G/ Z0 K% ~
- #define NRF24L01_IRQ_GPIO_CLK_ENABLE __HAL_RCC_GPIOF_CLK_ENABLE();2 {! l& z# W/ d
- #define NRF24L01_IRQ_READ() HAL_GPIO_ReadPin(NRF24L01_IRQ_GPIO_PORT , NRF24L01_IRQ_GPIO_PIN)
! O- @, Y) G2 C. L; t3 e - ( L* j: U5 P# [ R- K' @- o
- void NRF24L01_GPIO_Init(void)
; ?7 A. m, J6 [. q( ?: A - {
* Z w- p. Q/ Y& v - GPIO_InitTypeDef gpio_init_struct;
) a* |; ]! N2 @ t - NRF24L01_CS_GPIO_CLK_ENABLE;3 \# p9 e5 d3 t( O; S- ~* B
- NRF24L01_CE_GPIO_CLK_ENABLE;; X( C" W* W a: F+ w' v
- NRF24L01_IRQ_GPIO_CLK_ENABLE;6 X; \( j8 D: P4 e7 _
-
6 F" X1 o* m$ i# U: y - gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;
5 O7 R. g" t& z. A7 ]! X. O - gpio_init_struct.Pull = GPIO_PULLUP;
2 r! O* `& G/ X9 Z6 @1 f5 | - gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;
2 _* O5 W: D: I5 ?$ B9 g$ I - 1 w4 T# V/ _0 @
- gpio_init_struct.Pin = NRF24L01_CS_GPIO_PIN;
- x8 R/ @/ X. x8 g, m# k2 h' V! l( C% k - HAL_GPIO_Init(NRF24L01_CS_GPIO_PORT , &gpio_init_struct);" U8 h4 o7 ^$ R4 f& d5 y1 G
- 7 Y8 \, h6 L* ]& Z) W' `0 n
- gpio_init_struct.Pin = NRF24L01_CE_GPIO_PIN;
, [( N8 ^1 U" M3 Y - HAL_GPIO_Init(NRF24L01_CE_GPIO_PORT , &gpio_init_struct);3 o) @( g h" z1 L; s
-
: e4 ~+ i7 ]7 W1 p( N - gpio_init_struct.Mode = GPIO_MODE_INPUT;7 k5 [" S6 {3 B. l
- gpio_init_struct.Pin = NRF24L01_IRQ_GPIO_PIN;
1 s r8 g9 w1 h. N1 ] - HAL_GPIO_Init(NRF24L01_IRQ_GPIO_PORT , &gpio_init_struct);' O. z* [! }+ E$ g
- - K! D4 ^% {7 o6 v
- NRF24L01_CE_LOW;( Z2 I/ x; @& j4 }/ i" D' I1 z
- NRF24L01_CS_HIGH;8 s$ B7 ~4 c g; o4 \
- }
* k3 b2 Z. N4 J9 z
复制代码 : b+ m0 @! _; `$ K
7 i9 j y' U8 J! E$ @3 H6 ]
NRF24L01有五个可读写的寄存器是可以用来检测器件是否正常工作的:6 ], O$ f& Y j3 @" S( t. \
- uint8_t NRF24L01_Check(void) b( ~1 g& ]+ ^- n. s
- {5 b! l- b( \; a' f
- uint8_t buf[5] = {0xa5 , 0xa5 , 0xa5 , 0xa5 , 0xa5};) k$ @$ `$ c6 {, _% F* Q
- uint8_t i;
' L* p; Q7 H9 {& t5 D! ] - NRF24L01_Write_Buf(NRF_WRITE_REG + TX_ADDR , buf , 5);2 m$ K/ R9 c! l2 F( L
- NRF24L01_Read_Buf(TX_ADDR , buf , 5);
" f+ V' b) a' i - for(i = 0 ; i < 5 ; i++)
2 m- N4 x& D+ m% }6 S: L- R - if(buf[i] != 0XA5)
: I8 |/ e5 T; r+ r. j! S; G - break;
( r, J9 d- ]9 o0 }4 }6 ` - if(i!=5)( J/ D. Z. r! X# Z- {5 `
- return 1;# p; b+ o8 X% G) u0 H3 D! O% \
- return 0;! }- L0 `- q: P0 H9 j
- }
复制代码
7 X" z7 {( _; {+ T/ u2 W( o# \8 L$ h
" b: E" ?/ L3 h. W2 _/ w/ Q# ]NRF24L01模块同一时间只能设置为单独接收或者单独发送模式,属于半双工器件,要实现全双工收发需要两个模块:
! [, j3 n# X' l! H- void NRF24L01_RX_Mode(void)# C) W* Z7 W9 }* \+ m, J( y
- {
$ u: i1 O) f6 i% Z' a+ [# v0 k' i - NRF24L01_CE_LOW;
5 ^+ n- E- k) U: c" U9 Y - NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(uint8_t*)RX_ADDRESS,RX_ADR_WIDTH);
& n# K5 ^ l- M% U) r - / L7 L" o' Q' n7 S- h
- NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01); 3 V5 V. c7 T0 @8 z E. |* k
- NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01);" P* @5 ~4 o; v' q- R' t2 S
- NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40);- F3 r) j4 z) A, q" _. A
- NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);
% V' j/ q1 U) @& Q, c - NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);# D2 x( y9 _3 t5 m
- NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG, 0x0f);7 @7 m0 E r2 T4 X3 }; P
- NRF24L01_CE_HIGH;# I. I, n; b' D5 N& _: K9 g4 K
- }
- k) e$ l- @. [! p
9 ]. K# A; {7 g1 q- U2 c9 T( X2 ]' Y- void NRF24L01_TX_Mode(void)
# }8 j+ d& @& |( C6 t3 u - { " Z7 [# E7 e* @4 l! r3 R2 w3 j9 j) s H
- NRF24L01_CE_LOW;
: h8 m% q8 i- \. C - NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(uint8_t*)TX_ADDRESS,TX_ADR_WIDTH);, B+ t& T# L: i ^) a
- NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(uint8_t*)RX_ADDRESS,RX_ADR_WIDTH);
$ n; _# v7 h! u. |8 L
- X& ?1 L- H* f$ m& w& K- _. j- NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01);
9 D2 I$ e) R/ L3 ~4 Z9 S - NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01);" h/ ]) D" \- X; h- Q
- NRF24L01_Write_Reg(NRF_WRITE_REG+SETUP_RETR,0x1a);
O. ^' U4 I0 g: n - NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40);
$ I$ p2 u. L( L$ s7 l# \ - NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);" ?5 B( s5 w- y# k, e
- NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0e);* C9 d" W2 E# {- }( C j
- NRF24L01_CE_HIGH;6 w0 |5 h5 E( ?1 ?) d" n
- }
* E; }$ m6 ]2 [0 A5 D! w - 2 [ B$ F' \9 I- q
- uint8_t NRF24L01_RxPacket(uint8_t *rxbuf)3 H9 p7 c! l# i$ g: n
- {
) k: j) H+ ?7 p: k* U - uint8_t sta;
0 E, b% C2 t8 O - sta = NRF24L01_Read_Reg(STATUS);5 g5 s a8 v4 f. f
( U& W1 [3 ?1 X( R) @5 d: H- NRF24L01_Write_Reg(NRF_WRITE_REG + STATUS , sta);/ I! t' O4 X# t5 P# a
-
# J* h$ B! G- X+ Z0 D( V - if(sta & RX_OK). n5 P7 t' d+ I: r7 d9 U5 e% P
- {
4 X1 p+ E( a. }. d1 L+ P3 M - printf("sta = 0x%x RX_OK.\n" , sta);
* `/ G2 [2 y0 y$ D0 s0 W' z* K - NRF24L01_Read_Buf(RD_RX_PLOAD , rxbuf , RX_PLOAD_WIDTH);4 Q5 O/ ~4 G1 ?
- NRF24L01_Write_Reg(FLUSH_RX , 0xff);! g/ R- R& F2 _9 L1 j* P
- return 0;
9 O8 j) m" @: O/ e - } : c& e1 M" |. a5 @6 J, N
- return 1;
5 h H& e+ k/ M, f - }
: ~- L$ v. ^9 H' t0 F/ P; x+ P" O; h
4 l4 c% h# v/ u" N- uint8_t NRF24L01_TxPacket(uint8_t *txbuf)
$ f9 a; B5 f8 ]+ X% `' s4 J - {* }: k. s! e6 L1 e. }2 o
- uint8_t sta;. Y. y2 e6 p/ [" z
- NRF24L01_CE_LOW;
" B, k, E, O6 \ - NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);
) C' \ a. p& O% a* i) N+ Q - NRF24L01_CE_HIGH;$ J3 n$ z/ t4 R& s6 |' v( g
- while(NRF24L01_IRQ_READ() != 0);7 z+ K0 w T6 X6 O
- sta = NRF24L01_Read_Reg(STATUS);
) G( b S# E& I% j* i' G/ L1 I - NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta);3 P9 O: J/ u! @- t0 Y7 j& ^
- if(sta&MAX_TX)
1 `# O( l! o% T$ }8 a - {: n" u ]" P5 _* }' K8 [, `
- NRF24L01_Write_Reg(FLUSH_TX,0xff);
* F8 L/ f4 c# p' k. P4 g# W - return MAX_TX;
: j/ m' n. T( c9 j, B - }
) R) n/ n* e6 V - if(sta&TX_OK). s! G( e3 m) V- O4 }
- {
& e$ [5 K' C4 ^9 p) z0 v - return TX_OK;1 E( N: d3 W: y' G4 {: n) v
- }
. i& K2 ~" g) u+ }5 C" o - return 0xff;5 \6 H9 i, ]2 ?) L) f; a0 F. p
- }
复制代码
- W; F, E8 t) V- ~6 Y$ r/ J' v4 T9 ?: {; I8 d6 X4 y* b
我这里在主界面创建一个flexButton用于控制NRF24L01模块发送一行数据:
- @0 g1 H7 _9 Q5 P, T6 _3 C
N1 |0 n- l# z" O" }
3 X: o- W9 q( K1 H8 T看看发送效果,按下这个fb之后启动一行发送,在另一个设置了相同接收地址的接收机上接入电脑串口打印接收到的信息:' O) X! h8 L/ I
) t2 E, T/ Q9 c( ~; n# Z2 E
; E( L5 T% ]$ f7 m& c. r然后是接收,接收就更简单了,只需要设置模块为接收模式后,在Tick事件回调函数调用即可:
. b6 U; B* v( C3 G* G7 A2 C/ O
3 e9 w" d1 ]4 f+ \2 e1 F3 J# u |