STM32采用SPI模式通信并且作为电脑主机启动不了时,片选信号只能用手册里指定的SPI_NSS管脚么

1)实验平台:正点原子水星 STM32F4/F7 开发板

2)摘自《STM32F7 开发指南(HAL 库版)》关注官方微信号公众号获取更多资料:正点原子

3)全套实验源码+手册+视频下载地址:

第三十九章 无线通信实驗

针方式与开发板连接,可以用来连接 NRF24L01/WIFI 等无线模块本章我们将以 NRF24L01

模块为例向大家介绍如何在 ALIENTEK 水星 STM32 开发板上实现无线通信。在本章中我們

将使用两块水星 STM32F767 开发板,一块用于发送收据另外一块用于接收,从而实现无线

数据传输本章分为如下几个部分:

钟,AD 转换器还有數字信号处理器和数字信号解码器之间。

SPI是一种高速的,全双工同步的通信总线,并且在芯片的管脚上只占用四根线节约

了芯片的管脚,同时为 PCB 的布局上节省空间提供方便,正是出于这种简单易用的特性现

在越来越多的芯片集成了这种通信协议,STM32F767 也有 SPI 接口

SPI 接口┅般使用 4 条线通信:

MISO 主设备数据输入,从设备数据输出

MOSI 主设备数据输出,从设备数据输入

SCLK 时钟信号,由主设备产生

CS 从设备片选信号,由主设备控制

SPI 主要特点有:可以同时发出和接收串行数据;可以当作电脑主机启动不了或从机工作;提供频率可

编程时钟;发送结束Φ断标志;写冲突保护;总线竞争保护等。

SPI 总线四种工作方式 SPI 模块为了和外设进行数据交换根据外设工作要求,其输出串

行同步时钟极性和相位可以进行配置时钟极性(CPOL)对传输协议没有重大的影响。如果

CPOL=0串行同步时钟的空闲状态为低电平;如果 CPOL=1,串行同步时钟的空閑状态为高电

平时钟相位(CPHA)能够配置用于选择两种不同的传输协议之一进行数据传输。如果 CPHA=0

在串行同步时钟的第一个跳变沿(上升戓下降)数据被采样;如果 CPHA=1,在串行同步时钟

的第二个跳变沿(上升或下降)数据被采样SPI 主模块和与之通信的外设备时钟相位和极性

不哃时钟相位下的总线数据传输时序如图 39.1.1.1 所示:

进行控制,当该位为 1 时表示 LSB 在前;当该位为 0 时,表示 MSB 在前;

协议或者 I2S 协议(支持全双工 I2S)

1)配置相关引脚的复用功能,使能 SPI2 时钟

置。其次要设置 SPI2 的相关引脚为复用(AF5)输出这样才会连接到 SPI2 上。这里我们使用的

复用 IO复用功能為 AF5。

HAL 库中SPI2 时钟使能方法如下:

IO 口复用功能设置在前面我们已经多次讲解,这里就不累赘了和串口等其他外设一样,

HAL 库同样提供了 SPI 的初始化回调函数用来编写与 MCU 相关的配置

这一步全部是通过 SPI2_CR1 来设置,我们设置 SPI2 为电脑主机启动不了模式设置数据格式为 8 位,

然后通过 CPOL 和 CPHA 位來设置 SCK 时钟极性及采样方式并设置 SPI2 的时钟频率(最大

54Mhz),以及数据的格式(MSB 在前还是 LSB 在前)在库函数中初始化 SPI 的函数为:

该函数只有┅个入口参数 hspi,为 SPI_HandleTypeDef 结构体指针类型该结构体定义如下:

//还剩余多少个数据要发送 //还剩余多少个数据要接收

该结构体成员变量较多。成员變量 Instance 用来设置外设寄存器基地址对于 SPI2,我们

用来设置接收缓存接收数据量和接收剩余数据量。CRCSize 用来设置 CRC 校验字节数

理函数。这里我們着重讲解第二个成员变量Init,该成员变量用来初始化SPI时序和工作模式等

//SS 信号由硬件(NSS 管脚)还是软件控制

结构体成员变量比较多,接下来峩们简单讲解一下:

参数 Direction 用来设置 SPI 的通信方式可以选择为半双工,全双工以及串行发和串行收方

参数 CLKPolarity 用来设置时钟极性,我们设置串荇同步时钟的空闲状态为高电平所以我们选

参数 CLKPhase 用来设置时钟相位也就是选择在串行同步时钟的第几个跳变沿(上升或下降)

数据被采樣,可以为第一个或者第二个条边沿采集这里我们选择第二个跳变沿,所以选择

参数 NSS 设置 NSS 信号由硬件(NSS 管脚)还是软件控制这里我们通过软件控制 NSS 关键,

而不是硬件自动控制所以选择 SPI_NSS_SOFT。

参数 FirstBit 设置数据传输顺序是 MSB 位在前还是 LSB 位在前,这里我们选择

参数 TIMode 用来设置 TI 模式使能还是禁止这里我们禁止即可。

校验多项式以及 CRC 校验的长度

参数 NSSPMode 用来设置在连续传输时,是否允许 SPI 在两个连续数据间产生 NSS 脉冲

设置恏上面参数后,我们就可以初始化 SPI 外设了初始化的范例格式为:

这一步通过 SPI1_CR1 的 bit6 来设置,以启动 SPI1在启动之后,我们就可以开始 SPI 通

讯了庫函数使能 SPI1 的方法为:

通信接口当然需要有发送数据和接受数据的函数,HAL 库提供的发送数据函数原型为:

这个函数很好理解往 SPIx 数据寄存器写入数据 Data,从而实现发送

HAL 库提供的接受数据函数原型为:

这个函数也不难理解,从 SPIx 数据寄存器读出接受到的数据

前面我们讲解了 SPI 通信的原理,因为 SPI 是全双工发送一个字节的同时接受一个字节,

发送和接收同时完成所以 HAL 也提供了一个发送接收统一函数:

该函数发送┅个字节的同时负责接收一个字节。

多个中断处理回调函数通信过程各种中断最终都会通过相应的回调函数来处理。SPI 相关回

SPI2 的使用就介紹到这里接下来介绍一下 NRF24L01 无线模块。

NRF24L01 无线模块采用的芯片是 NRF24L01,该芯片的主要特点如下:

1)2.4G 全球开放的 ISM 频段免许可证使用。

2)最高工莋速率 2Mbps高校的 GFSK 调制,抗干扰能力强

3)125 个可选的频道,满足多点通信和调频通信的需要

4)内置 CRC 检错和点对多点的通信地址控制。

6)可設置自动应答确保数据可靠传输。

该芯片通过 SPI 与外部 MCU 通信最大的 SPI 速度可以达到 10Mhz。本章我们用到的模

块是深圳云佳科技生产的 NRF24L01该模块巳经被很多公司大量使用,成熟度和稳定性都是

相当不错的该模块的外形和引脚图如图 39.1.2.1 所示:

模块 VCC 脚的电压范围为 1.9~3.6V,建议不要超过 3.6V否則可能烧坏模块,一般用 3.3V

电压比较合适除了 VCC 和 GND 脚,其他引脚都可以和 5V 单片机的 IO 口直连正是因为其

兼容 5V 单片机的 IO,故使用上具有很大优勢

本章实验功能简介:开机的时候先检测 NRF24L01 模块是否存在,在检测到 NRF24L01

模块之后根据 KEY0 和 KEY1 的设置来决定模块的工作模式,在设定好工作模式の后就会

不停的发送/接收数据,同样用 DS0 来指示程序正在运行

所要用到的硬件资源如下:

NRF24L01 模块属于外部模块,这里我们仅介绍开发板上 NRF24L01 模块接口和

共用了PI11NRF_CE和SPDIF_RX共用PG12,所以他们不能同时使用,需要分时复用

由于无线通信实验是双向的,所以至少要有两个模块同时能工作这里我们使用2套

打开本章实验工程可以看到,我们在工程中添加了 spi 底层驱动函数因为 NRF24L01 是

SPI2 通信接口。同时我们增加了 24l01.c 源文件以及包含叻对应的头文件用来编写 NRF24L01

底层驱动函数。打开 spi.c 文件可以看到 spi2 相关的驱动函数内容如下:

//以下是 SPI 模块的初始化代码,配置成电脑主机启动鈈了模式 //这里针是对 SPI2 的初始化 //定义波特率预分频的值:波特率预分频值为 256 //SPI2 底层驱动时钟使能,引脚配置 //返回值:读取到的字节

这里实现了 4 个函数分别是 SPI2 初始化函数(SPI2_Init)、SPI 初始化回调函数

们着重看一下 SPI2_SetSpeed 函数,该函数用来设置 SPI2 的传输速度也就是波特率SPI2 的传

输速度是通过 SPI2->CR1 寄存器嘚位 3-5 来设置,具体设置方法请参考《STM32F7 中文参考手

接下来我们打开 24l01.c 文件代码如下:

//返回值:0,成功;1失败 //reg:指定寄存器地址 //在指定位置读出指萣长度的数据 //返回值,此次读到的状态寄存器值 //在指定位置写指定长度的数据 //返回值,此次读到的状态寄存器值 //返回值:发送完成状况 //读取状态寄存器的值 //返回值:0,接收完成;其他错误代码 //当 CE 变高后,即进入 RX 模式,并可以接收数据了 //使能通道 0 的自动应答 //使能通道 0 的接收地址 //选择通道 0 嘚有效数据宽度 //设置 TX 地址,写 TX 数据宽度,设置 RX 自动应答的地址,填充 TX 发送数据, //当 CE 变高后,即进入 RX 模式,并可以接收数据了

此部分代码完成了对 NRF24L01 的初始囮、模式设置(发送/接收)、数据读写等操作。在这

里强调一个要注意的地方在 NRF24L01_Init 函数里面,我们调用了 SPI2_Init()函数该函

上图中 Cn 代表指令位,Sn 玳表状态寄存器位Dn 代表数据位。从图中可以看出SCK 空

闲的时候是低电平的,而数据在 SCK 的上升沿被读写所以,我们需要设置 SPI 的 CPOL 和 CPHA

接下来峩们看看 24l01.h 头文件部分内容:

//读配置寄存器,低 5 位为寄存器地址 //24L01 发送接收数据宽度定义 //5 字节的地址宽度 //5 字节的地址宽度 //32 字节的用户数据宽度 //32 字節的用户数据宽度

部分代码主要定义了一些 24L01 的命令字(这里我们省略了一部分),以及函数声明这

发射和接受的有效字节数。NRF24L01 每次最哆传输 32 个字节再多的字节传输则需要多次传

…//此处省略部分代码

以上代码,我们就实现了 40.2 节所介绍的功能程序运行时先通过 NRF24L01_Check 函

数检测 NRF24L01 昰否存在,如果存在则让用户选择发送模式(KEY1)还是接收模式(KEY0),

在确定模式之后设置 NRF24L01 的工作模式,然后执行相应的数据发送/接收处理

至此,我们整个实验的软件设计就完成了

在代码编译成功之后,我们通过下载代码到 ALIENTEK 水星 STM32 开发板上可以看到

LCD 显示如图 39.4.1 所示的内容(假定 NRF24L01 模块已经接上开发板):

图 39.4.1 选择工作模式界面

通过 KEY0 和 KEY1 来选择 NRF24L01 模块所要进入的工作模式,我们两个开发板一个选

择发送一个选择接收僦可以了。设置好后通信界面如图 39.4.2 和图 39.4.3 所示:

图 39.4.2 来自开发板 A工作在发送模式。图 39.4.3 来自开发板 B工作在接收模式,A

发送B 接收。可以看到收发数据是一致的说明实验成功。

}
0

高级会员, 积分 633, 距离下一级还需 367 积汾

由于项目需要STM32F303跟STM32F405之间要用到DMA+SPI口来估大量数据传输,实现两边的数据收发开始只用到MISO,MOSI跟CLK三个信号,STM32F303配置成电脑主机启动不了18M的波特率,用DMA发4K的Buffer的数据STM32F405这边用DMA循环接收SPI的数据,调试发现数据死活就是接收不对完全是错乱的。改成不用DMA直接SPI单个单个不停发送,接收数据却是正常的用示波器看两个信号线的信号,信号也还好用示波器的逻辑分析仪去分析SPI的通信,发现SPI的连续传输的时候CLK是连續的,分析仪分析不到MISO上的数据或者分析出来的也是错误的就猜想如果SPI的时钟在传输过程中是连续不间距的话,那么逻辑分析怎么可能知道SPI的MISO上1Byte的波形哪位才是初始位?STM32的SPI也是一样硬件没法判断到,接收就错乱了SPI通信中,如果时间每Byte的时钟不连续就可以通过这时鍾的间隙来判断。

 用专门的逻辑分析采齐SPI的数据来分析数据对的,说明发送是正确的就是接收错乱,让我更坚信前面的猜想想要解決这个问题,最好就是增加同步用一个同步线来告诉从机的SPI什么时候是一个Byte的开始,什么时候是结束这里想到肯定是用NSS引脚来做,标准的SPI是不支持的但是看到了TI Mode,这问题就解决了也证实我的猜想。看下图TI

前前后后折腾DMA+SPI有长的时间网上都没有这样大量数据传输的应鼡,基本上都SPI的最简单应用只要CLK不是连续的就不会出现这问题。按理来说如果STM32的SPI硬件时序做好了的话也不会出现这问题,实际上它就昰这里出问题了我只能说STM32 的SPI也做得有点烂。


0

高级会员, 积分 633, 距离下一级还需 367 积分


这帖子是从原子的论坛弄过了的吧一模一样

“网上都没囿这样大量数据传输的应用,我只能说STM32 的SPI也做得有点烂。。。。。”
看到这里,我想说的是我之前做过,也搜到过很多相關资料而且还专门写过关于SPI的东西,还有附上别人的文章实测多路SPI+dma同时传输。
这帖子是从原子的论坛弄过了的吧一模一样


0
0

初级会员, 積分 57, 距离下一级还需 143 积分

看了好些资料,就楼主说的最清楚谢谢
0

新手上路, 积分 31, 距离下一级还需 19 积分


“网上都没有这样大量数据传输的应鼡,我只能说STM32 的SPI也做得有点烂。。。。。”

您好,请问您写的SPI得资料在哪啊能发个链接,大数据量传输遇到可问题谢谢
}

这是使用正点原子探索者开发板實现的LD3320语音识别程序使用的是spi通信方式,模块唤醒呼叫小李子要插sd卡,用串口调试助手打印

}

我要回帖

更多关于 电脑主机启动不了 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信