正点原子H7R7开发板上面的NRF24L01接口是可以接一个NRF24L01模块的,原子论坛也提供了例程可供参考,但是是适配给原子自家的NRF24L01模块的,使用第三方模块厂出品的NRF24L01模块程序需要做一些细微调整,无法直接通用。2 f+ D! J9 ]4 N: s; D+ [; I" b
1 ?1 O" q# u, \ B i* S* @: _2 X
首先是初始化SPI接口,这个非常简单:9 j7 b$ d# a" a; V3 G
- SPI_HandleTypeDef g_spi_handle;; |' l9 P( }, t7 ^
- 3 t& c9 e7 N( U, k- U
- uint8_t SPI2_PD3_PC2_PC3_Read_Write_Byte(uint8_t txdata)) L8 [# ]/ d$ z# ^7 ?
- {
- A9 c; J& Y) j5 ]. b0 N: X" N - uint8_t rxdata;' a4 r1 b, ~2 u) o( x
- HAL_SPI_TransmitReceive(&g_spi_handle , &txdata , &rxdata , 1 , 1000);7 a% r- l3 X; @% k6 n+ s2 I) |4 E4 }
- return rxdata;
, e: m5 n2 t5 Y3 D - }
$ |0 v* k! v4 U - * h4 T5 ?5 I* v | m0 c \9 @
- void SPI2_PD3_PC2_PC3_Init(void)
, A$ [7 i$ N7 g$ o: \* v - {
4 {' p* t. h. J, e5 ~ - GPIO_InitTypeDef gpio_init_struct = {0};
/ J) L) ?4 b( {6 W, m d4 L - RCC_PeriphCLKInitTypeDef rcc_periph_clk_init = {0};! ]! `' r+ s* _0 M7 K, z$ M: }5 H
- ; k: e; v. x2 V7 D: T3 V9 q
- __HAL_RCC_SPI2_CLK_ENABLE();
/ O7 _* K. V1 o: u0 [6 E - __HAL_RCC_GPIOC_CLK_ENABLE();3 w! S/ [) R8 Q8 B
- __HAL_RCC_GPIOD_CLK_ENABLE();5 C, L; S0 Q8 \* o1 `6 U3 L
-
$ L; _5 O d! N) R, | p - rcc_periph_clk_init.PeriphClockSelection = RCC_PERIPHCLK_SPI23;+ @) u, G( M: X& H8 P
- rcc_periph_clk_init.Spi23ClockSelection = RCC_SPI23CLKSOURCE_PLL1Q;2 m# W7 s H; J+ Q( H9 K
- HAL_RCCEx_PeriphCLKConfig(&rcc_periph_clk_init);
. y! D, t; D4 @# @( V; X. n
/ m* Z q- b' L6 U( g' W- gpio_init_struct.Mode = GPIO_MODE_AF_PP;
% g; L7 z( u' E* Q: i - gpio_init_struct.Pull = GPIO_PULLUP;
7 C2 s( x' j- ^. L; W - gpio_init_struct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
. ~8 l- y) I% G6 {
& b+ e1 S5 Y3 H" Q- l$ I- gpio_init_struct.Pin = GPIO_PIN_3;; I: v7 O. A* q- G0 R' ]: k: `
- gpio_init_struct.Alternate = GPIO_AF5_SPI2;
i x! _. l% z( H" v - HAL_GPIO_Init(GPIOD , &gpio_init_struct);+ {$ Y' Z% ~1 {9 O- T, @/ K
- O, h6 Y, w; D$ x: \ q. H$ i
- gpio_init_struct.Pin = GPIO_PIN_2;
0 t* Q8 n. L( j4 z: N7 I5 s - gpio_init_struct.Alternate = GPIO_AF5_SPI2;
" b1 j9 \' n) X, v' k# l - HAL_GPIO_Init(GPIOC , &gpio_init_struct);( z' y+ Y! \! F7 T
- ; D+ X7 G; n- X# m o- A
- gpio_init_struct.Pin = GPIO_PIN_3;$ @- X- N3 s1 N0 \
- gpio_init_struct.Alternate = GPIO_AF5_SPI2;2 {1 r! E0 ~5 b
- HAL_GPIO_Init(GPIOC , &gpio_init_struct);" w& {2 u% l/ e. z
- 6 A5 a" A g3 ?- q; d# U1 }
- g_spi_handle.Instance = SPI2;
8 i7 S8 c, ~+ F, |$ L: J - g_spi_handle.Init.Mode = SPI_MODE_MASTER;
' l5 @5 Q# y2 {) t% t - g_spi_handle.Init.Direction = SPI_DIRECTION_2LINES;
0 n8 T, K& v1 h) J- R6 @5 v - g_spi_handle.Init.DataSize = SPI_DATASIZE_8BIT;
( l3 z2 X: w4 d3 b' g- o - g_spi_handle.Init.CLKPolarity = SPI_POLARITY_LOW;
- S# T+ W4 {1 V# @$ W - g_spi_handle.Init.CLKPhase = SPI_PHASE_1EDGE;: `# x c& I% f: \) A& I9 }) Y; l
- g_spi_handle.Init.NSS = SPI_NSS_SOFT;
! u3 m: t9 ]' _* V G - g_spi_handle.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;( m# `. d! S/ g$ e9 W+ }3 @
- g_spi_handle.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE;
7 \8 z* Q" @5 n& f - g_spi_handle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;% [& M8 v) V1 w, p$ h* g6 W
- g_spi_handle.Init.FirstBit = SPI_FIRSTBIT_MSB;
6 ]8 [# m8 r+ T- C. H$ n& y - g_spi_handle.Init.TIMode = SPI_TIMODE_DISABLE;
6 `/ s/ |& _* M! j7 F - g_spi_handle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;7 A. {4 I4 C$ j# l }9 J* F+ b, C
- g_spi_handle.Init.CRCPolynomial = 7;, M/ @% q2 ?6 g; c3 |% P% L* H
- HAL_SPI_Init(&g_spi_handle);
8 v- B% d( l6 h$ B7 `/ B/ d2 g% r - 4 U. y. e' L$ Y- Z
- __HAL_SPI_ENABLE(&g_spi_handle);- h! `5 P. w" B1 [# G
- SPI2_PD3_PC2_PC3_Read_Write_Byte(0Xff);8 u/ ?% r) M h' g, d/ b
- }
复制代码 这里需要注意的是,H7R7的SPI接口时钟要设置为128分频或者256分频,因为SPI123三个接口的时钟直接挂在PLLQ上,分频太少的话,波形变形的程度使得NRF24L01无法识别,进而无法进行任何通信,然后就是时钟信号空闲时为低,第一个沿变开始传输数据,这个也是NRF24L01芯片的特性,不遵循这个设置无法进行通信。6 C; N& ~4 \! z$ V e
9 h8 K, D$ ~% r- d% b" n3 pNRF24L01还需要用CS CE IRQ三个脚,其中CS脚是片选,需要在传输数据时进行控制,CE脚常高表示使能,IRQ脚是发送时会用到:( `- S: D0 w- b r
- #define NRF24L01_CS_GPIO_PORT GPIOM% v; p- W) G9 U1 M! X3 C
- #define NRF24L01_CS_GPIO_PIN GPIO_PIN_13
7 o5 e2 K8 l- l2 j& H - #define NRF24L01_CS_GPIO_CLK_ENABLE __HAL_RCC_GPIOM_CLK_ENABLE();/ c( h! g/ N% s1 n
- #define NRF24L01_CS_HIGH HAL_GPIO_WritePin(NRF24L01_CS_GPIO_PORT , NRF24L01_CS_GPIO_PIN , GPIO_PIN_SET);
% _( i6 r o% _$ | - #define NRF24L01_CS_LOW HAL_GPIO_WritePin(NRF24L01_CS_GPIO_PORT , NRF24L01_CS_GPIO_PIN , GPIO_PIN_RESET);) @1 y% f& _/ j
$ o: p5 a( o: w- #define NRF24L01_CE_GPIO_PORT GPIOM
5 P. X4 C2 O$ [1 l; Z2 N% k - #define NRF24L01_CE_GPIO_PIN GPIO_PIN_14
6 R# D3 B, B" v% t$ _ - #define NRF24L01_CE_GPIO_CLK_ENABLE __HAL_RCC_GPIOM_CLK_ENABLE();
: H+ a- V/ M, j, K& @2 z - #define NRF24L01_CE_HIGH HAL_GPIO_WritePin(NRF24L01_CE_GPIO_PORT , NRF24L01_CE_GPIO_PIN , GPIO_PIN_SET);5 m4 N/ ?7 V* B* |, F
- #define NRF24L01_CE_LOW HAL_GPIO_WritePin(NRF24L01_CE_GPIO_PORT , NRF24L01_CE_GPIO_PIN , GPIO_PIN_RESET);
* n9 u- R, ?2 w' R9 \ - ( K4 H! E$ N7 Q4 z0 W
- #define NRF24L01_IRQ_GPIO_PORT GPIOF g) k b, z" \9 g7 G3 e
- #define NRF24L01_IRQ_GPIO_PIN GPIO_PIN_2
8 T U: v- s; X8 Z' a - #define NRF24L01_IRQ_GPIO_CLK_ENABLE __HAL_RCC_GPIOF_CLK_ENABLE();3 G! r" p7 M# o; z" @$ p; H9 t
- #define NRF24L01_IRQ_READ() HAL_GPIO_ReadPin(NRF24L01_IRQ_GPIO_PORT , NRF24L01_IRQ_GPIO_PIN)
- z7 k/ M c1 h. T; d/ v
* }( b$ s* h, q _- void NRF24L01_GPIO_Init(void)( V m( R- [* w6 s" o
- {
" C. J% h' w: ^) y+ |- y" r3 j - GPIO_InitTypeDef gpio_init_struct;3 {; I. c0 i5 T0 u2 M+ r5 S4 F
- NRF24L01_CS_GPIO_CLK_ENABLE;
* ]; G3 w" W9 G - NRF24L01_CE_GPIO_CLK_ENABLE;# W' \" }! N, U/ I5 l* v
- NRF24L01_IRQ_GPIO_CLK_ENABLE;
9 u% [8 S/ F1 H9 ^ _ -
0 K4 F: c1 X) g1 K - gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;
4 K N) q, h- K1 C& k. N+ K - gpio_init_struct.Pull = GPIO_PULLUP;4 z& q7 q% e8 D9 ]' A8 M
- gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;) M% ]0 U* @/ U
-
, x8 q! @4 r8 U' z - gpio_init_struct.Pin = NRF24L01_CS_GPIO_PIN;
( E, b+ _) P( M0 O; t+ w! z$ H - HAL_GPIO_Init(NRF24L01_CS_GPIO_PORT , &gpio_init_struct);
- Y9 m/ j8 z$ J0 R7 k -
6 @' K4 E- `: }# s; s7 C - gpio_init_struct.Pin = NRF24L01_CE_GPIO_PIN;
0 j6 V/ X* P/ B2 |: m0 ~ n - HAL_GPIO_Init(NRF24L01_CE_GPIO_PORT , &gpio_init_struct);
. C% M" g- O: {0 ?( D8 ]8 \. x -
" R" p& a. n* x. i - gpio_init_struct.Mode = GPIO_MODE_INPUT;
0 z4 l0 I, C8 o5 F) Y( k9 a - gpio_init_struct.Pin = NRF24L01_IRQ_GPIO_PIN;
8 H: ]& v; K& h0 |/ Q6 F - HAL_GPIO_Init(NRF24L01_IRQ_GPIO_PORT , &gpio_init_struct);$ E9 V1 E% N4 h5 \5 G) k
- % `6 w7 T ~ `* W: K
- NRF24L01_CE_LOW;0 @/ g$ _8 L- q4 ^$ _8 a
- NRF24L01_CS_HIGH;" n# V) F- j4 y; \2 ?
- }
复制代码
$ c# |" Q$ T* u& H/ e& S
$ n: ]& P5 d* J9 ~% K
4 G" q+ E' g3 ^' [# VNRF24L01有五个寄存器是可以用来检测器件是否正常工作的:( n, V# S. S7 a3 y' F) u; |
- uint8_t NRF24L01_Check(void)
# ?; w' j. W/ s+ u7 F- H/ g - {' T# S. J$ |* L# y6 `5 r
- uint8_t buf[5] = {0xa5 , 0xa5 , 0xa5 , 0xa5 , 0xa5};
& M, w- z: e; Q, v - uint8_t i; x/ _" m) v) w
- NRF24L01_Write_Buf(NRF_WRITE_REG + TX_ADDR , buf , 5);
/ P3 F l ~: c% X7 t4 s - NRF24L01_Read_Buf(TX_ADDR , buf , 5);% | E- n1 ?; j; V; [
- for(i = 0 ; i < 5 ; i++)3 W" P$ v2 W* A5 x% ~" L: ?. _0 C
- if(buf[i] != 0XA5)! i( \! a8 S) q. I1 Q
- break;
; c9 q" ^ P6 c3 U! s - if(i!=5)
/ }4 m! N' p5 i. X9 P; O9 P' N - return 1;
+ J) p& l8 C. ]% | - return 0;
. y" ?" ^2 W0 b @0 w - }
复制代码 9 H0 l) W, d5 a) D3 j1 M. P4 @
NRF24L01模块在同一时间只能设置为只接收或者只发送模式,属于半双工器件,要实现全双工收发需要两个模块:
' Y" C% t/ d& S1 K. [9 G2 e0 {- void NRF24L01_RX_Mode(void)' h( R0 ]! R8 }9 U- W
- {
( [, H$ g" E& M* B, h2 i- i0 B" u - NRF24L01_CE_LOW;8 ?, N% u, g' h2 x& Q3 ^
- NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(uint8_t*)RX_ADDRESS,RX_ADR_WIDTH);
z# r8 N: E% K/ e* s7 q, D- q8 }+ D0 ~' d - ! j1 K: C6 t$ K- c0 k0 v3 c6 F
- NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01);
- M) I+ B. ~- m4 }* ~ - NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01);- J; E& {& Q9 B6 K3 B
- NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40);
$ q4 @1 f0 Z4 K4 e4 \ - NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);
* H6 `3 u/ T' v/ Q' u/ I9 r - NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);
$ O- [7 g; {1 J" o- y9 C# L - NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG, 0x0f);* h1 p2 ~$ Z2 S9 ^% @% y# N8 \1 Y
- NRF24L01_CE_HIGH;
8 S+ N* U, P- Y3 i2 c - }
2 X0 U `- L; I2 S# E M/ B4 T" \# t - : m& _ n: b0 L
- void NRF24L01_TX_Mode(void); r; O7 \/ J3 n* c ?7 G
- {
2 y! r0 Y: `8 O% c. K - NRF24L01_CE_LOW;
# l r# S7 i* }4 c( \! C+ H - NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(uint8_t*)TX_ADDRESS,TX_ADR_WIDTH);+ u+ @7 |5 ?7 ~8 x: }4 T. f& b1 u
- NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(uint8_t*)RX_ADDRESS,RX_ADR_WIDTH);
2 T& I1 m! X$ Z4 A8 D9 M7 `- P - 8 i; p! k- x3 l N" D6 w7 c
- NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01);- `& v7 {7 F8 d8 P3 Z3 \% \( @& C
- NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01);, l1 `8 S$ R# q* |# M% o
- NRF24L01_Write_Reg(NRF_WRITE_REG+SETUP_RETR,0x1a);
T# l' t+ n$ }. R+ y - NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40);
6 V- m6 p* \6 j. @4 i - NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);
3 v/ x+ w2 v) j0 V) ^, b5 L8 J - NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0e);
% W- Z8 L+ ]& r1 ~& G' `/ g - NRF24L01_CE_HIGH;
. }% c5 d4 V6 I2 t9 V/ M - }
* y" d2 B3 T& S% C) `
) [" u2 A) U/ s# B$ R6 |- uint8_t NRF24L01_RxPacket(uint8_t *rxbuf)1 k* A9 d8 g& Z/ j' B H, N+ C
- {) g: X$ C' [% F, r6 b
- uint8_t sta; ; n/ z" |- Q) C3 h; [: I
- sta = NRF24L01_Read_Reg(STATUS);
) o( }# d e4 O( N/ }( C( a7 }
7 f, Y! e9 n! Q2 |- NRF24L01_Write_Reg(NRF_WRITE_REG + STATUS , sta);
$ @. L2 w0 t- \' m" A/ |5 R - $ \' C+ B* o9 V& m& G
- if(sta & RX_OK)
0 [. n U" ]' X7 v1 T3 X - {
' q8 U; c$ p B3 S7 O% P- w3 w - printf("sta = 0x%x RX_OK.\n" , sta);& m+ }# k7 u: d1 z& ~* }/ u5 V
- NRF24L01_Read_Buf(RD_RX_PLOAD , rxbuf , RX_PLOAD_WIDTH);
: N. w7 e- T" p& o# h6 d8 S# m, T - NRF24L01_Write_Reg(FLUSH_RX , 0xff);
`9 H5 G% c1 i( G9 s, W$ Q - return 0;: D6 C/ ^! u& ~; o
- } 1 Q* [8 L6 l. a S5 j$ |2 ^1 O
- return 1;9 K4 ]7 S5 b9 K8 U
- } $ {. ~% i7 N' [. r. n
- ) i, w7 K) u; m z1 y
- uint8_t NRF24L01_TxPacket(uint8_t *txbuf)
# _- G; ^7 d7 c- n - {
' O& X. Q [! q6 c& ^0 e - uint8_t sta;4 y, [6 f: ?3 N7 H. _/ E& a4 j, {
- NRF24L01_CE_LOW;- e( e9 E# L, t4 r* a% c+ [/ C
- NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH); d( D! _2 j4 W' V) Q) _
- NRF24L01_CE_HIGH;
" z% {/ Z( v. _ - while(NRF24L01_IRQ_READ() != 0);2 h2 P& z. p0 B z
- sta = NRF24L01_Read_Reg(STATUS);( H: j% e; ?2 Q' X! |: T
- NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta);! b& x% }2 U" u6 o
- if(sta&MAX_TX)
" }& ~! g+ n; `+ q - {1 u9 _' p) _, B" U* P( N* {- p5 E
- NRF24L01_Write_Reg(FLUSH_TX,0xff);+ S' i+ N0 d% n( o" A1 ]5 M
- return MAX_TX;
3 J1 q$ \$ o( Z - }
7 L( M- Z6 c8 @; ]: a8 p1 k - if(sta&TX_OK)
- f9 } [; }, W: q0 f, ] - {
& n r+ ^% l7 d7 Y2 J1 ] - return TX_OK;
. m! ?* r" ?" \* } - }
6 Z0 u+ f$ ~" w1 `- G - return 0xff;, _3 E+ i" R3 E4 ~( ]- f9 \
- }
复制代码
7 P* Z4 a8 F. g X. _% _* y q我这里在主界面创建一个flexButton用于控制NRF24L01模块发送一行数据:8 B" F1 }8 O: p& `
$ f7 |4 v1 Y7 g3 ?6 `1 g* q! A* V. o. c! H) Z4 X
看看发送效果,按下fb之后,H7R7开发板会通过NRF24L01模块发送一行字符串,另一个设置了相同接收地址的NRF24L01开发板就会收到这个字符串:$ w! u8 h, \- A
5 T) s( g( F6 ]. v: ?1 M3 u然后是接收,接收就更简单了,只需要设置模块为接收模式后,在Tick事件回调函数调用即可:
1 w% I. D, l5 R1 Y0 s$ }* Y
0 Z9 G n6 S" o# ?! B |
- y4 c- r$ W- l8 p3 s+ i