前面已经总结过STM32Fxx的特点和传输过程,下面以nRF24L01+ 2.4GHz无线收发器为例,来说明如何使用SPI。

一、nRF24L01+ 2.4GHz无线收发器的介绍

1. 主要特性

  • 全球2.4GHz ISM频段操作
  • 250Kbps, 1Mbps, 2Mbps三种空中传输速率
  • 超低功耗
  • 输出功率为 0dBm时发射功耗为11.3mA
  • 空中传输速率为2Mbps时接收功耗为13.5mA
  • Power down模式功耗低至900nA, Standby-I模式功耗低至26uA
  • 1.9~3.6V的电压工作范围
  • 支持6个接收通道(地址)
  • IO口能承受5V电压
  • ±60ppm 16MHz晶体振荡器
  • 4×4mm QFN封装

2. SPI操作时序

2.1 读操作时序图

图1. nRF24L01+ 读操作时序

①:发送指令+寄存器地址,都是从CSN(片选线,下同)的下降沿开始

②:主机(即STM32F4xx,下同)发送8位指令代码(C7~C0,下同)

③:不管主机发送何指令,从机(即nRF24L01+,下同)第一字节都会返回状态寄存器的值(寄存器0x07)

④:从机数据在每一个SCK的上升沿输出,首先输出的是第一字节(最低字节)的最高位,...,最后输出的是最高字节的最低位

⑤:读取操作都是以CSN的上升沿结束

2.2 写操作时序

图2. nRF24L01+ 写操作时序

①:同读操作

②:同读操作

③:同读操作

④:主机数据在每一个SCK的上升沿写入从机,首先写入的是第1个字节的最高位,...,最后写入的是最后一个字节的最低位

⑤:同读操作

2.3 状态机

图3. nRF24L01+ 状态图

  • Power Down 模式

在该模式下,nRF24L01+的功耗最小,不能进行发送或者接收。但是所有寄存器的值保持不变,SPI处于有效状态,允许对寄存器,TX/RX FIFO进行操作,PWR_UP(此位在CONFIG寄存器中)清0即进入该状态。

  • Standby-I 模式

将PWR_UP置1,即进入Standby-I模式,该模式既降低了nRF24L01+的平均功耗,同时又保持尽可能短的启动时间,将CE置1然后后清0,就可以进入TX/RX模式,然后又返回到Standby-I模式。

  • Standby-II 模式

当nRF24L01+设置为接收机(PTX),并且CE=1,TX FIFO为空时即进入该模式。相比Standby-I模式,这种模式相对耗电,一旦发送FIFO有新数据,就会立即将数据打包发送出去。

  • TX 模式

进入该模式需要满足以下条件:

  • PWR_UP=1
  • PRIM_RX=0
  • TX FIFO不为空
  • CE=1脉冲宽度超过10us
  • RX 模式

进入该模式需要满足以下条件

  • PWR_UP=1
  • PRIM_RX=1
  • CE=1

二、程序实现

根据上面nRF24L01+的时序,结合前面介绍的STM32F4xx SPI的操作小结,SPI设置成全双工收发模式,NSS(片选引脚)单独用一个IO口来控制,对nRF24L01+读写操作程序如下:

1. SPI发送/接收子函数

 1 /* SPI 发送*/
2 void _SPIDataSet(SPI_TypeDef * SPIx, unsigned char *Buf, unsigned char Cnt)
3 {
4 for(; Cnt; Cnt--)
5 {
6 while((SPIx -> SR & SPI_SR_TXE) != SPI_SR_TXE);
7 SPIx -> DR = *Buf++;
8 }
9 while(SPIx -> SR & SPI_SR_BSY);
10 Cnt = SPIx -> DR;
11 }
12
13 /* SPI 接收*/
14 void _SPIDataGet(SPI_TypeDef * SPIx, unsigned char *Buf, unsigned char Cnt)
15 {
16 for(; Cnt; Cnt--)
17 {
18 while((SPIx -> SR & SPI_SR_TXE) != SPI_SR_TXE);
19 SPIx -> DR = 0xFF;
20 while((SPIx -> SR & SPI_SR_RXNE) != SPI_SR_RXNE);
21 *Buf++ = SPIx -> DR;
22 }
23 24 }

L6:写入数据前必须保证TX缓存器为空

L9:确保最后一位数据发送完毕

L10:使RXNE位清0(对DR进行读操作,将使RXNE清0),若RXNE若置1,SPI不会接受新数据。

L19:由于SPI工作与全双工模式,即发送1位数据才会接收1位数据,此语句本质是让SPI输出SCK,使nRF24L01+输出数据

L20: 确保接收到完整的数据

2. 对nRF24L01+寄存器的读/写操作

 1 /* 写nRF24L01+ 寄存器 */
2 void DataSet(unsigned char CMD, /* 寄存器地址 */
3 unsigned char *Val, /* 发送数据指针 */
4 unsigned char Cnt /* 数据数量 */)
5 {
6 nRF24L01_CSN = 0;
7 _SPIDataSet(SPI1, &CMD, 1);
8 _SPIDataSet(SPI1, Val, Cnt);
9 nRF24L01_CSN = 1;
10 }
11
12
13 /* 读nRF24L01+ 寄存器 */
14 void DataGet(unsigned char CMD, /* 寄存器地址 */
15 unsigned char *Buf, /* 接收数据指针 */
16 unsigned char Cnt /* 数据大小 */)
17 {
18 nRF24L01_CSN = 0;
19 _SPIDataSet(SPI1, &CMD, 1);
20 _SPIDataGet(SPI1, Buf, Cnt);
21 nRF24L01_CSN = 1;
22 }

L6, L18: CSN的下降沿开始读/写操作

L9, L21: CSN的上升沿结束读/写操作

下图所示为通过逻辑分析仪抓取的设置nRF24L01+ pipe0接收地址(寄存器0xA)的波形:

图4. 设置Pipe0(寄存器0xA)接收地址波形

下图所示为通过逻辑分析仪抓取的读取nRF24L01+ pipe0接收地址(寄存器0xA)的波形:

图5. 读取Pipe0(寄存器0xA)接收地址波形

More~

1. 假如使用 Auto Acknowledgment 功能,发送端(PTX)Pipe0接收地址必须和发送地址     相同,这是用于接收接收端(PRX)的相应

2. 接收数据数量(最大32字节)必须写入RX_PW_Px寄存器(x为通道编号)

3. 调试失败,排查以下几点:

  • 硬件连接是否正确
  • 寄存器读写操作是否正确
  • 确保Standby-I/II 模式变换到TX 模式时,CE高电平时间足够(大于130us)
  • 发送端(PTX)和接收端(PRX)数据的大小要一致,比如接收端(PRX)接收数据大小设置为8字节,那么主机就要给发送端(PTX)的TX FIFO传输8个字节

/×××××××××××××××××××××××××××××××××××××××× THE END××××××××××××××××××××××××××××××××××××××××××××/

[STM32F4xx 学习] SPI与nRF24L01+的应用的更多相关文章

  1. [STM32F4xx 学习] SPI小结

    一.STM32F4xx系列的SPI特点: 1. 支持全双工的3线SPI模式(即SCK, MISO, MOSI) 2. 支持单工2线传输,同时数据线可以设置成单向或者双向模式 3. 8-bit, 16- ...

  2. STC8H开发(五): SPI驱动nRF24L01无线模块

    目录 STC8H开发(一): 在Keil5中配置和使用FwLib_STC8封装库(图文详解) STC8H开发(二): 在Linux VSCode中配置和使用FwLib_STC8封装库(图文详解) ST ...

  3. HAL驱动库学习-SPI

    如何使用SPI库1 声明SPI hanlde, 例如: SPI_HandleTypeDef hspi2 通过实现HAL_SPI_MspInit()函数初始化底层资源 以下两个必须进行初始化 a 使能s ...

  4. 读Dubbo源码,学习SPI

    核心类 ExtensionLoader 使用方法 定义接口,使用@SPI标记 @SPI("impl1") public interface SimpleExt { // @Adap ...

  5. [STM32F4xx 学习] 如何在RAM中调试程序

    在RAM中调试程序指的是将程序下载到RAM里面(而不是Flash里面),然后在RAM中执行程序.调试. 为什么要在RAM中调试程序?总结起来有以下两点原因: 1. Flash 擦写次数有限,STM32 ...

  6. Duboo学习-SPI

    待补充 现将Dubbo-SPI相关源码流程图更新

  7. 第24章 SPI—读写串行FLASH—零死角玩转STM32-F429系列

    第24章     SPI—读写串行FLASH 全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn 野火视频教程优酷观看网址:http://i.youku.com/ ...

  8. dubbo SPI设计

    SPI 全称为 Service Provider Interface,是一种服务发现机制.SPI 的本质是将接口实现类的全限定名配置在文件中,并由服务加载器读取配置文件,加载实现类.这样可以在运行时, ...

  9. STM32F030 使用硬件 SPI

    前言 以前玩过一点 STM32 单片机(主要是 STM32F103 系列),去年(2017)STM32F1 涨到不知哪里去了,今年好像降下来了.F0 系列相比 F1 系列少了一些功能,最高主频只到 4 ...

随机推荐

  1. Java Record 的一些思考 - 默认方法使用以及基于预编译生成相关字节码的底层实现

    快速上手 Record 类 我们先举一个简单例子,声明一个用户 Record. public record User(long id, String name, int age) {} 这样编写代码之 ...

  2. Windows库函数获取 可执行程序所在路径

    头文件 #include <Windows.h> 函数 函数已经写好了 std::string get_executable_dir_() { char path[255] = { 0 } ...

  3. F. Geometrical Progression

    http://codeforces.com/problemset/problem/758/F F. Geometrical Progression time limit per test 4 seco ...

  4. 【授课录屏】JavaScript高级(IIFE、js中的作用域、闭包、回调函数和递归等)、MySQL入门(单表查询和多表联查)、React(hooks、json-server等) 【可以收藏】

    一.JavaScript授课视频(适合有JS基础的) 1.IIFE 2.js中的作用域 3.闭包 4.表达式形式函数 5.回调函数和递归 资源地址:链接:https://pan.baidu.com/s ...

  5. Differential Evolution: A Survey of the State-of-the-Art

    @ 目录 概 主要内容 DE/rand/1/bin DE/?/?/? DE/rand/1/exp DE/best/1 DE/best/2 DE/rand/2 超参数的选择 的选择 的选择 的选择 一些 ...

  6. DEEP DOUBLE DESCENT: WHERE BIGGER MODELS AND MORE DATA HURT

    目录 概 主要内容 Effective Model Complexity(EMC) label noise data augmentation 下降方式 SGD vs Adam Adam SGD SG ...

  7. 【jvm】06-new一个对象到底占了多少内存?

    [jvm]06-new一个对象到底占了多少内存? 欢迎关注b站账号/公众号[六边形战士夏宁],一个要把各项指标拉满的男人.该文章已在github目录收录. 屏幕前的大帅比和大漂亮如果有帮助到你的话请顺 ...

  8. springboot单元测试为什么排除junit-vintage-engine

    https://blog.csdn.net/Ber_Bai/article/details/117001443 如果不排除,就需要使用@RunWith注解? 25-springboot整合单元测试指定 ...

  9. 更便捷的Mybatis增强插件——EasyMybatis

    easy-mybatis是一个对Mybatis的增强框架(插件).在Spring集成Mybatis的基础上,将项目开发中对数据库的常用操作统一化.使用本框架可以很便捷的对数据库进行操作,提高开发效率, ...

  10. 关于PaddleSharp GPU使用 常见问题记录

    在安装NVIDIA驱动过程中遇到一系列问题,记录如下! 附上PaddleSharp地址,大家喜欢可以关注 根据PaddleSharp官方说明需要安装驱动如下 CUDA 和 cuDNN 和 Tensor ...