SPI通信外设

SPI外设介绍

在这里插入图片描述
时钟频率就是SCK波形的频率,一个SCK时钟交换一个bit,所以时钟频率一般体现的是传输速度,单位是Hz或者bit/s。可以看出来,SPI的时钟其实就是由pclk分频得来的,pclk就是外设时钟,APB2的PCLK就是72MHz,APB1的PCLK是36MHz。

注意事项:一是这个频率数值并不是任意指定的,它只能是PCLK执行分频后的数值就只有这八个选项。
二是SPI1和SPI2挂载的总线是不一样的,SPI1挂载在APB2,PCLK是72MHz,SPI1挂载在APB1,PCLK是36MHz,所以同样的配置,SPI1的时钟频率要比SPI2的大一倍。

兼容I2S协议:是一种数字音频信号专用协议、

SPI框图

在这里插入图片描述

在这里插入图片描述
接下来看一下SPI的框图,我们可以大致把它分成两部分,左上角这一部分就是数据寄存器和移位寄存器打配合的过程。然后剩下右下角这一部分,就是一些控制逻辑寄存器。

移位寄存器,右边的数据低位,一位一位的从MOSI移出去,然后MISO的数据一位一位的移入到左边的数据高位,显然移位寄存器应该是一个右移的状态,所以目前图上表示的是低位先行的配置。
对应右下角有一个LSBFIRST的控制位,这一位可以控制是低位先行还是高位先行。

这里LSBFIRST帧格式:给0先发送MSB,MSB就是高位的意思,给1先发送LSB ,LSB 就是低位的意思。那ppt这里目前的状态LSBFIRST的应该是1,低位先行。如果LSBFIRST给0,高位先行的话,这个图还要变动一下,就是移位寄存器变为左移,输出,从左边移出去,输入,从右边移进来,这样才符合逻辑。
主从模式引脚变换
在这里插入图片描述

然后继续看左边这一块,这里画了个方框,里面把MOSI和MISO做了个交叉,这一块主要是用来进行主从模式引脚变换的。我们这个SPI外设可以做主机,也可以做从机,做主机时这个交叉就不用,MOSI为MO,主机输出,MISO为MI,主机输入,这是主机的情况。

如果我们STM32作为从机的话,MOSI为SI,从机输入,这时他就要走交叉的这一路,输入到移位寄存器,同理MISO为SO,从机输出,这时输出的数据也走交叉的这一路输出到MISO。

接收发送缓冲区
在这里插入图片描述

接收发送缓冲区,这两个缓冲区实际上就是数据寄存器DR,下面发送缓冲区就是发送数据寄存器TDR,上面接收缓冲区就是接收数据寄存器RDR,TDR和RDR占用同一个地址,统一叫做DR。

写入DR时,数据写入到TDR,读取DR时,数据从RDR读出,数据寄存器和移位寄存器打配合,可以实现连续的数据流。

具体流程:比如我们需要连续发送一批数据,第一个数据写入到TDR,当移位寄存器没有数据移位时,TDR的数据会立刻转入移位寄存器,开始移位,这个转入时刻,会置状态寄存器的TXE为1,表示发送寄存器空,当我们检查TXE置1后,紧跟着下一个数据就可以提前写入到TDR里侯着了,一旦上个数据发完,下一个数据就可以立刻跟进,实现不间断的连续传输。然后移位寄存器,这里一旦有数据过来了,它就会自动产生时钟将数据移出去,在移出的过程中,MISO的数据也会移入,一旦数据移出完成,数据移入也完成了,这时移入的数据就会整体的从移位计算器,转入到接收缓冲区RDR,这个时刻会置状态寄存器器的RXNE为1,表示接收计寄存器器非空。当我们检查RXNE置1后,就要尽快把数据从RDR读出来,在下一个数据到来之前,读出RDR就可以实现连续接收。否则如果下一个数据已经收到了,上个数据还没从RDR读出来,那RDR的数据就会被覆盖,就不能实现连续的数据流了。

右下角是一些控制逻辑,首先是波特率发生器,这个主要就是用来产生SCK时钟的,它的内部主要就是一个分频器,输入时钟是PCLK72M或36M,经过分频器之后输出到SCK引脚,当然这里生成的时钟肯定是和移位寄存器同步的,每产生一个周期的时钟移入移出一个bit。

BR位
在这里插入图片描述

然后右边CR1寄存器的三个位BR0、BR1、BR2,用来控制分频系数。手册这里看到BR[2:0] 是波特率控制,这三位写入下面这些值,可以对PCLK时钟执行2~ 256的分频,分频之后就是SCK时钟,所以这一块就对于来之前这里说的时钟频率是fpclk的2~256分频,那这就是波特率发生器的部分。
各种寄存器
在这里插入图片描述

LSB FIRST,决定高位先行还是低位先行。
SPE是SPI使能,就是SPI_Cmd函数配置的位。
BR配置波特率,就是SCK时钟频率。
MSTR(Master),配置主从模式,1是主模式,0是从模式,我们一般用主模式
CPOL和CPHA,用来选择SPI的四种模式。
SR状态寄存器,TXE发送寄存器空,RXNE接收寄存器非空,这两个比较重要,我们发送接收数据的时候需要关注这两位。
CR2寄存器,是一些使能位,比如中断使能,DMA使能等。

NSS引脚
在这里插入图片描述

NSS引脚,SS就是从机选择,低电平有效,所以这里前面加了个n,SS引脚我们直接使用一个GPIO模拟就行,因为SS引脚很简单,就置一个高低电平就行了。而且从机的情况下,ss还会有多个。

I2C基本结构

在这里插入图片描述
在这里插入图片描述

移位寄存器,是左移,高位移出去,通过GPIO到MOSI,从MOSI输出,显然这是SPI的主机。
之后引入的数据从MISO进来,通过gpio到移位寄存器的低位,这样循环八次,就能实现主机和从机交换一个字节,然后TDR和RDR的配合,可以实现连续的数据流。

另外TDR数据,整体转入移位寄存器的时刻,置TXE标志位。移位寄存器数据整体转入RDR的时刻,置RXNE标志位。

波特率发生器,产生时钟输出到SCK引脚。

数据控制器,看成是一个管理员,它控制着所有电路的运行。

开关控制就是SPI_Cmd,初始化之后,给个ENABLE,初始化整个外设。

SS从机选择引脚,另外这里并没有画SS从机选择引脚,这个引脚我们还是使用普通的GPIO来模拟即可。在一主多从的模型下,GPIO模拟的SS是最佳选择,这就是SPI的简化的结构。

主模式全双工连续传输

在这里插入图片描述
非连续传输的好处,就是容易封装好理解好用,但是会损失一丢丢性能;连续传输呢传输更快,但是操作起来相对复杂,那我们来分别具体分析一下。

首先第一行是SCK时钟线,这里CPOLl=1,CPHA=1,示例使用的是SPI模式3,所以SCK默认是高电平,然后在第一个下降沿MOSI和MISO移出数据,之后上升沿引入数据,依次这样来进行。

第二行是MOSI/MISO输出的波形,跟随SCK时钟变化,数据位依次出现,这里从前到后依次出现的是b0~b7 ,所以这里示例演示的是低位先行的模式,实际SPI高位先行用的多一些。

第三行是TXE发送寄存器空标志位,波形是这样的,等会儿再分析。

第四行,是发送缓冲器(写入SPI_DR),实际上就是这里的TDR

第三五是BSY, busy是由硬件自动设置和清除的。当有数据传输时,busy置1。

那上面这部分演示的就是输出的流程和现象。

然后下面是输入的流程和现象。

MISO/MOSI(输入),之后是RXNE接收数据寄存器非空标志位,最后是接收缓冲器(读出SPI_DR)。

发送的流程
在这里插入图片描述

我们来从左到右依次分析,首先SS置低电平,开始时序,在刚开始时TXE为1,表示TDR空,可以写入数据开始传输,然后下面指示的第一步就是软件写入0xF1至SPI_DR,0xF1就是要发送的第一个数据,之后看到写入之后TDR变为0xF1 ,同时TXE变为0,表示TDR已经有数据了,那此时TDR是等候区,移位寄存器才是真正的发送区。
移位寄存器刚开始肯定没有数据,所以在等候区TDR里的F1 ,就会立刻转入移位寄存器开始发送,转入瞬间置TXE标志位为1,表示发送寄存器空,然后移位寄存器有数据了,波形就自动开始生成,

数据转入移位寄存器之后,数据F1的波形就开始产生了,在移位产生F1波形的同时,等候区TDR是空的,为了移位完成时,下一个数据能不间断的跟随,这里我们就要提早把下一个数据写入到TDR里等着了。

所以下面第二步的操作,是写入F1之后,软件等待TXE=1,在这个位置,一旦TDR空了,我们就写入F2至SPI_DR,写入之后可以看到TDR的内容就变成F2了,也就是把下一个数据放到TDR里候着。

之后的发送流程也是同理,最后在这里如果我们只想发送三个数据,F3转入移位寄存器之后,TXE=1,我们就不需要继续写入了,TXE之后一直是1,注意在最后一个TXE=1之后,还需要继续等待一段时间,F3的波形才能完整发送完,等波形全部完整发送之后,busy的标志由硬件清除,这才表示波形发送完成了,那这些就是发送的流程。

接收的流程
在这里插入图片描述

接收的流程:SPI是全双工,发送的同时还有接收,所以可以看到在第一个字节发送完成后,第一个字节的接收也完成了,接收到的数据1是A1 ,这时移位寄存器的数据整体转入RDR,RDR随后存储的就是A1 ,转入的同时按RXNE标志位也置1,表示收到数据了。
我们的操作是下面这里写的,软件等待RXNE=1表示收到数据了,然后从SPI_DR也是RDR读出数据A1 ,这是第一个接收到的数据,接收之后软件清除RXNE标志位,然后当下一个数据2收到之后,RXNE重新置1,我们监测到RXNE=1时,就继续读出RDR,这是第二个数据A2 。
最后在最后一个字节时序完全产生之后,数据3才能收到,所以数据3,直到这里才能读出来,

然后注意,一个字节波形收到后,移位寄存器的数据自动转入RDR,会覆盖原有的数据,所以我们读出RDR要及时,比如A1这个数据收到之后,最迟你也要在这里把它读走,否则下一个数据A2覆盖A1,就不能实现连续数据流的接收了,这是整个发送和接收的流程这个交换的流程。这个连续传输,对效率要求很高,否则的话,我们更推荐下面这个非连续传输。

非连续传输
在这里插入图片描述

在这里插入图片描述

那我们看一下这个非连续传输和连续传输,有什么区别呢,

首先这个配置还是spi模式三,sck默认高电平,发送数据时如果检测到TXE=1了,TDR为空,就软件写入0xF1至SPI_DR,这时TDR的值变为F1,TXE变为0,目前移位寄存器也是空,所以这个F1会立刻转入移位寄存器,开始发送,波形产生并且,TXE置回1,表示你可以把下一个数据放在TDR里侯着了。

但是现在区别就来了,在连续传输这里,一旦TXE等于1了,我们就会把下个数据写到TDR里侯着这样是为了连续传输数据衔接更紧密,这样的话,流程就比较混乱,程序写起来比较复杂。

所以在非连续传输这里,TXE等于1了,我们不着急把下一个数据写进去,等待第一个字节时序结束,意味着接收第一个字节也完成了,这时接收的RXNE会置1。我们等待RXNE置1后,先把第一个接收到的数据读出来,之后再写入下一个字节数据,也就是这里的(软件等待TXE等于1,但是较晚写入0xf2SPI_DR),较晚写入TDR后,数据2开始发送,我们还是不着急写数据3,等到了这里,先把接收的数据2收着,再继续写入数据3。
数据3时序结束后,最后再接收数据3置换回来的数据。

我们的整个步骤:第一步等待TXE为1,第二步写入发送的数据至TDR,第三步等待RXNE为1,第四步读取RDR接收的数据,之后交换第二个字节,重复这四步。

非连续传输缺点
在这里插入图片描述

非连续传输缺点:就是在这个位置没有及时把下一个数据写入TDR候着,所以等到第一个字节时序完成后,第二个字节还没有送过来,那这个数据传输就会在这里等着,所以这里时钟和数据的时序,在字节与字节之间会产生间隙,拖慢了整体数据传输的速度这个间隙在SCK频率低的时候影响不大,但是在SCK频率非常高时,间隙拖后腿的现象就比较严重了,比如我这里用示波器看了一下,不同SCK频率间隙的影响。

不同SCK频率间隙的影响

256分频

在这里插入图片描述

这里有四个波形,SCK分频系数分别是264、128、28、56,先看一下最慢的,256分频,这个SCK频率是72M/26大概是280k。

图示上面是SCK信号,这里使用SPI模式0,所以默认低电平,下面是SS信号,低电平表示选中从机,这个波形是SPI非连续传输,交换五个字节的时序,SCK线,连续交换了五个字节,但是你几乎看不出字节与字节之间的间隙对,因为这个时钟频率比较慢,间隙时长也不大,所以在这个比较慢的波形看来,间隙对它的影响就可以忽略了。

128分频
在这里插入图片描述

这图是128分频,SCK频率大概560k,这时就更明显的看出来字节之间的间隙了,字节和字节之间并不是严丝合缝的,这会降低整体的字节传输速度。但这个比例上看,这一点点间隙也可以忽略不计的。

2分频
在这里插入图片描述
我们直接看一下最快的二分频,这个SCK时钟频率是72M/2=36M,频率非常快,已经超过这个示波器的采样频率,所以每个字节的时钟已经看不完整了。这里可以看到间隙所占的时间比例,已经是数据传输的好几倍了,不能忽略间隙。
如果你忽略了间隙,那计算一下二分频的数据传输速率,应该是256分频的128倍,当你实测一下,它肯定达不到这么高,所以通过看这个波形我们就清楚了,如果你想在极限频率下,进一步提高数据传输速率,追求最高性能,那最好使用连续传输的操作逻辑,或者还要进一步采用DMA自动转运,这些方法效率都是非常高的。

软硬件波形对比

在这里插入图片描述
软硬件波形对比,这里上面是软件波形,下面是硬件波形。

这些和I2C的软件件波形对比其实都是差不多的,首先他们的数据变化趋势肯定是一样的,采样得到的数据也是一样的,I2C所描述的scl低电平期间数据变化,高电平期间数据采样,与SPI的SCK下降沿数据移出,上升沿数据移入,最终波形的表现形式都是一样的。

区别就是硬件波形,数据线的变化是紧贴SCK边沿的,而软件波形数据线的变化,在边沿后有一些延迟。只是硬件波形一般会紧贴边缘,软件波形一般只能在电平期间,不过最终都不会影响数据传输,不过软件波形如果能贴近边缘,我们还是贴近边缘,否则如果你等太久比较靠近下一个边沿,那数据也容易出错。

数据手册

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/706117.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

重复文件怎么查找并清理?6种重复文件清理方法亲测好用!

重复文件怎么查找并清理?重复的文件会占用计算机中不必要的空间,从而降低计算机速度。这些文件是您设备上现有文件的副本。您可能有照片、视频、音频、档案、文档等的文件副本。因此,当电脑被这些文件占用运行速度时,你会迫切地希…

Java项目:111 基于SpringBoot的在线家具商城设计与实现

作者主页:舒克日记 简介:Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 项目介绍 本系统有管理员和用户两个角色,包括前台商城平台及后台管理系统。 前台商城系统包含首页门户、商品推荐、商品搜索、商品展示、购物车、订…

探索Java 8 Stream API:现代数据处理的新纪元

Stream流 Stream初探:何方神圣? Stream流是一种处理集合数据的高效工具,它可以让你以声明性的方式处理数据集合。Stream不是存储数据的数据结构,而是对数据源(如集合、数组)的运算操作概念,支…

❤vue2项目webpack打包的优化策略

❤ vue2项目webpack打包的优化策略 (优化前) 现在我们的打包时间为: >打包体积大小为: 1、去除开发环境和生产环境提示以及日志 开发环境和生产环境的打印处理 生产环境去除console.log打印的两种方式 通过环境变量控制co…

一张图读懂天然气气源

一张图读懂天然气气源

《pvz植物大战僵尸杂交版》V2.0.88整合包火爆全网,支持安卓、ios、电脑等!

今天来给大家安利一款让人欲罢不能的游戏——《植物大战僵尸杂交版》2.0.88版。这可不是普通的植物大战僵尸,它可是席卷了B站,火爆全网的存在! 先说说这个版本,它可是网络上现存最全的植物大战僵尸杂交版整合包。里面不仅有修改工…

tkinter文本对齐方式

tkinter文本对齐方式 文本对齐方式效果代码 文本对齐方式 左对齐(left):默认对齐方式,文本从左边界开始。右对齐(right):文本从右边界开始。居中对齐(center)&#xff1…

NVIDIA MPS详解

NVIDIA 文章目录 NVIDIANVIDIA MPS介绍一、MPS作用二、MPS实例MPS与Hyper-Q区别Pascal架构和Volta架构不同架构上的MPS实现MPS基准测试MPS的使用MPS组成MPS执行过程开启与关闭MPS Volta MPS资源配置公平性MPS程序示例编写开启MPS脚本编写执行程序编写关闭MPS脚本运行MPS脚本运行…

linux部署运维3——centos7.9离线安装部署配置涛思taos2.6时序数据库TDengine以及java项目链接问题处理(二)

上一篇讲了centos7.9如何安装涛思taos2.6时序数据库的操作步骤和方案,本篇主要讲解taos数据库的初始化,相关配置说明,数据库和表的创建问题以及java项目连接问题。 centos7.9如何离线安装taos2.6,请点击下方链接详细查看&#xf…

新疆在线测宽仪配套软件实现的9大功能!

在线测宽仪可应用于各种热轧、冷轧板带材的宽度尺寸检测,材质不限,木质、钢制、铁质、金属、纸质、塑料、橡胶等都可以进行无损非接触式的检测,在各式各样的产线应用中,有些厂家,需要更加详尽完备的分析信息&#xff0…

离散化——Acwing.802区间和

离散化 定义 离散化可以简单理解为将连续的数值或数据转换为离散的、有限个不同的值或类别。离散化就是将一个可能具有无限多个取值或在一个较大范围内连续取值的变量,通过某种规则或方法,划分成若干个离散的区间或类别,并将原始数据映射到…

【Go】用 Go 原生以及 Gorm 读取 SQLCipher 加密数据库

本文档主要描述通过 https://github.com/mutecomm/go-sqlcipher 生成和读取 SQLCipher 加密数据库以及其中踩的一些坑 用 go 去生成读取 SQLCipher 数据库用 gorm 去读取 SQLCipher 数据库在生成后分别用 DBeaver、db browser 和 sqlcipher 读取 SQLCipher 数据库,…

基于jeecgboot-vue3的Flowable流程-流程处理(二)

因为这个项目license问题无法开源&#xff0c;更多技术支持与服务请加入我的知识星球。 对应VForm3&#xff0c;原先的后端解析也要做调整 1、获取历史任务的表单信息 // 获取历史任务节点表单数据值List<HistoricVariableInstance> listHistoricVariableInstance his…

Python第二语言(十二、SQL入门和实战)

目录 1. Python中使用MySQL 1.1 pymysql第三方库使用MySQL 1.2 连接MySQL 1.3 操作数据库&#xff0c;创建表 1.4 执行查询数据库语句 2. python中MySQL的插入语句 2.1 commit提交 2.2 自动提交 3. pymysql案例 3.1 数据内容 3.2 DDL定义 3.3 实现步骤 3.4 文件操…

最小生成树kruskal算法详解

kruskal算法的思想简单来说就是&#xff1a;每次选择图中最小边权的边&#xff0c;如果边两端的顶点不在相同的连通块中&#xff0c;就把这条边加入到最小生成树中。 具体实现如下&#xff1a; 首先是边的定义&#xff0c;需要判断边的两个端点是否在不同的连通块中&#xff…

Vue前端ffmpeg压缩视频再上传(全网唯一公开真正实现)

1.Vue项目中安装插件ffmpeg 1.1 插件版本依赖配置 两个插件的版本 "ffmpeg/core": "^0.10.0", "ffmpeg/ffmpeg": "^0.10.1"package.json 和 package-lock.json 都加入如下ffmpeg的版本配置&#xff1a; 1.2 把ffmpeg安装到项目依…

深入探究MySQL游标(Cursor)

前言 MySQL游标&#xff08;Cursor&#xff09;是MySQL中用于处理查询结果的一种机制。游标允许我们在查询结果集中逐行处理数据&#xff0c;而不是一次性获取所有数据。这对于处理大量数据非常有用&#xff0c;因为它可以减少内存消耗并提高性能。在MySQL中&#xff0c;游标主…

【源码】【Spring+SpringMVC+MyBatis】电子商城网上购物平台的设计与开发

学生成绩管理系统 系统功能开发环境开发技术前端技术后端技术 系统展示登录界面注册界面系统首页商品详情页下单界面付款界面购物车界面 源码获取↓↓↓↓&#xff1a; 源码可在后台私信联系博主或文末添加博主微信获取帮助 系统功能 登录、注册模块&#xff1a;如果用户第一次…

udp协议下的socket函数

目录 1.网络协议 2.网络字节序 3.socket编译接口 4.sockaddr结构体 5.模拟实现 1.socket函数 2.bind函数&#xff08;绑定&#xff09; 1.讲解 1.如何快速的将 整数ip<->字符串 2.ip地址的注意事项 3.端口号的注意事项 3.recvfrom函数 4.sendto函数 5.代码呈…

C++ Primer 第五版 第16章 模板与泛型编程

模板是C中泛型编程的基础。一个模板就是一个创建类或函数的蓝图或者说公式。当使用一个vector这样的泛型类型&#xff0c;或者find这样的泛型函数时&#xff0c;我们提供足够的信息&#xff0c;将蓝图转换为特定的类或函数。这种转换发生在编译时。 一、定义模板 1. 函数模板…