上回在NUCLEO_L552ZE_Q_STM32Nucleo_144 开发板上测试了外部中断的使用,本想着这回来一篇有关TrustZone的文章,毕竟这才是Cortex-M33的重要的内容,于是花了些时间去研究,然而现实总是那么残酷,在这碰了壁,自己建立的工程下载进去之后没有反应,就想着先去看看官方给的GPIO_IOToggle_TrustZone例程,按照说明文件里的步骤下载到开发板上,结果还是没有任何反应,我也是一头雾水,在网上也找不到任何有关的资料,说明文档是英文的,看得也是一知半解的,所以就没弄成,还是决定先放在一边吧,不能被这个耽搁了。恰好手上有两个nRF24L01P模块,还有两块stm32f103c8t6小板子,于是就鼓捣了一下使用它们来做个无线通信测试,下面就请跟随我进入正题吧。# D4 b" n7 @ {6 A7 S6 e/ B
评测内容:/ q/ p2 S2 p+ ?5 R
1、使用STM32F103C8T6系统板连接nRF24L01P作为主机发送一固定长度字符串,NUCLEO_L552ZE_Q_STM32Nucleo_144 开发板的板载SPI通信接口连接nRF24L01P作为从机接收,并且通过uart串口将接收到的数据发送到PC上位机显示,使用板载LED指示发送和接收状态。7 s" g+ w" ?. v2 N
所需元件:% B9 ` z' ^! s$ |! s r
1、NUCLEO_L552ZE_Q_STM32Nucleo_144 开发板*1;
9 N% G) I+ ^ R0 \. @3 E0 k2、STM32F103C8T6系统板*1;5 \6 @5 a, @& T
3、nRF24L01P模块*2;
9 E! r3 g/ g( `) g; A2、板载红色LED;, v! m/ J( L. u6 f5 q8 x5 `/ e% A9 a
: R) ?& s; ^8 Q5 b, r- c评测步骤:
$ ~: ?. O" M# O) R3 u& H& p2 G0 C5 P5 C1、新建工程:' \4 F+ E; e& E$ m0 E; j
本次测评我使用STM32CubeMX的开发板模板进行工程创建,针对NUCLEO_L552ZE_Q_STM32Nucleo_144 开发板上的板载硬件已经默认帮配置好了,只需要根据自己的需求配置SPI接口便可以了,按照如下步骤便可创建一个开发板的默认配置工程;
5 J2 T) W7 y4 ~- e" ?. Z& t
$ S# ]* u3 e! u; G1 b# \* l
$ `7 I) [, v$ }. a! n2 ?2、配置SPI接口:
! q4 o% {/ U( Z3 x7 {! z% U! K根据下图配置将SPI接口设置好,SPI接口使用的是开发板上的CN7排座的SPI_A接口,在STM32CubeMX上SPI1的默认SCK引脚在PA1上,我根据开发板的原理图将其改到了PA5,需要注意的是,nRF24L01P的IRQ引脚需要设置成上拉输入模式;
5 _/ B+ Q# f( K4 p' E! T, B
0 a$ n. x% B- `/ n- t! i! N, @nRF24L01P的SPI接口
' ^4 @+ A9 E. s4 s; j8 h; U7 A. t4 K* v$ B/ ]+ Y' ~4 }, E
SPI配置选项
, ~6 M7 d; f: v7 j6 Z9 u) X3 R+ s2 B ?/ X J
开发板接口原理图
3 L! H& K F% n; ~" C) @3、设置串口波特率:# @; H: K/ J4 h/ h3 h1 ]! \
开发板上与STLink虚拟串口连接使用的是LPUART1,工程创建的时候已经默认配置好了,使用PG7和PG8两个引脚,波特率为209700Bits/s,这个波特率不是我想要的,所以将它改成了921600Bits/s;
5 l' b: r& u, K( ^4 o9 G( L% ^. h, A. d1 A
4、保存工程:! Y& }. G3 \8 }. H- Y2 F" N0 P: y
保存好配置工程并且生成MDK_v5工程;) Z3 g3 r& l* m' C- e7 r/ h3 I2 P4 j' [
+ T# X, h* B7 \% m
5、测试串口的工作情况:
: a! P; K3 q) I6 J' x/ I/ O8 D6 m. T因为不能保证nRF24L01P能够顺利的工作,因此我是先测试串口能够正常工作之后再考虑加入nRF24L01P;这也是一种调试代码的技巧,一点点来,不然什么东西都一下子加上,调试的时候出问题就会不清楚问题的出处具体是在哪里;; ?, P% E0 ^" |, o
在这里,又再一次体现出了HAL库强大的封装工艺了,在标准库函数上要实现发送一个字符串,需要自己调用串口发送字符的函数来循环实现发送字符串的函数,而在HAL库上,只需要一个函数,不管是发送字符还是发送字符串,统统都能搞定。
- T6 ?2 _. z2 A; C% z就像以前学习串口通信的时候发送Hello World一样,添加如下代码到main函数的循环里,
) {2 q# k6 h- C- HAL_UART_Transmit(&hlpuart1, "Hello World !!!\r\n", 17, 100);
4 w# C- p. R3 C+ I$ ~3 s - HAL_Delay(500);
复制代码 将代码编译连接通过后下载到开发板上,按下开发板右下角的复位键后,便能在串口助手上看到如下打印的信息,说明串口工作正常;
+ a y! q6 U8 q6 K
/ Y9 Z; h. h7 Q9 c, U9 T6、添加nRF24L01P相关的代码:; r7 S1 k% L) j
nRF24L01P的代码我使用的是购买该模块的时候官方提供的测试模板,模块使用的是泽耀科技生产的挪威原装芯片nRF24L01P模块,不是黑色PCB板那种,但应该都是通用的,接口也是一样的,已经成功在我的STM32F103C8T6系统板上正常收发了,代码我会在末尾的附件中给出,* \2 c+ B0 T' t+ E! c% E" k
复制模板的nRF24L01P源代码和头文件到本工程中并添加到工程里;9 E, X6 C1 t2 ~- K0 b
* t9 u+ {% x# F/ b* \1 I- h7 D7 i8 k! a
由于使用的环境不一样,需要做一点修改,首先是引脚宏定义,在nRF24L01P.h文件的开头添加#include "main.h",并且将不需要的头文件包含去掉,nRF24L01P.h文中定义了模块的CSN、CE、IRQ三个接口的引脚,改成如下;) K7 ^3 H$ ^2 M3 L2 _
- /** RF24L01硬件接口定义 */+ K0 \! q' j* y
- #define RF24L01_CE_GPIO_PORT GPIOD
. }/ ]. k4 a; t6 n c3 V - #define RF24L01_CE_GPIO_PIN GPIO_PIN_15
* C. r5 x `7 c - $ |+ e5 a& m1 d4 M T: Y1 x" [
- #define RF24L01_CS_GPIO_PORT GPIOD
5 W" L# ^, o' w, P7 x n - #define RF24L01_CS_GPIO_PIN GPIO_PIN_14
- g! \" f8 g( h% K4 w
: y+ Z2 w% B* A: ~- #define RF24L01_IRQ_GPIO_PORT GPIOF
. V4 C. U* l+ K3 Z' A - #define RF24L01_IRQ_GPIO_PIN GPIO_PIN_12
复制代码 然后是nRF24L01P.c文件中的延时函数,替换成HAL库的延时函数,并且注释掉500Ms的延时函数(HAL库的延时函数能够延时500ms以上),相应的调用延时函数的地方再做点修改;
- ~/ Q7 R, e- N; _: o4 s' c- /**
. h2 K2 Z$ N" f; O# e$ f0 ` l& B" ? - * @brief :NRF24L01 延时(Ms)
8 c3 W! J: S+ L - * @param :
0 M4 R! j$ S! N; R0 {; d - @TxByte:延时的Ms数
6 P/ l2 S6 x. v4 e4 n! x& b1 r - * @note :不超过2^32。: v- Z5 ?+ j- v
- * @retval:无
& V+ e( D( j2 J8 a+ p" `* U - */
: [: E2 ~" G2 L - static void NRF24L01_delay_ms(uint32_t Ms)! J# l/ j4 m$ P
- {/ S: S, S& R( J% Q+ I7 ^: f
- HAL_Delay(Ms);
$ {) n; Q3 O( J2 @- d* _ - }! G/ R3 N* `) f% `2 W' {; V
- + ]. ~1 O. B5 X6 ?4 N3 ?
- /**& t; p) F' ^7 I" r; ~6 D1 |4 S" X# f
- * @brief :NRF24L01 延时(500Ms)9 \* C2 @1 W: `0 n" S/ ?
- * @param :
) u. t; [- f& m( h/ p - @Ms_500:延时的500Ms倍数
. e y& U M( O* I& o - * @note :不超过255。# @3 a& ^9 S8 k+ H; |* O% }
- * @retval:无
2 j" K( B5 L" ? u8 \ - */; M1 S% z) a( Q2 \1 G3 k Q
- //static void NRF24L01_delay_500ms(uint8_t Ms_500)7 e+ f; x! K4 W/ G
- //{3 \$ \" L- g+ I2 j
- // drv_delay_500Ms(Ms_500);
2 w, z! B9 k. N3 m8 f - //}
复制代码
' k8 v9 p9 M/ _% i. q7 y, x接下来是将SPI读写函数替换HAL库的SPI读写函数,在这里又再一次凸显出了HAL库的那个简单易用的优点;8 t( W4 U8 a2 i# p
- /**2 _5 d3 f% b: J q+ m/ L2 {2 @7 {2 _' c
- * @brief :NRF24L01 SPI收发一个字节
9 \. K/ _( C; G# w' F - * @param :
8 F \+ m) U: X q9 a5 A+ J0 w - @TxByte:发送的数据字节" s1 s' S: v* V
- * @note :接口函数,方便移植。
) ^9 m8 R/ h) k3 y R% B1 g$ x- d - * @retval:读取的数据
+ q; v6 z" d+ o# b - */. ~1 h1 w* r: }2 I4 M
- static uint8_t nRF24L01_SPI_RW_Byte( uint8_t TxByte )
9 A- x; k* |- _0 P8 V - {
- _* {2 D! m: U$ v - uint8_t RxByte;
+ _0 Y" p% _! z6 P# I5 M" ^# X7 W' e! E - 8 ?( V' r: N- W$ I5 @
- HAL_SPI_TransmitReceive(&hspi1, &TxByte, &RxByte, 1, 100);
( H# o% G0 R0 I, v3 H b- q -
_3 r5 n! {. l - return RxByte;
N% B0 h( u+ p* v8 @ - }
复制代码 再接下来,nRF24L01P.c文件实现了nrf24L01P使用到的GPIO口的初始化函数NRF24L01_Gpio_Init,由于使用的固件库不一样,且main.c文件中已经统一初始化了,所以就将该函数的内容注释掉,并且注释掉所有调用的地方。编译工程,没有问题说明移植成功。
4 y& S6 i, e8 f; P7、编写代码实现无线接收功能:将nRF24L01P.h包含到main.c文件中,在文件开头定义一个用于接收数据的数组;
0 p) n' x5 i! x6 i, P; [ f- M! M- T- uint8_t g_RF24L01RxBuffer[ 32 ] = { 0 };
复制代码
& o2 Z2 V1 X$ Y在main函数中添加如下代码,实现nRF24L01P的无线接收功能
" J$ ~9 z, T8 X, [- uint8_t i;( G4 J }: x0 a' r3 `& ^
-
1 q3 e. x5 j/ a) K - /* USER CODE BEGIN 1 */
7 ?! i1 _1 t) j - & s7 X; ^) P; O* K, o$ d2 Y" U
- /* USER CODE END 1 */
9 x8 H8 c$ n+ f# ^+ A( m: X - ' F3 @) d$ T$ S* v5 q% B" Y
- /* MCU Configuration--------------------------------------------------------*/5 t' j( j9 [. x/ H* ]3 y* }
$ S q4 `; j. }# b, V# l) S- /* Reset of all peripherals, Initializes the Flash interface and the Systick. */
2 c0 P; X3 x) t) ?; k/ O/ j - HAL_Init();
" f5 i p" B' v- z/ T' W - ! g& p6 [5 h/ j' j
- /* USER CODE BEGIN Init *// a8 W3 ?6 f5 @9 w: Q" V0 `$ Q
' Q- i3 G R+ L% P* h- /* USER CODE END Init */
+ g% N( a) ~& u# y
/ @& D) N, ?5 C q# q- /* Configure the system clock */
]6 k9 x/ m. k% t$ q - SystemClock_Config();
+ h7 ?! _/ l7 H/ t - & Y/ a. I. r/ _4 e& I/ M
- /* USER CODE BEGIN SysInit */+ l q4 N2 W& r$ s+ `
* B" V% R+ V' Y$ F- O3 ~# u! x/ C- /* USER CODE END SysInit */0 m& M2 w( t# B4 f/ y
- . {2 a, v! L$ H" v. E3 l: ?
- /* Initialize all configured peripherals */
C" s1 W, a( N0 e3 p5 H - MX_GPIO_Init();7 ? D8 \4 j" I, I! C& p
- MX_ADC1_Init();7 T0 L# U8 t0 y1 t
- MX_LPUART1_UART_Init();
|4 H5 o( j9 ~* Y; G0 i: f - MX_RTC_Init();: H' p9 T' c+ t
- MX_SPI1_Init();
* h2 r+ M+ P2 P/ x7 {2 f8 l+ J* L" | - MX_UCPD1_Init();7 g& Z% V/ z+ C8 D& }% ]
- MX_USB_PCD_Init();2 p e# c2 G' q
- /* USER CODE BEGIN 2 */- g. y7 R4 k0 V; k
- NRF24L01_check( ); //检测nRF24L01P是否已连接
# x3 c) |( z$ h3 C. U - RF24L01_Init( ); //初始化nRF24L01P- X# a# W! o. i5 D) i/ ~" Y$ m
-
7 t" `8 J* K7 k7 [! @* k - HAL_GPIO_WritePin(LED_RED_GPIO_Port, LED_RED_Pin, GPIO_PIN_RESET); I& ~1 u( d) ^8 w9 [
- for( i = 0; i < 6; i++ )4 p* z/ O" V1 h' U; P$ e- k
- {
; }- y2 `/ _- @6 |3 O8 h- Z - HAL_GPIO_TogglePin(LED_RED_GPIO_Port, LED_RED_Pin);: \7 w3 Z3 N% F& L6 }
- HAL_Delay( 500 );
% I; t& c* Z6 H7 ?4 f& c2 l) g - }7 f' A! ]! M1 n5 r1 @5 V4 e
- 8 r8 N' ^" r, N0 |2 ^, q
- RF24L01_Set_Mode( MODE_RX ); //接收模式, k9 Y( I" @/ ^6 s; t i3 f+ G
- /* USER CODE END 2 */* o: F* @' H7 v
- A, v; `) f2 s8 p
- /* Infinite loop */
+ X8 v, ]5 @/ C$ ~! S6 D - /* USER CODE BEGIN WHILE */
, q( Q& D& \$ R* T - while (1)0 j2 \# k% Z7 [+ k- d
- {
0 W+ h& W0 G/ C7 ^$ E - /* USER CODE END WHILE */& z' q; I6 O$ _- ?! M0 v
- O& {% x1 ~$ b2 w5 u: G5 e- /* USER CODE BEGIN 3 */7 V! O2 }8 ?1 g$ V3 u" A2 n, W
! e" F) G' k9 n0 F2 ^- i = NRF24L01_RxPacket( g_RF24L01RxBuffer ); //接收字节
6 Z$ c h ?6 T: v8 X3 M - if( 0 != i )+ n' k f y. C9 C" z
- { e0 [/ e5 l" \
- HAL_GPIO_TogglePin(LED_RED_GPIO_Port, LED_RED_Pin);
' U- o. Y8 [3 ?5 L1 g' T - HAL_UART_Transmit(&hlpuart1, g_RF24L01RxBuffer, i, 100); ! d. _; k( t, s/ A& V$ [
- }# ?* a+ |' m5 b5 V/ `5 f. ?
- }
) ^% L" Z$ i ~' _ - /* USER CODE END 3 */
复制代码 8、运行结果:代码编译通过,烧录至开发板上,按下右下角的复位键,程序开始运行。发送端我使用的是官方测试模板小改动后在STM32F103C8T6系统板上实现的,在此就不详细阐述了,有需要可下载附件做参考。发送端和接收端都运行起来后,串口助手上也开始打印接收到的数据了;( G5 B2 t2 y: Y5 H0 T0 ^" m) @
5 b3 h' S5 f0 N# |% L! D% i+ G1 }# Y3 ]& m
总结:
+ r1 v+ k( o8 @nRF24L01对我来说是个噩梦,为了能够发挥NRF24L01P的最远传输距离,曾经一点点啃英文数据手册应用在51单片机上(黑色小模块给的例程都是NRF24L01而不是NRF24L01P的,前者的传输距离较短,后者的资料有点少),前些天为了将原先51单片机上程序移植到STM32上,荒废了几天时间,还是无法发送数据,气得我直接将模块给废了,然后就遇到了这款红色版的模块,例程和资料都可以再公司官网上下载到,很详细靠谱。( X" s! B) c( d5 s/ r& Z3 i
NUCLEO_L552ZE_Q_STM32Nucleo_144 开发板的SPI和UART串口评测就这些,简单来说,使用HAL库来开发的代码确实要简单很多,开发板上的STLink还提供有虚拟串口,并且将SPI接口也都在一个地方引出来了,对于接线来说很方便。OK,有关nRF24L01P的细节东西比较多,有些地方没有阐述清楚的,欢迎在评论区指出。
$ f6 [" `! x5 b4 Y4 H* `7 _( I( k& ]% A* b* Q. }' F
1 Z) W- F2 s( @0 H4 B- o
' S2 s& E% @. f H: H5 y+ P; r' h4 {: R) v6 h6 ]$ F; l4 e& A5 G
nRF24L01P_TX.zip
(4.45 MB, 下载次数: 2)
|