正点原子H7R7开发板上面的NRF24L01接口是可以接一个NRF24L01模块的,原子论坛也提供了例程可供参考,但是是适配给原子自家的NRF24L01模块的,使用第三方模块厂出品的NRF24L01模块程序需要做一些细微调整,无法直接通用。) q4 ~6 d1 a8 v* m9 A
, I2 Z/ i9 Z8 y# v& j
首先是初始化SPI接口,这个非常简单:7 |) X, o- i/ V( g( @, s8 {$ s& u
- SPI_HandleTypeDef g_spi_handle;
/ j- Q2 Z5 t# L7 t - ; o' z5 T: E1 \9 W9 L' ~, K, H
- uint8_t SPI2_PD3_PC2_PC3_Read_Write_Byte(uint8_t txdata)
% ? }( B M" J - {
: i& I, y* Q1 L. v' z8 S+ J; x - uint8_t rxdata;
4 J7 u3 b# z5 d. e, y& G - HAL_SPI_TransmitReceive(&g_spi_handle , &txdata , &rxdata , 1 , 1000);
- s( o* L7 t3 s$ J! x - return rxdata;
3 v( T% h% @. g - }
' S Z% v9 p) n1 u! f
' H" x( ~) T4 d8 a0 {3 x; H- void SPI2_PD3_PC2_PC3_Init(void), X; k' A8 f/ s3 o) u0 ~
- {
& U% s% M! N7 Q7 H - GPIO_InitTypeDef gpio_init_struct = {0}; S! T1 x+ s9 u3 D
- RCC_PeriphCLKInitTypeDef rcc_periph_clk_init = {0};
( q( x, G; }$ w
. ]6 ?$ r, d1 {, i7 N- __HAL_RCC_SPI2_CLK_ENABLE();
$ b4 r2 u" x3 i" A8 P5 h - __HAL_RCC_GPIOC_CLK_ENABLE();$ ~* I$ v' y' \& r$ o; D% h3 i7 [
- __HAL_RCC_GPIOD_CLK_ENABLE();6 s$ Z( g3 H% T3 w" m7 M
- & ^- H$ q" W v, _- f
- rcc_periph_clk_init.PeriphClockSelection = RCC_PERIPHCLK_SPI23;& _+ Q! N( N0 y0 w- a* i9 P) W
- rcc_periph_clk_init.Spi23ClockSelection = RCC_SPI23CLKSOURCE_PLL1Q;$ }% o1 G. s( P; U) a# m. k; L
- HAL_RCCEx_PeriphCLKConfig(&rcc_periph_clk_init);
6 R4 w7 X2 `! ?/ ~ - # j1 y: Z3 t \, X( {# u
- gpio_init_struct.Mode = GPIO_MODE_AF_PP;$ h! n" a! r( h) @
- gpio_init_struct.Pull = GPIO_PULLUP;
; w, L, ^7 w$ r( l - gpio_init_struct.Speed = GPIO_SPEED_FREQ_VERY_HIGH;
6 S, R5 S5 e7 a; c0 d9 X1 q
( e, r c; u) r( ~8 q% l8 k+ [9 p- gpio_init_struct.Pin = GPIO_PIN_3;
3 L* Z$ l9 C; f% S. f+ t - gpio_init_struct.Alternate = GPIO_AF5_SPI2;- f- c" l4 d2 \7 L! p, r' [% p
- HAL_GPIO_Init(GPIOD , &gpio_init_struct);8 {, D0 ]3 U: c' k
- / U+ g# L7 G0 I7 x8 t5 B
- gpio_init_struct.Pin = GPIO_PIN_2;
! r. q' I5 }* c5 z& L. X. u, f3 N - gpio_init_struct.Alternate = GPIO_AF5_SPI2;
5 F$ u' m# r3 u, N' w0 U - HAL_GPIO_Init(GPIOC , &gpio_init_struct); Y# v. r% u1 S
-
4 C8 i/ L& ]) _$ T/ w - gpio_init_struct.Pin = GPIO_PIN_3;( _+ p& A( w" c$ n; O
- gpio_init_struct.Alternate = GPIO_AF5_SPI2;% s/ r9 ^2 X* A8 g
- HAL_GPIO_Init(GPIOC , &gpio_init_struct);
% v7 p( {% Q( O$ O( \/ n$ X1 t5 \! z! ` - ; e* I/ Z: v; ?5 c3 w( ~
- g_spi_handle.Instance = SPI2;
% `% T7 V2 v( z& A - g_spi_handle.Init.Mode = SPI_MODE_MASTER;+ w Y0 W( ^0 C9 Z
- g_spi_handle.Init.Direction = SPI_DIRECTION_2LINES;
# T% J+ ^+ q( e7 X H( W; r/ m - g_spi_handle.Init.DataSize = SPI_DATASIZE_8BIT;
2 o& H$ D" i5 X: y - g_spi_handle.Init.CLKPolarity = SPI_POLARITY_LOW;
- }) \- I0 r2 t; C - g_spi_handle.Init.CLKPhase = SPI_PHASE_1EDGE;. h' }, v! f; ]' x' R5 R
- g_spi_handle.Init.NSS = SPI_NSS_SOFT; 0 _* R! b3 E# o# } o2 `+ B- ~
- g_spi_handle.Init.NSSPMode = SPI_NSS_PULSE_DISABLE;
. ~* W% t0 [$ t; i5 B$ g - g_spi_handle.Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE;2 o5 M& e; |3 H. i9 J {9 S
- g_spi_handle.Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_128;
n, S; ~) w& d: W) A8 _( u4 |' n% U - g_spi_handle.Init.FirstBit = SPI_FIRSTBIT_MSB;
. p$ c6 U9 e5 z. P - g_spi_handle.Init.TIMode = SPI_TIMODE_DISABLE;
+ h# ^/ H+ ~) m+ k9 P - g_spi_handle.Init.CRCCalculation = SPI_CRCCALCULATION_DISABLE;' W% ]) S- X: x
- g_spi_handle.Init.CRCPolynomial = 7;
3 `* t# C4 O3 P/ ]8 F5 S1 I' h) Q - HAL_SPI_Init(&g_spi_handle);
9 P; C, v2 B9 G; m5 q. I) m
( o" f/ F) g* I# f* b- __HAL_SPI_ENABLE(&g_spi_handle);. s/ H2 @' b: e
- SPI2_PD3_PC2_PC3_Read_Write_Byte(0Xff);
9 V: D# ]! _1 k' @' @! M ~ - }
复制代码 这里需要注意的是,H7R7的SPI接口时钟要设置为128分频或者256分频,因为SPI123三个接口的时钟直接挂在PLLQ上,分频太少的话,波形变形的程度使得NRF24L01无法识别,进而无法进行任何通信,然后就是时钟信号空闲时为低,第一个沿变开始传输数据,这个也是NRF24L01芯片的特性,不遵循这个设置无法进行通信。& G! O% w) H! Y" j
$ X* K: u7 V) o: S; VNRF24L01还需要用CS CE IRQ三个脚,其中CS脚是片选,需要在传输数据时进行控制,CE脚常高表示使能,IRQ脚是发送时会用到:
- Q( Q7 m. [- O @4 W& k" ]- #define NRF24L01_CS_GPIO_PORT GPIOM M: F ` S. G7 b- C
- #define NRF24L01_CS_GPIO_PIN GPIO_PIN_134 Y7 v- J* @9 ^2 j6 g' ?
- #define NRF24L01_CS_GPIO_CLK_ENABLE __HAL_RCC_GPIOM_CLK_ENABLE();
- K" m& s0 y; D$ d l1 t8 x/ l - #define NRF24L01_CS_HIGH HAL_GPIO_WritePin(NRF24L01_CS_GPIO_PORT , NRF24L01_CS_GPIO_PIN , GPIO_PIN_SET);; V* U: o# V% V' [; W
- #define NRF24L01_CS_LOW HAL_GPIO_WritePin(NRF24L01_CS_GPIO_PORT , NRF24L01_CS_GPIO_PIN , GPIO_PIN_RESET);
8 ^# R% A* v# K - + N+ _- K5 Z1 C; e# ]
- #define NRF24L01_CE_GPIO_PORT GPIOM
8 C( G$ Z# r' \; T0 c2 N; E - #define NRF24L01_CE_GPIO_PIN GPIO_PIN_14
& W- i5 z7 F: E. E! Q& ~9 { - #define NRF24L01_CE_GPIO_CLK_ENABLE __HAL_RCC_GPIOM_CLK_ENABLE();
' b4 t1 b! C* M' l - #define NRF24L01_CE_HIGH HAL_GPIO_WritePin(NRF24L01_CE_GPIO_PORT , NRF24L01_CE_GPIO_PIN , GPIO_PIN_SET);
# ~) |' B6 m2 q+ X" r0 I" q1 @ - #define NRF24L01_CE_LOW HAL_GPIO_WritePin(NRF24L01_CE_GPIO_PORT , NRF24L01_CE_GPIO_PIN , GPIO_PIN_RESET);% d. d3 z- f& Z+ t6 J
% l8 `* }) B7 I- #define NRF24L01_IRQ_GPIO_PORT GPIOF
: k" o. s; a/ b) j - #define NRF24L01_IRQ_GPIO_PIN GPIO_PIN_2) p/ c! {! @+ }4 K7 t% M7 e
- #define NRF24L01_IRQ_GPIO_CLK_ENABLE __HAL_RCC_GPIOF_CLK_ENABLE();. L$ X5 g# J) r" k
- #define NRF24L01_IRQ_READ() HAL_GPIO_ReadPin(NRF24L01_IRQ_GPIO_PORT , NRF24L01_IRQ_GPIO_PIN)
: m" @+ t7 h$ T1 E1 D0 H
5 L0 e$ b: F5 ?3 ~1 ?1 Q- void NRF24L01_GPIO_Init(void)
- ^9 f8 q9 G2 {! q7 K) x - {! S9 k2 s1 M: C* ? e8 k+ h1 z8 U- |% ~3 h
- GPIO_InitTypeDef gpio_init_struct;
2 M; v0 E1 \: Y* D; c - NRF24L01_CS_GPIO_CLK_ENABLE;2 u) a7 {7 g9 L" X
- NRF24L01_CE_GPIO_CLK_ENABLE;( ^6 r2 ^+ x5 r# d2 J. {
- NRF24L01_IRQ_GPIO_CLK_ENABLE;
6 U1 p! _, m: @0 ^, g( v - ( u4 u1 G* q! F! s/ `3 |
- gpio_init_struct.Mode = GPIO_MODE_OUTPUT_PP;3 C3 ]1 b( k0 H7 k6 I
- gpio_init_struct.Pull = GPIO_PULLUP;9 j6 e1 h! r$ E, x, t
- gpio_init_struct.Speed = GPIO_SPEED_FREQ_HIGH;' X" D% ]" ~! K* W R
-
- H- M) P, O8 x+ c - gpio_init_struct.Pin = NRF24L01_CS_GPIO_PIN;
+ U6 ]' x& a0 F0 I& S9 ~1 N - HAL_GPIO_Init(NRF24L01_CS_GPIO_PORT , &gpio_init_struct);, Q5 M0 ~5 t5 W3 R$ i, ^
-
) o# w- y( L2 ^, i7 c - gpio_init_struct.Pin = NRF24L01_CE_GPIO_PIN;
1 u- t+ h/ s, W' M) x - HAL_GPIO_Init(NRF24L01_CE_GPIO_PORT , &gpio_init_struct);
0 x2 k# \2 `* R: k5 g0 x - 6 V' c+ A( N; {! H: t4 K9 X1 l
- gpio_init_struct.Mode = GPIO_MODE_INPUT;
; R: K* k8 I* [ - gpio_init_struct.Pin = NRF24L01_IRQ_GPIO_PIN;8 U9 ]; C+ a3 k) d) E1 i$ A3 o
- HAL_GPIO_Init(NRF24L01_IRQ_GPIO_PORT , &gpio_init_struct);
( W2 y, r/ {3 P+ j) Z, ] - 6 A. b' K2 \+ z" H! P/ T
- NRF24L01_CE_LOW;
8 c! H9 ~* C8 P - NRF24L01_CS_HIGH;. Z/ p3 {& h2 m7 x+ I% m' N# Y9 ~
- }
复制代码 6 e" p. \: G6 T0 p' R7 A
% W' v% q; |' X4 F( G# E
6 k* A- J) P- u
NRF24L01有五个寄存器是可以用来检测器件是否正常工作的:
: b6 b4 `4 [, q, ]" U0 E- uint8_t NRF24L01_Check(void)
( B( [3 v$ q# X' \" X7 } - {) k/ y' R/ x4 Q, b$ I0 m6 Y9 v
- uint8_t buf[5] = {0xa5 , 0xa5 , 0xa5 , 0xa5 , 0xa5};
9 {3 e+ v4 ]6 L - uint8_t i;1 r/ O e6 m4 t! T
- NRF24L01_Write_Buf(NRF_WRITE_REG + TX_ADDR , buf , 5);
) _8 n5 {6 Q0 ^, y8 p' ~ - NRF24L01_Read_Buf(TX_ADDR , buf , 5);, a% ?& O( I* }% x$ Z$ x$ W
- for(i = 0 ; i < 5 ; i++)3 `. b4 J: Z' B8 W% k
- if(buf[i] != 0XA5)
" H' R' U# L( E: @ - break; # M' N7 @' M" K% W
- if(i!=5)- v* b, t0 G6 m5 v$ \5 u$ k
- return 1;
; o7 m3 T3 o4 t+ A1 e$ ~5 U3 D - return 0;
6 h6 n: t' m5 w& U3 ?$ |! X' a - }
复制代码 $ X) X. g3 D% \; d8 {( V
NRF24L01模块在同一时间只能设置为只接收或者只发送模式,属于半双工器件,要实现全双工收发需要两个模块:
1 p7 [" a2 X( x- void NRF24L01_RX_Mode(void)/ E, n: k; e8 g2 X3 y
- {
) E5 I2 w) w# H - NRF24L01_CE_LOW;
, P: n; o+ ]# [6 {" l& [ - NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(uint8_t*)RX_ADDRESS,RX_ADR_WIDTH);8 o# B1 W2 z# M
- 8 E) F3 {2 p1 a" G- Z
- NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01); 8 _# e( }$ b$ w8 g$ T5 a# ~0 ]
- NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01);
! F- a# J% I. _) U, w, l - NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40);$ V9 g! _' R, r0 @) v+ S
- NRF24L01_Write_Reg(NRF_WRITE_REG+RX_PW_P0,RX_PLOAD_WIDTH);
4 ^% q: U* K/ w/ P - NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);
/ L0 }4 `1 D% @! {+ c - NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG, 0x0f);
1 b7 q+ m, W. a0 G - NRF24L01_CE_HIGH;
% t: }9 b+ u9 t6 L) t - }' P" X1 L5 f: `1 [$ X
- 9 V. g; M7 f! b V6 p4 d
- void NRF24L01_TX_Mode(void)
" l2 r6 W. y' V9 [0 w2 O$ a5 e - { ; d% Z" [; f4 s3 G
- NRF24L01_CE_LOW;
% |5 A. d" O% Y- T4 G; I* H$ j- |* s - NRF24L01_Write_Buf(NRF_WRITE_REG+TX_ADDR,(uint8_t*)TX_ADDRESS,TX_ADR_WIDTH);' k- @0 J* ~* v+ Y/ Z
- NRF24L01_Write_Buf(NRF_WRITE_REG+RX_ADDR_P0,(uint8_t*)RX_ADDRESS,RX_ADR_WIDTH);( P5 Z7 O1 o4 z
- ) m% x8 t2 g9 N! C: X0 j/ b
- NRF24L01_Write_Reg(NRF_WRITE_REG+EN_AA,0x01);) J2 {% X/ }* U0 g0 y
- NRF24L01_Write_Reg(NRF_WRITE_REG+EN_RXADDR,0x01);
: f0 P) L" O; u - NRF24L01_Write_Reg(NRF_WRITE_REG+SETUP_RETR,0x1a);- M& j7 q9 p* ]/ S9 l
- NRF24L01_Write_Reg(NRF_WRITE_REG+RF_CH,40);+ F' e S0 L" ^, R
- NRF24L01_Write_Reg(NRF_WRITE_REG+RF_SETUP,0x0f);1 w+ E2 Y; ~) f. K( K" Y% W# `" n; \7 L
- NRF24L01_Write_Reg(NRF_WRITE_REG+CONFIG,0x0e);. }6 w! l/ |0 ]6 a. `" y0 [
- NRF24L01_CE_HIGH;7 R( Y6 n# a* {$ h0 ]- C) n
- }
- J B" |' ^2 A" H3 M' ]8 ?$ T1 q
) z$ h8 K4 h# k" S4 f- uint8_t NRF24L01_RxPacket(uint8_t *rxbuf)
+ x8 a/ U6 R# c' Z4 P - {
' ]7 q o) _) T/ Q' p" O% G$ T - uint8_t sta;
* t+ I* K* {2 D2 z2 J1 }7 @: z: ? - sta = NRF24L01_Read_Reg(STATUS);
8 d' X/ ^# L$ f5 h: A. C+ ]7 m
) |) F% ~6 \; p# E" d% ?" B# u- NRF24L01_Write_Reg(NRF_WRITE_REG + STATUS , sta);
2 o7 P/ e) l' i% r8 x - 9 @' x, M' y/ B) f) ?
- if(sta & RX_OK)$ R' ~+ ?# t. Y1 L$ N
- {
/ P9 @5 G' D* ~) X% G* q - printf("sta = 0x%x RX_OK.\n" , sta);
]7 c8 O( `5 G, t- t - NRF24L01_Read_Buf(RD_RX_PLOAD , rxbuf , RX_PLOAD_WIDTH);8 V; ]* m4 d; U) n( n) S2 f; q
- NRF24L01_Write_Reg(FLUSH_RX , 0xff);; C0 K: A0 n: j ^5 O$ [& ~. }4 c
- return 0;
8 D9 l6 W+ \0 K7 T) M - }
6 R% c( R7 a! I o, J7 L6 { - return 1;4 ?: r! h3 v8 A4 f3 {0 o
- } . y, Y: S& a% b T9 X
! `2 V9 V I% L- uint8_t NRF24L01_TxPacket(uint8_t *txbuf)
5 u! x7 N" X! `7 d' A6 J - {% h; @1 B8 C, K/ w: q2 a% I
- uint8_t sta;
W1 v8 |6 L' W5 @- ^& u - NRF24L01_CE_LOW;
$ Z" J6 o3 h! b4 G; @, c S - NRF24L01_Write_Buf(WR_TX_PLOAD,txbuf,TX_PLOAD_WIDTH);
0 u4 B/ w: R. E0 Q! J: T - NRF24L01_CE_HIGH;
3 S9 m* |6 F% G+ y% C - while(NRF24L01_IRQ_READ() != 0);
" R# \8 _, k+ \0 p$ p - sta = NRF24L01_Read_Reg(STATUS);5 Z# }3 @8 j- G) g. y
- NRF24L01_Write_Reg(NRF_WRITE_REG+STATUS,sta);
- |- c8 Q+ x N - if(sta&MAX_TX)
. G1 ?' x0 }6 o9 Q6 s/ j6 @# r" q3 a - {( L4 R' {! J5 `, {
- NRF24L01_Write_Reg(FLUSH_TX,0xff);* Z& _! [; V9 q7 W* Z8 D0 y0 j- |
- return MAX_TX;& _/ O8 V0 e, b
- }$ T1 _* X" o2 F3 o
- if(sta&TX_OK)" @6 a/ E' \6 n6 {! [
- {0 n. c& M% L% T0 S+ j' m {
- return TX_OK;1 u" R$ m6 C0 a& T
- }
% Z3 f+ D" R7 b% n( u - return 0xff;
' P z0 {" t/ p0 }) M - }
复制代码 : C6 B" P; b6 b, W `" g: @' [
我这里在主界面创建一个flexButton用于控制NRF24L01模块发送一行数据:
/ U! A A; I" U+ L* z7 \
. \: }- G9 o' j: y/ S$ n7 R0 K+ U8 A! d6 X# y% a* O
看看发送效果,按下fb之后,H7R7开发板会通过NRF24L01模块发送一行字符串,另一个设置了相同接收地址的NRF24L01开发板就会收到这个字符串:% d% b+ X/ F# ]# v' o! V
% @, ^1 G, Y. S, s) y
然后是接收,接收就更简单了,只需要设置模块为接收模式后,在Tick事件回调函数调用即可:
; k$ l+ S& r" z0 N! @* J; U1 }
% ^' E ?9 F6 C0 s' l |
0 y J3 m& c9 G* ^( Q$ @! V9 M