前言
5 W- j& y% ^3 v, U2 O: x& dSTM32下NRF24L01实现无线传输4 n$ T& d7 P. y3 P+ ~
, X7 i1 C6 T) u! j
( q) v0 G1 {& t r8 T, U& m* E- t
一、原理图
$ r) ]. m. Q' k6 E& U& q1.STM32F103C8T6
6 m+ N4 |$ K) ~7 F4 c& x y1 ~
8 r# N7 v. `- p8 z% E& T( P
t) t; T' ~7 u" S% m
/ O% Z6 l1 @) j! n8 d7 \" v4 p2.NRF24L01
1 Z5 N+ _5 \1 v0 \
/ D8 A. j* T/ T
" Y/ x; ]9 E9 r" U: e
! O: ~. F; S* E, u9 UNRF24L01是 nordic 的无线通信芯片,它具有以下特点:: h' n. H x+ t: ?
6 v0 i+ K7 X, |3 D b8 U0 r$ c. b
& ]4 x$ O8 k4 L8 d1) 2.4G 全球开放的 ISM 频段(2.400 - 2.4835GHz),免许可证使用;
+ I: i g$ `6 X0 M2)最高工作速率 2Mbps,高校的 GFSK 调制,抗干扰能力强;! ?2 v, Z; ~9 x% p" k0 n$ ?2 E. ?3 [
3) 125 个可选的频道,满足多点通信和调频通信的需要;1 Q9 C6 \- n" y4 s1 c( n
4)内置 CRC 检错和点对多点的通信地址控制;8 f# A( H$ H& y3 Y. }. Y
5)低工作电压(1.9~3.6V),待机模式下状态为 26uA;掉电模式下为 900nA;
; P. m, v8 [7 A/ M+ b+ C) `# e6)可设置自动应答,确保数据可靠传输;
& W, U7 G; ?+ A& e7)工作于EnhancedShockBurst 具有Automatic packet handling,Auto packet transaction handling ,可以实现点对点或是 1 对 6 的无线通信,速度可以达到 2M(bps),具有可选的内置包应答机制,极大的降低丢包率。
; l0 O' l( g: S3 ^8)通过 SPI 总线与单片机进行交互,最大通信速率为10Mbps;& r' @* W; b' v$ _, s
0 J' L' ~( d _
# G B% h, k; r$ n; i) V二、Keil代码. e* n8 V- j* k* Z% g* S$ x% f
1.SPI_NRF2401.C: U, }4 V' O* |, L9 r, v
- <font face="微软雅黑" size="3">#include "Struct.h" E" t' S* r( Q% ]
( E) y" u5 {2 P0 |* z- /******************************************************************************
9 F9 u1 n1 e6 h+ b |, b) C - 宏定义& t/ Z+ }/ t/ i9 c5 d) s
- *******************************************************************************/
% l0 @3 s( d/ j* k - #define NRF_CE_GPIO GPIOC , m# o* ^- A! J, K- [! c* K7 X
- #define NRF_CE_Pin GPIO_Pin_14 " W2 U: S3 |- {' C2 }6 W
- #define NRF_CSN_GPIO GPIOC
) C) `" L- @0 a }$ |) T: F* R4 l9 [ - #define NRF_CSN_Pin GPIO_Pin_13
: U+ X8 h- j+ i7 P: c - #define NRF_IRQ_GPIO GPIOC5 C# \# x5 I; Y2 I& d! y, U& g
- #define NRF_IRQ_Pin GPIO_Pin_15
% A1 _ v# x$ C) J - + W$ P* P( ~2 J2 y; }
- #define NRF_CE_H NRF_CE_GPIO ->BSRR = NRF_CE_Pin //CE高电平+ V. O. i0 A ~5 C; N4 ~# I2 Z: p
- #define NRF_CE_L NRF_CE_GPIO ->BRR = NRF_CE_Pin //CE低电平9 Z) c* ^% y- n" S: o! _( }1 i! y. n' z6 j
- #define NRF_CSN_H NRF_CSN_GPIO->BSRR = NRF_CSN_Pin //CSN高电平( M- Q& {5 N6 P u/ R% `
- #define NRF_CSN_L NRF_CSN_GPIO->BRR = NRF_CSN_Pin //CSN高电平- ]! |* E; h$ h% {
- #define NRF_IRQ_Read NRF_IRQ_GPIO->IDR & NRF_IRQ_Pin //IRQ读数据; [' c8 u/ j7 r, \1 H
- /******************************************************************************
/ E) z h# n& K8 ]$ q2 x# r - 变量定义; q) x, V1 @6 M! r; J! Y
- *******************************************************************************/
3 H7 X% h5 x' v) X! a6 P - uint8_t NRF24L01_RXDATA[32];//nrf24l01接收到的数据
3 j5 P- `( Z2 u: m4 o - uint8_t NRF24L01_TXDATA[32];//nrf24l01需要发送的数据+ a8 k. {4 a# a. x$ h
- static uint8_t TX_ADDRESS[5]= {0x1A,0x2A,0x3A,0x4A,0x5A};//本地地址* ~2 a0 O- Q, E
- static uint8_t RX_ADDRESS[5]= {0x1A,0x2A,0x3A,0x4A,0x5A};//接收地址
1 \( Z# }5 e. o8 C' T0 E" K - static uint16_t Nrf_Erro=0;
; G; W7 R F3 m
2 \: K* ? D, {- /******************************************************************************8 g3 z! G: o5 m+ i- Z
- 函数原型: void SPI2_Init(void)+ ` N1 B T% N' Z) {, a( t
- 功 能: 初始化SPI总线; }0 P% q0 J4 c7 d
- *******************************************************************************/
' y. y: p( V! q - void SPI2_Init(void)+ X1 d% b/ N1 e9 m: }
- {
' @; q: X2 A4 P% k6 ~! [& e4 l5 p - SPI_InitTypeDef SPI_InitStructure; ' T+ j1 O# e) x m" j4 ^; ?$ g3 `! c8 ^4 d
- GPIO_InitTypeDef GPIO_InitStructure;
0 n1 t7 W. `: g - EXTI_InitTypeDef EXTI_InitStructure;
7 x3 Y# n( G2 K- n: w/ H - 7 H* V- i8 W5 T$ Q$ ~8 [
- RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC | RCC_APB2Periph_AFIO, ENABLE);% S2 k8 d0 l& K7 H1 c
- RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI2, ENABLE);6 z% C- g9 n6 c" T3 N8 r5 ^: x
- //配置SCK,MISO,MOSI引脚 # S* s) v2 g* k; g
- GPIO_InitStructure.GPIO_Pin = GPIO_Pin_13|GPIO_Pin_14|GPIO_Pin_15;
7 w( ]+ m2 x* y& r - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
% N$ s! z# Z) n" G! |& C - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP; //复用功能 & H8 c5 V. e3 C8 N/ A/ ~
- GPIO_Init(GPIOB, &GPIO_InitStructure);1 \. {! X/ j( r$ a7 u
- //配置CE引脚
, B/ ^! P1 s* A A - GPIO_InitStructure.GPIO_Pin = NRF_CE_Pin;
% H9 U( m0 ~& r3 t+ W - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
, X% |4 H, ~+ ~3 E9 _) |% j - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出+ u# F, T$ O7 o( u. R. C
- GPIO_Init(NRF_CE_GPIO, &GPIO_InitStructure);
* l# `. M* R# k: {$ D - //配置CSN引脚
8 T* s+ d* A9 S7 _ - GPIO_InitStructure.GPIO_Pin = NRF_CSN_Pin;
/ d, _/ Z! `9 K - GPIO_InitStructure.GPIO_Speed = GPIO_Speed_10MHz;
6 x( z2 R% [* M6 Q. v$ `! z - GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; //推挽输出
- k. @% ~2 l/ [! e I - GPIO_Init(NRF_CSN_GPIO, &GPIO_InitStructure);
# M7 c# }+ Z0 g8 j. f- w6 a* q) M9 @ - //配置IRQ引脚, [* {3 @2 t' {% W! O6 s
- GPIO_InitStructure.GPIO_Pin = NRF_IRQ_Pin; 5 Y }. B L+ h& @7 x4 [$ M
- GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; 5 I7 R0 `4 ?6 T' K- U3 A
- GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU; //上拉输入
- g& ~1 ~2 } o: @, E - GPIO_Init(NRF_IRQ_GPIO, &GPIO_InitStructure);
$ o8 k& O0 U9 @6 O- l' D - 0 T! G0 [. l# T5 h# T4 ^4 G. W4 z
- GPIO_EXTILineConfig(GPIO_PortSourceGPIOC,GPIO_PinSource15);% ?+ Z1 z5 @+ ?. y, i& `2 A8 c- N
- EXTI_InitStructure.EXTI_Line=EXTI_Line15;* E& P; D' [( g& _& I
- EXTI_InitStructure.EXTI_Mode=EXTI_Mode_Interrupt;//外部中断6 }; R3 G) Q( }' ~
- EXTI_InitStructure.EXTI_Trigger=EXTI_Trigger_Falling;//下降沿触发) A" `9 u# t6 p; ^% \" Q2 L- S& [
- EXTI_InitStructure.EXTI_LineCmd=ENABLE;
9 q5 \7 }" t6 @; w) u$ m - EXTI_Init(&EXTI_InitStructure);. c# F7 I3 D3 N. t/ c$ M
-
* m- V( C6 L( K% j1 S! y* v - NRF_CSN_H; //禁止NRF器件
/ H. x1 P0 K7 ]' C! K0 N$ A$ L - SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //双线全双工
* R7 I1 s B+ H. A$ i- J! C0 i - SPI_InitStructure.SPI_Mode = SPI_Mode_Master; //主模式
) |! o3 N% B$ }! C( F' E6 s - SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b; //数据大小8位 : I$ m# N$ Q B7 f7 s% D
- SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low; //时钟极性,空闲时为低 5 u! S0 A6 p* V- S5 R0 y
- SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge; //第1个边沿有效,上升沿为采样时刻 . Z; F& y" e" N7 j
- SPI_InitStructure.SPI_NSS = SPI_NSS_Soft; //NSS信号由软件产生
+ J) a/ Q; H5 b - SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_8; //8分频,9MHz
6 H3 V Q% O- e. n) M3 x9 u( T) } - SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB; //高位在前 , t5 G% D. ^! c8 T- h) @) V) D
- SPI_InitStructure.SPI_CRCPolynomial = 7; % [( x5 L+ }' A8 ]
- SPI_Init(SPI2, &SPI_InitStructure); 6 [! {% ~$ d; }' w
- [, A+ x/ F9 R- U! H" `
- SPI_Cmd(SPI2, ENABLE);//使能 SPI1, p9 Z5 h" p* W2 O7 J* d' ?
-
# c$ A) [% O* @, E, z0 n+ v - // PrintString("\r\n SPI2 初始化完成!");$ `7 ]9 @: r) H1 M/ Y7 A; v
- }
: ~* P/ l4 e6 H4 H# R - /******************************************************************************9 V( ^) V/ Z1 V, u! A
- 函数原型: uint8_t SPI_RW(uint8_t data)
4 q# [; o/ \) c9 x0 g7 R0 A+ U - 功 能: SPI总线读写+ R/ d8 {. z0 ^" v) T
- 返 回 值: 返回SPI总线读取数据
% j; c* k. e0 X U/ t. Y; k - *******************************************************************************/ # M/ P5 G/ {4 T8 m
- uint8_t SPI_RW(uint8_t data)
" ~: G5 J; p' P% T) o - { % s# C6 K/ h, P& e, L G
- while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_TXE) == RESET);//当SPI发送缓冲器非空时等待 . E4 z0 x/ ?2 i" s6 }& c' v5 _
- SPI_I2S_SendData(SPI2, data);//通过SPI总线发送一字节数据! f. P* l& d9 p* q7 L- a
- while (SPI_I2S_GetFlagStatus(SPI2, SPI_I2S_FLAG_RXNE) == RESET);//当SPI接收缓冲器为空时等待7 T% M6 k0 l. m: Y$ j, C
- return SPI_I2S_ReceiveData(SPI2);
3 x0 g# H+ u* V$ p8 P: m% Y - }) r1 k; h' a5 P4 h
- 6 v4 L, N* k! C' Y
- /******************************************************************************
9 x& q9 f1 P0 \ _5 W) ]( y - 函数原型: uint8_t NRF_Write_Reg(uint8_t reg, uint8_t value): G6 V; l! G7 ~- Z1 w* U
- 功 能: NRF写寄存器# O( T5 k* ?' F z2 a$ ~
- 返 回 值: NRF写寄存器返回值
/ h. I r: N1 e. b* v: @ - *******************************************************************************/: @. p q, o$ X
- uint8_t NRF_Write_Reg(uint8_t reg, uint8_t value)
2 i" D1 B9 C* F; D4 i - {: ?+ N& S p/ r% v+ U
- uint8_t status;
: H& h7 \- m, s. p" i# g - NRF_CSN_L; //选通NRF器件
' A* N' k& m. Y, g+ M+ \$ J1 v - status = SPI_RW(reg);//写寄存器地址2 ^. X" ~- ?& B3 Z
- SPI_RW(value); //写数据
( _1 Y$ r* y+ e' H% A - NRF_CSN_H; //禁止NRF器件
% y1 c" p" U. j' d! n - return status;7 k4 X. [! M6 f# o
- }" m) ~: P. @' C3 W% S# j1 |5 ^
6 \3 T& Q9 x9 m8 l, |) ?- /******************************************************************************
* ? F+ g) c% B+ }* a' S6 r - 函数原型: uint8_t NRF_Read_Reg(uint8_t reg)
; m5 v6 z. Q4 R# f' f6 y - 功 能: NRF读寄存器7 q0 A$ k& G% N2 p7 ~
- 返 回 值: 寄存器数据" [8 I. e1 x& Q0 R& k8 d# a/ [
- *******************************************************************************/
& p; E" }3 R6 ?/ |0 L - uint8_t NRF_Read_Reg(uint8_t reg)
1 @' m2 V: o5 o. n; e - {
" H2 F: ~- a3 I! @ - uint8_t reg_val;7 e2 N" v3 `- _: o' m
- NRF_CSN_L; //选通NRF器件
( m/ a- Y1 t; F# w - SPI_RW(reg); //写寄存器地址
6 p: N! L1 `; p# \ - reg_val = SPI_RW(0);//读取该寄存器返回数据% ]) P1 Z% ^( k/ ]' U7 g; e7 ^
- NRF_CSN_H; //禁止NRF器件 6 n f6 [7 H: ]& d
- return reg_val;: C3 N9 Z: ^9 f( c9 S5 Q
- }
5 L5 C) l& H1 p" z
" b9 y z' x4 X( j; z- /******************************************************************************' n4 Y4 g9 ~: _% X1 K: W3 R
- 函数原型: uint8_t NRF_Write_Buf(uint8_t reg, uint8_t *pBuf, uint8_t uchars)
7 N* ~9 E. s, T% O' {! K( u, X6 } - 功 能: NRF写缓冲区
& m' j8 v( }* z: Z8 e k - 返 回 值: NRF写缓冲区返回值3 g6 G$ o& V1 G* ^, L
- *******************************************************************************/! |$ r+ z7 C4 }# g2 o* g
- uint8_t NRF_Write_Buf(uint8_t reg, uint8_t *pBuf, uint8_t uchars)7 i% C" G6 J( i
- {9 i8 M3 S2 d* N
- uint8_t i;: U6 i6 d. i1 O$ V' {) N6 w, q
- uint8_t status;
2 b1 h4 u6 Z& B! S4 n4 y' o$ v9 x - NRF_CSN_L; //选通NRF器件 ' W- d4 G I, |/ D/ h; @* Z. j+ r
- status = SPI_RW(reg);//写寄存器地址 ( ~9 r* A3 m1 ?6 o" V
- for(i=0; i<uchars; i++)
. v# L- M, G+ m( g - {
) ], u. R+ G. e. Q, O - SPI_RW(pBuf[i]);//写数据 % a0 Z% J9 g1 @; v
- }
4 Q' s; C6 x3 _9 y# P - NRF_CSN_H; //禁止NRF器件
# H( m" O3 ]0 I& e! B* C2 H6 E* e - return status;
; L: J! f! C+ m6 L4 n0 B2 j - }
5 e# Q! B1 `) O* r2 Q" U3 c$ _
* y, W2 e, V* U- /******************************************************************************
$ T( z( s3 {& y7 T k; T* e6 I - 函数原型: uint8_t NRF_Read_Buff(uint8_t reg, uint8_t *pBuf, uint8_t uchars)5 ~, b+ e6 L4 B$ y
- 功 能: NRF读缓冲区! L- b2 m& x3 T/ q w
- 返 回 值: 缓冲区数据
$ ?* O% G: S2 V% m9 q# Q& _- O( A - *******************************************************************************/
6 G9 |! R/ u6 z3 e& a4 e( r - uint8_t NRF_Read_Buff(uint8_t reg, uint8_t *pBuf, uint8_t uchars)0 q. Z+ K3 t2 {8 k; p) F. c
- {, Y' F7 h$ D( Q/ W4 F* v; q Z2 P- e
- uint8_t i;' Q) e( A/ X" C# Z+ I: N
- uint8_t status;4 A x9 `/ c' X) k2 |: E
- NRF_CSN_L; //选通NRF器件
2 U! Q1 i; f6 ]# G - status = SPI_RW(reg);//写寄存器地址
$ R# y" W3 p7 q2 s3 p - for(i=0; i<uchars; i++)
' l. n q# G2 }) C& r: d - {+ t6 o5 }6 d; ]: j0 R- g) `0 `
- pBuf[i] = SPI_RW(0);//读取返回数据 9 z. _) j4 E7 a
- }, ?% I$ Z; s) k+ n; |0 E2 z
- NRF_CSN_H; //禁止NRF器件1 z% s1 z' K8 v
- return status;, s2 \- S% L7 [9 O, [! ?: K
- }$ [' }: e( t# l6 d% c9 r. L7 i. E
- : W# H- D6 S' w3 ]/ z, Z
- /******************************************************************************
- v% p! A% a; z+ q - 函数原型: void NRF24L01_Check(void)
+ B& A, H; O: R$ r# } - 功 能: 检查NRF器件是否正常: R( n: V; D* |0 Y; z' ?0 \0 g
- *******************************************************************************/' E& P$ O5 a; N& R1 F( w
- void NRF24L01_Check(void)
0 U6 [. }4 x0 `: P% I - { 3 l8 O0 a5 r. B1 l5 P
- uint8_t buf[5]; 9 @1 q0 N t% R) { |$ d
- uint8_t i; 3 n8 J6 e/ m4 ]5 c, C9 c0 j
- //写入5个字节的地址
( Y' M9 h. X) E - NRF_Write_Buf(NRF_WRITE_REG+TX_ADDR,TX_ADDRESS,5); 1 L, Q8 F, d2 E" }
- //读出写入的地址 . `( F+ Z% m: N3 Y
- NRF_Read_Buff(TX_ADDR,buf,5); ' i5 V: D8 g- ~( m% j
- //比较, n$ P+ @ L6 f1 D' w2 M7 u
- for(i=0;i<5;i++)
( ^( p9 g5 {# x5 b# J - { + U! T6 [1 Q& p( G4 r, ?! F' L
- if(buf[i]!=TX_ADDRESS[i])
) z& @- j3 i# D3 M8 I# B - break; 1 r. g+ i1 e, I3 @! H6 A' G
- } + \7 o/ K0 U0 U( E+ d8 i8 L" T
- // if(i==5)
% i; G* t) t( G$ p - // PrintString("\r\n NRF24L01 初始化成功!"); W9 i, b' B9 v/ s
- // else; D/ U5 z$ r. r! q8 P5 e6 A
- // PrintString("\r\n NRF24L01 初始化失败!");
! i1 G6 d3 G. a$ T8 m - }+ J2 ^* N9 l6 f3 Q: n, N' M
- ' R7 S0 C7 V* v0 h/ Q2 o6 V7 c
- /******************************************************************************8 f- v K1 d! H6 p# _' r
- 函数原型: static void NRF24L01_Set_TX(void)
& z' k2 P( q' q |/ N$ M - 功 能: 将NRF24L01设置为发送模式
" N. J5 K0 U6 H- _ - *******************************************************************************/. M, `* c: [9 z# H8 x, C2 a
- static void NRF24L01_Set_TX(void)+ Y$ a+ D/ ~6 M
- {4 W1 k0 d- B% J: p; s- p5 ~; [* q
- NRF_CE_L;1 k9 k8 z6 n7 Y
- NRF_Write_Reg(NRF_WRITE_REG + CONFIG,0x0E);//发送. u) P; x) `5 }" i
- NRF_CE_H;0 B* Q* v, s2 T Q6 x# T7 N
- }
6 x, ^; d0 M( Q0 i) u9 a+ x
, k4 f0 x, [" B/ `! x5 n, `- /******************************************************************************
1 _" a/ }6 v% m& v; ? - 函数原型: static void NRF24L01_Set_RX(void)
k5 @, t2 T) b+ Q# R/ }0 ^ - 功 能: 将NRF24L01设置为接收模式
, o( k z" Y: C# _ - *******************************************************************************/+ ~+ u4 ~" B5 @% A, d
- static void NRF24L01_Set_RX(void)
6 }3 {8 W7 _2 s R0 U# l - {
, S. b. O. Q5 B! c - NRF_CE_L;5 g' `+ W# b, y0 ?
- NRF_Write_Reg(NRF_WRITE_REG + CONFIG,0x0F);//接收
) I/ Z+ [! t5 w. B - NRF_CE_H;; F5 ]; E: n, G. Z
- }* {& ^# d) X) x
6 i0 V R. c. k9 A3 }2 ]. _- /******************************************************************************
7 G( B5 G8 @+ y, Z4 n - 函数原型: void NRF_Send_TX(uint8_t * tx_buf, uint8_t len)- j$ r/ n1 u! w% r8 }
- 功 能: NRF2401发送数据包% m3 H( b( F3 G, i- k
- *******************************************************************************/4 L% V- d, u) [
- void NRF_Send_TX(uint8_t * tx_buf, uint8_t len)9 f+ E% x! |' T! U+ u3 O5 H! B C
- {
4 o6 X2 K- [2 p; l4 r - NRF24L01_Set_TX();/ e) }* U) K) s7 j" x3 s+ I t6 J) t
- NRF_CE_L;//进入待机模式1 % z) }1 L* a3 m6 I! o
- NRF_Write_Buf(WR_TX_PLOAD, tx_buf, len);//装载数据- B1 V1 G# K9 y1 M4 _( k
- NRF_CE_H;//设置CE为高,启动发射。CE高电平持续时间最小为10us/ G- u) n7 H# L6 D* u2 C8 z7 {
- }0 i* y# ~9 P6 j4 y/ }$ I
- /******************************************************************************
" l2 e& I% [; }# o( u b8 q' |4 c2 R* o - 函数原型: void NRF24L01_Init(uint8_t Chanal,uint8_t Mode)
4 A5 J& x2 [* @- W+ W9 c - 功 能: NRF24L01初始化3 I% i: I4 f8 y7 m+ p8 V. ?% l
- 参 数: Chanal,RF通道* [$ D. w% W( H7 v, o& d6 n+ L' \
- *******************************************************************************/
. T4 p5 K3 P1 J1 o8 @ - void NRF24L01_Init(uint8_t Chanal,uint8_t Mode)- ^: E( [$ k- ]' X) W
- {
0 J8 l, f) g4 G* }( v# K# @6 g: O - NRF_CE_L;
; u. F4 n" {' I - 4 |9 u) q& a8 B) l. A3 o6 b- h9 q
- NRF_Write_Reg(FLUSH_TX,0xff);//清空发送缓冲区
i0 ^+ G# d$ @- g/ m" ?' s6 W - NRF_Write_Reg(FLUSH_RX,0xff);//清空接收缓冲区
& R: X3 x4 N& B# E" b U* b8 G - NRF_Write_Buf(NRF_WRITE_REG + TX_ADDR, TX_ADDRESS,5); //写TX节点地址
- S0 k2 z' n* T# r/ N m - NRF_Write_Buf(NRF_WRITE_REG + RX_ADDR_P0,RX_ADDRESS,5); //写RX节点地址
" F7 {2 y& P+ M+ z - 3 H" c7 v& k+ a6 C; T
- NRF_Write_Reg(NRF_WRITE_REG + EN_AA, 0x01); //使能通道0的自动应答
5 j( a Q* F5 f- n# ^0 v p/ L8 r r( x - NRF_Write_Reg(NRF_WRITE_REG + EN_RXADDR, 0x01); //使能通道0的接收地址
% U* ]7 K9 |- n3 p0 D* T2 S - NRF_Write_Reg(NRF_WRITE_REG + SETUP_RETR,0x1a); //设置自动重发间隔时间:500us;最大自动重发次数:10次 - N! `$ D2 U+ R1 |0 j
- NRF_Write_Reg(NRF_WRITE_REG + RF_CH, Chanal); //设置RF通道为CHANAL
. s/ K2 x6 u: B8 ^% x8 g - NRF_Write_Reg(NRF_WRITE_REG + RX_PW_P0, 32); //设置通道0的有效数据宽度2 C* `* g& B n a: b% M: W9 a0 j
- NRF_Write_Reg(NRF_WRITE_REG + RF_SETUP, 0x0f); //设置TX发射参数,0db增益,2Mbps,低噪声增益开启
8 S9 D( `# {9 J- R0 v9 { -
6 d; k3 [, h$ Z+ Y- I - if(Mode==TX)! i9 O9 i6 f! h d
- NRF_Write_Reg(NRF_WRITE_REG + CONFIG,0x0E);//发送: u! N2 H8 A1 ` J" w B7 y
- else if(Mode==RX)" k G; ?0 R( p1 [* H! ^9 T
- NRF_Write_Reg(NRF_WRITE_REG + CONFIG,0x0F);//接收5 R8 G4 U4 U& @4 N- a
-
; b( Y2 s9 c$ v+ | - NRF_CE_H;9 L* \# E6 k5 S! W9 q4 A9 k
- }+ Z) ?7 ^0 ~2 a8 b- R; C
- 0 l3 R, P& L5 o* [1 H! A+ W
- /******************************************************************************' C$ {# k& Z: @, E
- 函数原型: static void NRF24L01_Analyse(void)* J4 i# M& M8 U# s& ?( i
- 功 能: 分析NRF24L01收到的数据帧3 u8 Z3 B! e) N4 B
- *******************************************************************************/! b- o2 e4 X9 _/ D0 C# @
- static void NRF24L01_Analyse(void)7 Z! E+ Z% ?: o, \, H+ m
- {8 p1 N8 C1 K! P. r
- uint8_t sum = 0,i;
7 c5 ?- g: a( Y' H3 R7 E$ v - uint8_t len = NRF24L01_RXDATA[3] + 5;
; K8 j$ I- c# _ - //uint8_t i=0;6 a5 e+ W7 H- q/ p
- for(i=3;i<len;i++)
3 R5 f3 f# G1 S/ U( i- d. t - sum ^= NRF24L01_RXDATA[i];
. A' w) m( I, o, Z - if( sum!=NRF24L01_RXDATA[len] ) return; //数据校验
9 D3 }" s- {3 P2 ~; q; v: Q - if( NRF24L01_RXDATA[0] != '[font=微软雅黑][size=3]2.SPI_NRF24L01.h[/size][/font]
1 ~ b% E6 y e% h - [code]<font face="微软雅黑" size="3">#ifndef _SPI_NRF24L01_H_9 _# d" \2 X3 k' J
- #define _SPI_NRF24L01_H_
& c! W% h* ^( `3 {* U - #include "stm32f10x.h"1 s; b' Q# D$ q! m
" B* x1 j5 O: c3 }- /******************************************************************************1 b! @0 T- s+ |9 e2 W
- 宏定义2 T0 e5 r4 t6 x* x
- *******************************************************************************/ 0 v( d9 z' ^* g
- #define TX 1
% r( Y" p! @1 U - #define RX 2 {4 H5 q3 c, S" W5 U
- ; P3 E2 g9 S3 @" c% v$ ^
- #define RX_DR 6 //接收数据中断.当接收到有效数据后置一。写‘1’清除中断。
! j! A5 V: z' F( U5 V8 u& a - #define TX_DS 5 //数据发送完成中断。当数据发送完成后产生中断。如果工作在自动应答模式下,只有当接收到应答信号后此位置一。写‘1’清除中断。 / ~# Z( g7 K! ~& ^% h0 n
- #define MAX_RT 4 //达到最多次重发中断。写‘1’清除中断。如果MAX_RT中断产生则必须清除后系统才能进行通讯。8 G' _7 i" w) e7 n; G5 x
- #define TX_FULL 0 //TX FIFO寄存器满标志。 1:TX FIFO 寄存器满 0: TX FIFO 寄存器未满, 有可用空间。 % n) J* j5 W# {' h0 z9 z. G1 M
: l6 H$ M O% e$ U, H6 k- /******************************************************************************* v/ G7 ]& |0 r/ o% h$ N' c
- 全局变量声明' m7 L2 X7 f) Y. [0 `
- *******************************************************************************/ 0 M( y Y* C) B) `. y
- extern uint8_t NRF24L01_RXDATA[32];//nrf24l01接收到的数据) {: }; j( F7 r" P
- extern uint8_t NRF24L01_TXDATA[32];//nrf24l01需要发送的数据, `$ Q( M/ i9 o+ h4 ]
* j- G, W$ c1 `/ }5 h5 l; D- V- /******************************************************************************: C f+ D6 X. `! f" h% n2 i/ W
- 全局函数声明0 `8 k* v! u) Y C& R
- *******************************************************************************/
; x% O4 W2 {* V. g - void SPI2_Init(void);
" e, Y: n/ D' U! W - void NRF24L01_IRQ(void);
. Y. s; @3 p- l0 g* u7 {; D* j - void NRF24L01_Check(void);; Q$ x5 ~ `2 ^9 H4 F! D- _
- void NRF24L01_Init(uint8_t Chanal,uint8_t Mode);$ S$ }' c. _, V, e" H
- void NRF_Send_TX(uint8_t * tx_buf, uint8_t len);
6 x; r5 I2 p% ]0 s: L* W - void Nrf_Connect(void);# a; j9 A! K3 E& }1 j" J! J
- $ i8 S% ?+ f" ]3 `' \6 o7 h: E) D0 C
- uint8_t NRF_Read_Reg(uint8_t reg);
: f! D- y9 n C! K. C) B - uint8_t NRF_Write_Reg(uint8_t reg, uint8_t value);5 Q& Q& n4 ]# i5 `; }. @9 p1 \
- uint8_t NRF_Read_Buff(uint8_t reg, uint8_t *pBuf, uint8_t uchars);
3 _# [2 b; L" c6 g
8 h7 D8 D. }$ z7 B4 ~) ?" g9 ]4 n9 d6 |& F- /******************************************************************************
% G) [/ }# ~1 d7 [ - NRF24L01寄存器指令
0 c' A/ ^7 F9 f& c - *******************************************************************************/
5 O/ W C9 G7 ~4 d - #define NRF_READ_REG 0x00 // 读寄存器指令
2 u% J$ a* I+ T* t+ s - #define NRF_WRITE_REG 0x20 // 写寄存器指令
Y* i2 h! W1 [6 _: a$ h. U6 ^ - #define ACTIVATE 0x50 // follow with 0x73 to activate feature register- j9 r9 E. K- K5 _
- #define R_RX_PL_WID 0x60 // 读接收缓冲区的长度
4 c, Z& o& }2 x" F" G0 m - #define RD_RX_PLOAD 0x61 // 读取接收数据指令& ?! i. D$ s2 U+ ?
- #define WR_TX_PLOAD 0xA0 // 写待发数据指令% t, h' Q( V9 r- G0 ?6 s
- #define W_ACK_PAYLOAD 0xA8 // Used in RX mode.' I2 e% C: k: M
- #define FLUSH_TX 0xE1 // 冲洗发送 FIFO指令
{1 c( q2 b$ v0 `% O - #define FLUSH_RX 0xE2 // 冲洗接收 FIFO指令
8 C/ V- R$ @9 o) M; x( r - #define REUSE_TX_PL 0xE3 // 定义重复装载数据指令5 \6 ~4 `3 Q/ u) }4 y/ }" O. c
- #define NOP 0xFF // 保留, h9 p% G9 L- X+ f, H8 \; c
- /******************************************************************************! y4 l0 m' z S" I
- NRF24L01寄存器地址# u, _/ ^' n/ W- x
- *******************************************************************************/
" J5 n N9 m) V- c9 X - #define CONFIG 0x00 // 配置收发状态,CRC校验模式以及收发状态响应方式, l- u4 |; Z6 j" c) v7 I( R: c* X
- #define EN_AA 0x01 // 自动应答功能设置$ O b u7 m( ]& V
- #define EN_RXADDR 0x02 // 可用信道设置# G, L& U7 W( i7 i- U3 v: T
- #define SETUP_AW 0x03 // 收发地址宽度设置
1 m/ @, u x3 v1 S7 v - #define SETUP_RETR 0x04 // 自动重发功能设置
4 W2 \! n4 i. [1 `4 H - #define RF_CH 0x05 // 工作频率设置
/ q3 n2 Y: K$ H - #define RF_SETUP 0x06 // 发射速率、功耗功能设置9 v8 C" T% p, p" x1 Q( E
- #define NRFRegSTATUS 0x07 // 状态寄存器. q+ N* c9 ]; s1 P" F
- #define OBSERVE_TX 0x08 // 发送监测功能
, W9 s% j+ ?3 C2 k1 Y9 f - #define CD 0x09 // 地址检测
( F+ ?4 \* w1 x - #define RX_ADDR_P0 0x0A // 频道0接收数据地址
: F1 m( O5 T* V1 N! K5 a - #define RX_ADDR_P1 0x0B // 频道1接收数据地址
; |; Q% X9 T# `0 k; N4 N - #define RX_ADDR_P2 0x0C // 频道2接收数据地址; b. H( p" d Y; S1 U
- #define RX_ADDR_P3 0x0D // 频道3接收数据地址+ H3 m; M7 K' a/ b% R
- #define RX_ADDR_P4 0x0E // 频道4接收数据地址/ B, \9 e1 I# D1 p
- #define RX_ADDR_P5 0x0F // 频道5接收数据地址
' [0 @. W- l0 f; z/ {9 L) l' c2 S, b - #define TX_ADDR 0x10 // 发送地址寄存器2 v e+ |; i/ [9 x, ~9 K9 \+ P
- #define RX_PW_P0 0x11 // 接收频道0接收数据长度
& j3 e- n: x* B c - #define RX_PW_P1 0x12 // 接收频道1接收数据长度
1 F) u p6 H3 E$ K/ m6 y - #define RX_PW_P2 0x13 // 接收频道2接收数据长度
$ C3 Y; o3 {$ p2 @# E. \; W' v6 d - #define RX_PW_P3 0x14 // 接收频道3接收数据长度; K) F( i. P9 D$ d( y( n
- #define RX_PW_P4 0x15 // 接收频道4接收数据长度
! U0 z+ K6 @- _8 F* X( d0 {0 w3 _- x - #define RX_PW_P5 0x16 // 接收频道5接收数据长度
X5 S- M# F, X7 s% L - #define FIFO_STATUS 0x17 // FIFO栈入栈出状态寄存器设置$ R i/ ]; a9 |
- 6 X! c, z# ]0 t
- #define DYNPD 0x1C // per pipe DPL control 4 e3 ] B W& s. @( O
- #define FEATURE 0x1D // “Feature” register address ' Q7 T) }% J: b2 C! S& P; G4 ?
- 6 l$ _" c$ L2 k! q. j4 n. g( U
- #endif$ b9 V, h8 |8 h; T
- </font>
复制代码 3.Struct.h
* @, L9 u) V6 a6 ]5 g- G L- <font face="微软雅黑" size="3">#ifndef _STRUCT_H_ a5 p, s! O1 |* m! A2 a
- #define _STRUCT_H_$ Z) z8 U5 T& S y
7 V4 o8 |0 A u- #include "stm32f10x.h"9 [2 X4 p! f7 i" C1 f8 z* J
- #include "Led.h"; O8 D8 A( {" B+ N) k
- #include "SPI_NRF24L01.h"
& A5 u& q+ @+ g; f1 N y1 E3 a* o - #include "Uart.h"* e, q0 g! E" A J
- , O! Q5 E0 m/ F' V: q( I
- #endif
2 T: x$ b- s7 r/ g7 X0 A - </font>
复制代码 4.main.c- K1 C9 S9 b( B
- <font face="微软雅黑" size="3">#include "Struct.h"
4 \: Z5 v' |/ P$ \. G; r* f - : g4 A$ X0 i# h- D+ x+ d
- int main(void)- i) K0 v- W8 O/ K6 O
- {
) ]. K0 r1 A- a1 h6 c5 Z - SPI2_Init(); //SPI2初始化 ^. E1 Y1 O# t' ^
- NRF24L01_Init(35,TX);//2401选择35通道,发送模式" s0 R9 f! Q0 t6 |; g9 }
- NRF24L01_Check();//检测2401是否正常
4 O r7 X4 `/ T: n& i8 |9 x4 T - PrintString("\r\n HEELO QST! \r\n");% S1 B) `) L, N. L$ e4 f0 v3 M
- }
4 j9 X9 ?' o% Y: n1 q - </font>
复制代码
" c- r- I+ G9 p' I q: n1 g3 }1 N: a1 |+ f, r( k( U
总结
3 u. c, y' }# |( Q, x以上就是今天要讲的内容,本文仅仅简单介绍了基于STM32F103C8T6在Keil下编程实现NRF24L01实现无线传输的原理图和代码。9 D2 d. I2 E5 h0 S9 I( L2 A, m$ u( \" ?
1 h( E# z/ G5 T! x" g% q% ?
) return; //数据校验$ G% I' b' X# C: g4 d
if( NRF24L01_RXDATA[1] != 'M' ) return; //数据校验. [* ]& s7 D& w) x
if( NRF24L01_RXDATA[2] != '>' ) return; //MWC发送给上位机的标志
) ^0 N6 M( l0 t! Q) b0 p// LEDGreen_ON;
@* u0 L v+ b- p! H// if( NRF24L01_RXDATA[4] == MSP_FLY_DATA )//功能桢标志; _3 A7 H! R+ K/ g0 w' @/ ^$ \* Q
// {" p" x# B. @: z; J% w1 }
// Battery_Fly =( (uint16_t)(NRF24L01_RXDATA[6]) << 8 ) | NRF24L01_RXDATA[5];
c% p) c) `4 Q. r8 ^+ d3 V# L// THROTTLE1 = ( (uint16_t)(NRF24L01_RXDATA[8]) << 8 ) | NRF24L01_RXDATA[7];0 n4 \8 J: s' b& f, a5 Z [
// THROTTLE2 = ( (uint16_t)(NRF24L01_RXDATA[10]) << 8 ) | NRF24L01_RXDATA[9];
* `3 u+ d, c- G// THROTTLE3 = ( (uint16_t)(NRF24L01_RXDATA[12]) << 8 ) | NRF24L01_RXDATA[11];
& N4 C* C$ U* C7 ?, |// THROTTLE4 = ( (uint16_t)(NRF24L01_RXDATA[14]) << 8 ) | NRF24L01_RXDATA[13]; 7 X: m& a2 [; R. B
// pid[0].kp = NRF24L01_RXDATA[15];
( ^- Z& e/ f. X6 c; t// pid[0].ki = NRF24L01_RXDATA[16];
8 T* c A& Q A" @* |3 C// pid[0].kd = NRF24L01_RXDATA[17];
& L7 C# s; ^! ]: C// & I' @! C3 b% ^& h4 I; ]
// pid[1].kp = NRF24L01_RXDATA[18];
6 n* h4 |' x+ }+ u+ T ]. j// pid[1].ki = NRF24L01_RXDATA[19];) M N" d I5 [; }4 Y
// pid[1].kd = NRF24L01_RXDATA[20];
8 x b" L) e' h2 _0 o% U7 D
( p# R2 ~/ P4 c; [1 f: h4 T: D. `// pid[2].kp = NRF24L01_RXDATA[21];/ u. \5 j* q) Q
// pid[2].ki = NRF24L01_RXDATA[22];
8 z& T# q5 |. Y( a# g8 z// pid[2].kd = NRF24L01_RXDATA[23];
; g3 t# S: F4 G1 g: `: w// 3 Y, y: E! ?" ?$ \) w# g
// for(i=3;i<10;i++)
- a9 h7 P& w$ T% }: ~9 t// {1 d7 w; x/ c. z$ N
// pid.kp=0;
( A/ d/ i; t7 R6 ?" o' W// pid.ki=0;+ {7 c5 r+ G' L9 @( [' Y# E
// pid.kd=0;8 B" n0 Q' Y0 `2 |7 [8 R
// }
9 O' n( Z/ T* y7 Q* L& @! _! e' [1 \// }: q9 a9 e' d* W* G; C; X, _1 j. m
// else if( NRF24L01_RXDATA[4] == MSP_RAW_IMU || NRF24L01_RXDATA[4] == MSP_ATTITUDE )//功能桢标志
/ W1 ^/ M! r9 P8 A// Uart_Send(NRF24L01_RXDATA,len+1);' z5 b( j! V" a5 Z# {) G
}
8 u8 T& _. J8 Q7 z- B& T9 Y" j1 ?) |
/******************************************************************************
5 k, c! {: [9 ?- t9 s函数原型: void NRF24L01_IRQ(void)' C' J, e2 ^2 j8 Q7 ]/ ~. L% x% E
功 能: NRF24L01中断
8 H, U2 j+ G9 u6 z: g*******************************************************************************/+ B+ s# A' X* D/ J) a0 k
void NRF24L01_IRQ(void)& l0 q8 j. i4 E! ]/ @
{
0 F, _3 L8 X' S( ]) i- ? uint8_t status = NRF_Read_Reg(NRF_READ_REG + NRFRegSTATUS);
4 J: w; D P. f$ e $ C& V* {4 A: W# C9 a6 l. _
if(status & (1<<RX_DR))//接收中断
/ [! i1 ?+ g6 a4 W {
6 q$ Z- l% Z* @; S% G) E/ X) u uint8_t rx_len = NRF_Read_Reg(R_RX_PL_WID);//收到数据长度
* M# O! P/ [" w/ G' B) m if(rx_len==32)9 Q: }) \7 K, ~" [; X* @
{) [# B3 N; l% W' h* W6 a; j) t
NRF_Read_Buff(RD_RX_PLOAD,NRF24L01_RXDATA,rx_len);//读取接收FIFO数据2 X6 p4 u p5 K# |% ]3 m6 ]0 F4 A, G
Nrf_Erro = 0;) e! a: f% Z" e/ l
}6 R A* T- t2 b+ J$ l$ }$ g
else
! O& i4 F9 [5 U! a4 z- |; i {) T" N+ l! O/ i% P! x+ J
NRF_Write_Reg(FLUSH_RX,0xff);//清空接收缓冲区. e) f" J, B& M. F' W' e9 N6 K
}
+ i; f0 C9 U2 h4 {) t }3 ]+ o3 b: c# m. g3 K5 v! V
if(status & (1<<MAX_RT))//达到最多次重发中断
2 g2 e. M# f% F: ~# P P/ L {
: O4 N& b& N- j" X if(status & (1<<TX_FULL))//TX FIFO 溢出
# A( n0 w' F2 d o: c8 l; N- E B( E2 z {
4 S' l+ G& ] Z( j: B8 t NRF_Write_Reg(FLUSH_TX,0xff);//清空发送缓冲区* c' k6 |2 w8 L v/ c, U
}2 s8 D9 e1 e- i3 x; N
}
3 K, i( O( {" u9 D: f4 U if(status & (1<<TX_DS))//发送完成/ y& M8 g- y( [" ~0 v/ |$ @
{
4 ^% _- W4 j/ |" E: l- {( c' I/ P NRF24L01_Set_RX();//设置Nrf2401为接收模式6 I2 j4 Y" z$ C3 H0 U2 M. ?) K, a
}2 V+ {5 Z: I( J9 |
NRF_Write_Reg(NRF_WRITE_REG + NRFRegSTATUS, status);//清除中断标志位
. {- A, c# V0 b/ [ {}1 x' k4 h/ a, y9 x9 o
+ e4 k) h3 C6 P+ m/******************************************************************************
, _% p" n- y! h9 S& ]. Y7 Q. q函数原型: void Nrf_Connect(void)
# k6 |# r* o5 l* I: ]) b# u/ E功 能: NRF24L01连接函数. _. Q& f; b; Y4 p. F
*******************************************************************************/
* k$ ` B& w& @7 D6 `9 Ovoid Nrf_Connect(void)//500HZ
, u* [3 ~9 L5 P- }) p9 t* Q9 Z+ w7 A& L{, u+ T. ~$ l+ h: U& [9 \- [
Nrf_Erro++;
0 U- c5 F+ Q! k7 d$ z if(Nrf_Erro==1)! }$ p2 T: B% V) {- b/ [1 }/ }7 u
{
B, I% E! w/ g- z# g6 G NRF24L01_Analyse();//分析NRF24L01收到的数据帧$ V9 k0 @; b5 `9 m2 ~: F0 I
}' a+ C/ n, a- ]: |1 \; r
if(Nrf_Erro%50==0)//0.1s未接收nrf数据 ,试图连接飞控
3 }0 U2 _2 s) T" }4 r { 2 r) l5 L. H0 ?( I! S
NRF24L01_IRQ();//清除中断标志位3 A z6 W" x, o
}
" c6 [/ n2 E1 s$ \) G2 z if(Nrf_Erro>=500)//1s未接收nrf数据 ,关闭绿色LED指示灯
4 f& Y+ R( b; r3 v% _' P& g. O# h/ a {
! g( `2 ]8 n( n \" m f8 I// LEDGreen_OFF;4 Y1 T* s0 Z* B$ M! d7 d1 m; p
Nrf_Erro = 1;6 J, }9 M2 [% Y2 v' k5 S
// Battery_Fly = 0;0 b! h/ }( {/ O( o' z
}" p3 D, A* D8 o$ z. `6 a" h
}
& l- `: R2 K; z</font>[/code]2.SPI_NRF24L01.h
~) T: Y7 |& ^& W+ r$ n1 {- <font face="微软雅黑" size="3">#ifndef _SPI_NRF24L01_H_$ ^3 w. E7 }# D% U2 t; c' h2 x( E x
- #define _SPI_NRF24L01_H_
; L+ [& {# b$ E) ? - #include "stm32f10x.h"! O7 w0 d4 ?* n9 G4 G3 T7 x
- ( l4 n& G: z+ i& ]/ o. A1 m
- /******************************************************************************
2 f/ Y* r0 g- O% M, u: W - 宏定义
$ E) @ i* Z7 i3 T. B - *******************************************************************************/
, `) U9 v, M3 R0 N/ W ] - #define TX 19 d- |; T2 ~; y7 c9 U
- #define RX 2
, b+ Q( j1 W/ q, I$ s - # |' S) i ]1 r- X* f5 L
- #define RX_DR 6 //接收数据中断.当接收到有效数据后置一。写‘1’清除中断。
, p! x" m) {& _+ m$ P6 i2 v - #define TX_DS 5 //数据发送完成中断。当数据发送完成后产生中断。如果工作在自动应答模式下,只有当接收到应答信号后此位置一。写‘1’清除中断。
' N( J: e3 a9 M; j3 U! H2 I - #define MAX_RT 4 //达到最多次重发中断。写‘1’清除中断。如果MAX_RT中断产生则必须清除后系统才能进行通讯。
8 ?6 `1 p6 X. y& j - #define TX_FULL 0 //TX FIFO寄存器满标志。 1:TX FIFO 寄存器满 0: TX FIFO 寄存器未满, 有可用空间。
, V0 u3 ]& Y, N+ V( u
# o% H& q% A% ^$ N5 p' I$ Q- /******************************************************************************
! a" [- E+ t: Q' H4 P& y - 全局变量声明6 W+ I( U5 J8 O. [8 _: j7 }- t9 n
- *******************************************************************************/ ( u. Z( R5 L6 i% L% V4 @; `
- extern uint8_t NRF24L01_RXDATA[32];//nrf24l01接收到的数据0 A0 D% Y% _! W! X4 R
- extern uint8_t NRF24L01_TXDATA[32];//nrf24l01需要发送的数据. U' F( E) A; Z) b
- # g6 G+ Y3 Y" G, B
- /******************************************************************************
8 b% m: S$ V5 D2 s' k+ Y - 全局函数声明1 ?9 U+ q0 V, ?$ A" N2 A4 D
- *******************************************************************************/
) F( S* _, k j- }( ` - void SPI2_Init(void);
r+ Y. D) z6 s - void NRF24L01_IRQ(void);0 B# S5 S* J; I8 z& s
- void NRF24L01_Check(void);* [/ n+ B( I3 ~ G1 @; Y7 I
- void NRF24L01_Init(uint8_t Chanal,uint8_t Mode);
8 |' V, y" O" [1 k$ S$ [* d# C - void NRF_Send_TX(uint8_t * tx_buf, uint8_t len);/ I, x8 o5 a) @; \% c/ _7 ^8 i
- void Nrf_Connect(void);
" L" \/ R$ K' a4 P6 m! }) \8 D - 8 A: p0 G- }1 f$ R. i
- uint8_t NRF_Read_Reg(uint8_t reg);3 l y0 X, {" D' D
- uint8_t NRF_Write_Reg(uint8_t reg, uint8_t value);" O3 R6 ?" E( v. u
- uint8_t NRF_Read_Buff(uint8_t reg, uint8_t *pBuf, uint8_t uchars);6 K$ F' }: s2 {; i. G+ \( [
( T8 t- j- T; V! N- /******************************************************************************/ I! e9 @8 a0 y
- NRF24L01寄存器指令$ l1 G+ A5 W8 s# Q9 n
- *******************************************************************************/
( K' I) n* a# X3 v ~$ @" R6 Q - #define NRF_READ_REG 0x00 // 读寄存器指令) ^ B- P3 ]/ B% J0 i) E+ `8 J4 K
- #define NRF_WRITE_REG 0x20 // 写寄存器指令8 F1 X: M8 E( Z5 F
- #define ACTIVATE 0x50 // follow with 0x73 to activate feature register
7 |9 B2 Z" l, V$ m( ~) n- l - #define R_RX_PL_WID 0x60 // 读接收缓冲区的长度( y2 y2 r$ R, y; ]0 L
- #define RD_RX_PLOAD 0x61 // 读取接收数据指令$ V1 T8 J3 ^9 b; S4 w9 q: g
- #define WR_TX_PLOAD 0xA0 // 写待发数据指令
: I* ~% U3 I0 e. y) r - #define W_ACK_PAYLOAD 0xA8 // Used in RX mode.
J# ]) |: o4 r$ w9 S1 d, B* g7 H' z - #define FLUSH_TX 0xE1 // 冲洗发送 FIFO指令# w. h' }0 P: A9 W; Q3 ]; E
- #define FLUSH_RX 0xE2 // 冲洗接收 FIFO指令
5 O, R2 D, p! B; d- B% T9 | - #define REUSE_TX_PL 0xE3 // 定义重复装载数据指令
, L$ T2 F$ u( v2 O% j - #define NOP 0xFF // 保留
! w: N! P3 n& [: ], P) P& P6 | - /******************************************************************************
u! i" F' q6 X6 a& E# A/ J - NRF24L01寄存器地址
1 x) B/ A+ O, M4 }1 |6 _ - *******************************************************************************/ 5 W+ s5 F5 R! y" j
- #define CONFIG 0x00 // 配置收发状态,CRC校验模式以及收发状态响应方式- `+ \ ?8 {5 ?, N+ s
- #define EN_AA 0x01 // 自动应答功能设置
+ A+ s. B6 \+ D. W4 ^0 ]. y - #define EN_RXADDR 0x02 // 可用信道设置4 P/ y, ~6 r% ?" R' p9 B2 G
- #define SETUP_AW 0x03 // 收发地址宽度设置! x1 ~5 b5 ?7 n/ r: S2 \
- #define SETUP_RETR 0x04 // 自动重发功能设置
0 d' w* J7 b( v; L, u: \ - #define RF_CH 0x05 // 工作频率设置
- e3 p* N7 g& ]2 d( d4 z) { - #define RF_SETUP 0x06 // 发射速率、功耗功能设置
8 V# h0 W1 J3 X: B! K9 X3 O - #define NRFRegSTATUS 0x07 // 状态寄存器) M( l% D0 B: L+ W( ~8 |" l+ J, i
- #define OBSERVE_TX 0x08 // 发送监测功能' Z$ v L! u0 x8 U; c/ K1 `
- #define CD 0x09 // 地址检测 , ]5 {7 k# S+ `% a- g0 T9 }
- #define RX_ADDR_P0 0x0A // 频道0接收数据地址
! b' q& O: n R& e7 i; v; Q - #define RX_ADDR_P1 0x0B // 频道1接收数据地址
' x3 }' U! b2 Q/ a% _* t# i, g. ] - #define RX_ADDR_P2 0x0C // 频道2接收数据地址
2 `4 u1 }3 `3 U, M5 ~- W - #define RX_ADDR_P3 0x0D // 频道3接收数据地址
' z4 [ O: q6 C3 c - #define RX_ADDR_P4 0x0E // 频道4接收数据地址
9 n7 Z- C- X# M: [, d6 Q/ ^' e - #define RX_ADDR_P5 0x0F // 频道5接收数据地址( n% O, p& j+ |6 a# P2 v f
- #define TX_ADDR 0x10 // 发送地址寄存器
9 X+ x5 F! a+ O - #define RX_PW_P0 0x11 // 接收频道0接收数据长度# N6 U1 j- t" m8 E
- #define RX_PW_P1 0x12 // 接收频道1接收数据长度) L6 p( {+ W& m8 c9 Q
- #define RX_PW_P2 0x13 // 接收频道2接收数据长度* G V* V D4 `1 h9 b' s5 ~
- #define RX_PW_P3 0x14 // 接收频道3接收数据长度
7 z, h z# w2 A7 I; [ - #define RX_PW_P4 0x15 // 接收频道4接收数据长度" N2 C5 Q) i+ r# e7 E3 _" b: Y
- #define RX_PW_P5 0x16 // 接收频道5接收数据长度4 i4 v ^6 u1 R- A
- #define FIFO_STATUS 0x17 // FIFO栈入栈出状态寄存器设置
; w: o* z9 J6 x$ E& U - % V' c! [1 B! C6 ]7 k- h7 g2 K
- #define DYNPD 0x1C // per pipe DPL control
9 O% ^. W0 n* J6 l% Y - #define FEATURE 0x1D // “Feature” register address
- @6 s/ d9 N' M: k- z -
1 E- B) {# a4 L+ _, L. s, X% E - #endif) Q7 N* \ t+ O
- </font>
复制代码 3.Struct.h8 C: C8 G' X3 c3 m% h& a
- <font face="微软雅黑" size="3">#ifndef _STRUCT_H_
1 g9 {9 }' R- w - #define _STRUCT_H_& Y: }4 k% b6 Z! ^, N) i$ X( n
- 0 w7 R' s- k2 U( ~" f+ s
- #include "stm32f10x.h"
0 T# K3 h/ p2 u; O - #include "Led.h"
9 A `# L. P7 I& m$ m; w - #include "SPI_NRF24L01.h"
8 L& ^; w( |5 O - #include "Uart.h"
/ l' R. P; S! ^7 g( j, C
4 m% D+ J. @) c5 a+ ]- #endif. L- ^9 d8 k; F0 Q
- </font>
复制代码 4.main.c
0 e$ O' N J. C- <font face="微软雅黑" size="3">#include "Struct.h"8 j7 L# ^/ d0 o- F7 @5 ^' I! m
^9 K* }; o3 ]% m4 l- int main(void)
) D8 m# A l% e5 @7 B - {1 P8 }! u9 q. q
- SPI2_Init(); //SPI2初始化# W$ G, a2 a' ?3 {
- NRF24L01_Init(35,TX);//2401选择35通道,发送模式
; N' a; ~1 |3 c9 l3 O5 f* F - NRF24L01_Check();//检测2401是否正常
( n, r! A5 Z/ R - PrintString("\r\n HEELO QST! \r\n");# S6 O+ a! V4 M& {# ?
- }
" r0 r$ b- F" G$ {9 P4 N - </font>
复制代码 # D( T" o5 W& ~
; K! Y% g0 P I7 B总结: W) j* ?; \4 a! j3 E! b/ U* @2 y
以上就是今天要讲的内容,本文仅仅简单介绍了基于STM32F103C8T6在Keil下编程实现NRF24L01实现无线传输的原理图和代码。
, d5 E r7 Q0 f3 e9 u
6 H5 r6 [: s+ h |