STM32快速复习(八)SPI通信

文章目录

  • 前言
  • 一、SPI是什么?SPI的硬件电路?SPI发送的时序?
  • 二、库函数
  • 二、库函数示例代码
  • 总结


前言

SPI和IIC通信算是我在大学和面试中用的最多,问的最多的通信协议
IIC问到了,一般SPI也一定会问到。
SPI相对于IIC多了一个片选信号(CS)
SPI相对于IIC,最主要特点,传输速率增快,不需要等待下位机回复,有了片选信号,可以明确控制信号传输的单对单。所以,代码相对于IIC也简单一些。(很多时候,芯片不会有那么多的GPIO口给SPI用作片选信号)
IIC可以用两根线连接多设备,SPI需要再增加片选线,假如连接3个设备,IIC只需要2根通信线,SPI则需要(3+n)条线,n为设备数量,也就是6根线。
在这里插入图片描述


一、SPI是什么?SPI的硬件电路?SPI发送的时序?

SPI是什么?
SPI(Serial Peripheral Interface,串行外设接口)是由Motorola公司开发的一种通用数据总线,与IIC 差不多,也是为了实现主控芯片和各种外挂芯片之间的数据交流。SPI和IIC都是常用的接口协议,只是根据其不同的特点,应用场景有所不同。

SPI特点:SPI(Serial Peripheral Interface)是由Motorola公司开发的一种通用数据总线
四根通信线:SCK(Serial Clock)、MOSI(Master Output Slave Input)、MISO(Master Input Slave Output)、SS(Slave Select)
同步,全双工
支持总线挂载多设备(一主多从)

SPI没有应答机制

硬件特点(参考上图):所有SPI设备的SCK、MOSI、MISO分别连在一起
主机另外引出多条SS控制线,分别接到各从机的SS引脚
输出引脚配置为推挽输出,输入引脚配置为浮空或上拉输入

STM32的SPI电路:
STM32内部集成了硬件SPI收发电路,可以由硬件自动执行时钟生成、数据收发等功能,减轻CPU的负担
可配置8位/16位数据帧、高位先行/低位先行
时钟频率: fPCLK / (2, 4, 8, 16, 32, 64, 128, 256)
支持多主机模型、主或从操作
可精简为半双工/单工通信
支持DMA
兼容I2S协议

STM32F103C8T6 硬件SPI资源:SPI1、SPI2
在这里插入图片描述
在这里插入图片描述
***寄存器配合介绍: ***
**移位寄存器:**右侧的数据一位一位地从MOSI输出,MOSI的数据一位一位地移到左侧数据位。
LSBFIRST控制位:用于控制移位寄存器是低位先行(1)还是高位先行(0)。
MISO和MOSI的交叉:用于切换主从模式。不交叉时为主机模式,交叉时为从机模式。
接收缓冲区、发送缓冲区:实际上分别就是接收数据寄存器RDR、发送数据缓冲区TDR。TDR和RDR占用同一个地址,统一叫作DR。移位寄存器空时,TXE标志位置1,TDR移入数据,下一个数据移入到TDR;移位寄存器接收完毕(同时也标志着移出完成),RXNE标志位置1,数据转运到RDR,此时需要尽快读出RDR,以防止被下一个数据覆盖。
细节:SPI为全双工同步通信,所以为一个移位寄存器、两个缓冲区;IIC为单工通信,所以只需要一个移位寄存器、一个缓冲区;USRT为全双工异步通信,所以需要两个移位寄存器、两个缓冲区,且这两套分别独立。
***控制逻辑介绍: ***
波特率发生器:本质是一个分频器,用于产生SCK时钟。输入时钟就是外设时钟f =72MHz/36MHz。每产生一个时钟,就移入/移出一个比特。SPI_CR1中的[BR2,BR1,BR0]用于产生分频系数。
SPI_CR1:SPI控制寄存器1,下面简单介绍一下。详细可以参考中文数据手册“23.5 SPI和I2S寄存器描述”一节。
SPE(SPI Enable):SPI使能,就是SPI_Cmd函数配置的位。
BR(Baud Rate):配置波特率,也就是SCK时钟频率。
MSTR(Master):配置主机模式(1)、从机(0)模式。
CPOL、CPHA:用于选择SPI的四种模式。

简化后:
在这里插入图片描述
波特率发生器:用于产生SCK时钟。
数据控制器:根据配置,控制SPI外设电路的运行。
字节交换过程:交换完毕,移位寄存器空,则TXE位置1、RXNE位置1,TDR会自动转运数据到移位寄存器,RDR数据等待用户读取。
开关控制【代码】:SPI外设使能。
GPIO【代码】:用于各引脚的初始化。
从机使能引脚SS【代码】:并不存在于SPI硬件外设中,实际使用随便指定一个GPIO口(例如PA4)即可。在一主多从模式下,GPIO模拟SS是最佳选择。

在实际书写代码的过程中,使用一个结构体便可以直接配置 波特率发生器 和 字节交换的默认模式,这是SPI外设内部便会自动工作,用户额外需要关心的只是何时读写DR。下面介绍读写时序的流程,分别是性能更高、使用复杂的“主模式全双工连续传输”,以及性能较低、常用且简单易学的“非连续传输”:

不常用:
在这里插入图片描述
本模式可以实现数据的连续传输。
连续写入数据:只要TXE置1,就立马进中断写入数据(会同时清除TXE位);当写入到最后一个数据时,等待BSY位清除,发送流程完毕。
连续读出数据:只要RXNE位置1,就立马进中断读出数据(会同时清除RXNE位)。若不及时读出,现有数据就会被新的数据覆盖。
评价:连续数据流传输对于软件的配合要求较高,需要在每个标志位产生后及时读写数据,整个发送和接收的流程是交错的,但是传输效率是最高的。对传输效率有严格要求才会用到此模式,否则一般采用下面更为简单的“非连续传输”。

常用:
在这里插入图片描述

本模式对于程序设计非常友好。(示例代码基于此)
字节交换流程:最开始等待TXE位置1,发送一个数据(会自动清除TXE);等待RXNE置1,读取数据。再进行下一次的字节交换。
评价:非连续传输会损失数据传输效率,数据传输速率越快,损失越明显。

SPI发送的时序
SPI通信的基础是交换字节。也就是说,每次SPI通信的过程中,通过各自的MOSI、MISO线,主机和从机的寄存器会形成一个循环移位操作,每个比特的通信都是转圈的循环移位,8个时钟周期完整的交换一个字节。那么根据需求有选择的忽略交换过来的数据,就可以实现(以主机举例,从机同理)主机只发送、主机只接收、主从机交换数据这三类操作。

在这里插入图片描述
工作原理:
波特率发生器上升沿:所有寄存器左移一位。
波特率发生器下降沿:将采样输入的数据放到寄存器的最低位。
重复8个时钟周期,便可以实现主机和从机的数据交换。
注:实际上,何时移位、何时采样、时钟极性都是可以设置的,下面将介绍。
功能介绍:显然存在资源浪费现象。
同时进行发送和接收:正常的交换字节。
只想发送、不想接收:不看接收过来的数据。
只想接收、不想发送:随便发一个数据,比如0x00/0xFF。

时序举例:SPI交换单个字节的时序:
起始条件和终止条件:起始条件是SS从高电平切换到低电平,终止条件是SS从低电平切换到高电平。
在这里插入图片描述

交换一个字节:两个配置位分别为CPOL(Clock Polarity, 时钟极性)规定空闲状态的时钟高低电平、CPHA(Clock Phase, 时钟相位)规定数据移入(数据采样)、移出的时机。
总共有四种模式可以选择,常用模式0,会配置一个就足够,其他的只是改变时钟电平。

  1. 【模式0】[CPOL,CPHA] = [0,0],SCK低电平为空闲状态;SCK第一个边沿(上升沿)移入数据,第二个边沿(下降沿)移出数据。

  2. 【模式1】[CPOL,CPHA] = [0,1],SCK低电平为空闲状态;SCK第一个边沿移出数据,第二个边沿移入数据。
    在这里插入图片描述

  3. 【模式2】[CPOL,CPHA] = [1,0],SCK高电平为空闲状态;SCK第一个边沿移入数据,第二个边沿移出数据。
    在这里插入图片描述

  4. 【模式3】[CPOL,CPHA] = [1,1],SCK高电平为空闲状态;SCK第一个边沿移出数据,第二个边沿移入数据。

在这里插入图片描述
由于从机SPI协议由硬件控制,所以从机发送过来的数据,其数据变化边沿都是紧贴着时钟下降沿完成的。并且,如果最后接收完一个字节后时钟仍为低电平,那么从机会继续将下一个地址的数据发送过来,就实现了“连续地址读”。

二、库函数

SPI/I2S常用设置:
SPI_I2S_DeInit :将SPI或I2S外设恢复到默认的初始状态。
SPI_Init 【必需】:初始化SPI(串行外设接口)外设,并配置其相关参数,包括数据传输模式、时钟极性和相位、数据位长度等。
I2S_Init :初始化I2S(串行音频接口)外设,并配置其相关参数,包括数据格式、数据位长度、时钟极性和相位等。
SPI_StructInit :将SPI外设的配置结构体初始化为默认值。
I2S_StructInit :将I2S外设的配置结构体初始化为默认值。
SPI_Cmd 【必需】:使能或禁用SPI外设。
I2S_Cmd :使能或禁用I2S(串行音频接口)外设。
SPI_I2S_SendData 【常用】:用于向SPI或I2S外设发送数据。但只是将数据送到发送缓冲区。
SPI_I2S_ReceiveData 【常用】:从SPI或I2S外设接收数据。但只是将数据从接收缓冲区读出。
关于中断及标志位【必需】:
SPI_I2S_GetFlagStatus :常用于非中断函数。获取SPI或I2S外设的特定标志位的状态。常见的标志位包括传输完成标志(TXE或BTF)、接收缓冲区非空标志(RXNE)、传输错误标志(OVR、CRCERR等)以及其他特定功能的标志。
SPI_I2S_ClearFlag :常用于非中断函数。用于软件清除SPI或I2S外设的特定标志位。
SPI_I2S_ITConfig :配置SPI或I2S外设的中断使能状态。注意在使用中断功能之前,还需要配置中断优先级、编写中断服务程序以及使能全局中断。
SPI_I2S_GetITStatus :常用于中断函数。用于获取SPI或I2S外设的特定中断标志位的状态。
SPI_I2S_ClearITPendingBit :常用于中断函数。用于清除SPI或I2S外设的特定中断标志位。
单独参数的配置:
SPI_DataSizeConfig :配置SPI外设的数据位长度。
SPI_NSSInternalSoftwareConfig :配置SPI外设的NSS(多主机模式)的内部软件控制模式。
SPI_SSOutputCmd :使能或禁用SPI外设的SS(片选信号)输出功能。
SPI_BiDirectionalLineConfig :用于配置SPI外设的双向数据线模式。
DMA配置(连续数据传输):
SPI_I2S_DMACmd :使能或禁用SPI或I2S外设的DMA传输。
CRC配置:
SPI_TransmitCRC :向SPI外设发送CRC(循环冗余校验)值。
SPI_CalculateCRC :用于计算SPI外设接收到的数据的CRC(循环冗余校验)值。
SPI_GetCRC :用于从SPI外设获取计算得到的CRC(循环冗余校验)值。
SPI_GetCRCPolynomial :用于从SPI外设获取当前配置的CRC(循环冗余校验)多项式值

二、库函数示例代码

代码如下(示例):

 #include "stm32f10x.h"                  // Device header
 //SPI-SS引脚写操作
void SPI_User_W_SS(uint8_t BitValue){
   GPIO_WriteBit(GPIOA, GPIO_Pin_4, (BitAction)BitValue);
 }
 //SPI初始化
void SPI_User_Init(void){
   //1.开启外设时钟
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE);//GPIO时钟
   RCC_APB2PeriphClockCmd(RCC_APB2Periph_SPI1, ENABLE); //SPI1时钟
   //2.初始化端口
   //初始化SS-推挽输出
   GPIO_InitTypeDef GPIO_InitStructure;
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP;
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_4;
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_Init(GPIOA, &GPIO_InitStructure);
   //初始化CLK、MOSI-外设复用推挽输出
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_5 | GPIO_Pin_7;
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_Init(GPIOA, &GPIO_InitStructure);
   //初始化MISO-上拉输入
   GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
   GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
   GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
   GPIO_Init(GPIOA, &GPIO_InitStructure);
   //3.配置SPI
   SPI_InitTypeDef SPI_InitStructure;
   SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2; //APB2的2分频-36MHz
   SPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;                       //第一个边沿采样,第二个边沿输出
   SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;                         //时钟空闲时低电平
   SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                  //数据位宽8bit
   SPI_InitStructure.SPI_Direction = SPI_Direction_2Lines_FullDuplex; //SPI双线全双工
   SPI_InitStructure.SPI_FirstBit = SPI_FirstBit_MSB;                 //高位先行
   SPI_InitStructure.SPI_Mode = SPI_Mode_Master;                      //主机模式
   SPI_InitStructure.SPI_NSS = SPI_NSS_Soft;                          //软件自定义片选信号
   SPI_InitStructure.SPI_CRCPolynomial = 0x0007;                      //CRC用不到,所以默认值7
   SPI_Init(SPI1, &SPI_InitStructure);
   //4.SPI使能
   SPI_Cmd(SPI1, ENABLE);
   
   SPI_User_W_SS(1);//默认不选中从机
}
   
//SPI起始信号
void SPI_User_Start(void){
   SPI_User_W_SS(0);
 }
 //SPI终止信号
void SPI_User_Stop(void){
   SPI_User_W_SS(1);
 }
 //SPI交换一个字节(模式0)
 uint8_t SPI_User_SwapByte(uint8_t SendByte){
   while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_TXE)!=SET); //等待TXE置1
   SPI_I2S_SendData(SPI1,SendByte);                          //发送数据到TDR
   while(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE)!=SET);//等待RNXE置1
   return SPI_I2S_ReceiveData(SPI1);                         //从RDR接收数据
}

流程:开时钟 — 配置串口 — 配置SPI — 开启SPI使能 — 交换数据 — 关使能


总结

IIS是一种用于将数字音频设备连接在一起的电气串行总线接口标准。 在工作中音频采集,AD和主芯片之间的通信都是使用IIS进行的,它用于在电子设备中的集成电路之间传送PCM音频数据。在IIS总线上,只能同时存在一个主设备和发送设备。主设备可以是发送设备,也可以是接收设备,或是协调发送设备和接受设备的其它控制设备。在IIS系统中,提供时钟的设备为主设备。(知道有这么个东西就行,工作和大学没用到,我也不会)

关于是否清除标志位。手册上写明了TXE和RXNE“由硬件置位并由软件清除”,但是这并不代表需要一条专门的语句来清除标志位,比如SPI中就是读写数据的过程中就自动清除了,所以具体还需要查看数据手册的描述。

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

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

相关文章

3.js - 模板渲染 - 简单

3.js 真tm枯燥啊,狗都不学 效果图 源码 // ts-nocheck// 引入three.js import * as THREE from three// 导入轨道控制器 import { OrbitControls } from three/examples/jsm/controls/OrbitControls// 导入lil.gui import { GUI } from three/examples/jsm/libs/li…

【数据结构】09.树与二叉树

一、树的概念与结构 1.1 树的概念 树是一种非线性的数据结构,它是由n(n>0)个有限结点组成一个具有层次关系的集合。把它叫做树是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。 根结点:根…

webGL可用的14种3D文件格式,但要具体问题具体分析。

hello,我威斯数据,你在网上看到的各种炫酷的3d交互效果,背后都必须有三维文件支撑,就好比你网页的时候,得有设计稿源文件一样。WebGL是一种基于OpenGL ES 2.0标准的3D图形库,可以在网页上实现硬件加速的3D图…

阶段三:项目开发---大数据开发运行环境搭建:任务2:安装配置ZooKeeper

任务描述 知识点:安装配置ZooKeeper 重 点: 安装配置ZooKeeper 难 点:无 内 容: ZooKeeper是一个开源分布式协调服务,其独特的Leader-Follower集群结构,很好的解决了分布式单点问题。目前主要用于诸…

IT之家最新科技热点 | 小米 AI 研究院开创多模态通用模型

人不走空 🌈个人主页:人不走空 💖系列专栏:算法专题 ⏰诗词歌赋:斯是陋室,惟吾德馨 目录 🌈个人主页:人不走空 💖系列专栏:算法专题 ⏰诗词歌…

一.2.(3)放大电路的图解分析方法和微变等效电路分析方法;

放大电路的主要分析方法:图解法、微变等效电路法 这里以共射放大电路为例 (1) 图解法: 1.静态分析 首先确定静态工作点Q,然后根据电路的特点,做出直流负载线,进而画出交流负载线,最后,画出各极电流电压的波形。求出最大不失真输出电压。 估算IBQ,然后根据数据手册里…

二分查找2

1. 山脉数组的峰顶索引&#xff08;852&#xff09; 题目描述&#xff1a; 算法原理&#xff1a; 根据题意我们可以将数组分为两个部分&#xff0c;一个部分是arr[mid-1]<arr[mid]&#xff0c;另一个部分为arr[mid-1]>arr[mid]&#xff0c;此时不难发现我们可以将二分…

U.S.News发布全美最佳本科AI专业排名

10 加州大学圣迭戈分校 University of California, San Diego UCSD的人工智能项目从事广泛的理论和实验研究&#xff0c;学校的优势领域包括机器学习、不确定性下的推理和认知建模。除了理论学习&#xff0c;UCSD教授非常注重把计算机知识运用到自然语言处理、数据挖掘、计算…

从模拟到预测,从智能到智慧:数字孪生技术在水库管理中的应用演变,推动水利行业向更高层次的智慧化迈进

目录 引言 一、数字孪生技术概述 二、数字孪生技术在水库管理中的应用演变 1. 从模拟到预测&#xff1a;构建精准的数字孪生模型 2. 从智能到智慧&#xff1a;实现全面感知与精准控制 3. 推动公众参与与透明化管理 三、数字孪生技术推动水利行业向更高层次的智慧化迈进 …

密室逃脱——收集版修改测试

一、原版修改 1、导入资源 Unity Learn | 3D Beginner: Complete Project | URP 2、设置Scene 删除SampleScene&#xff0c;打开UnityTechnologies-3DBeginnerComplete下的MainScene 3、降低音量 (1) 打开Hierarchy面板上的Audio降低音量 (2) 打开Prefabs文件夹&#xf…

推荐3款【王炸级别】的效率软件,免费无广告,你一定要收藏

Temp Cleaner Temp Cleaner 是一款专为 Windows 操作系统设计的临时文件清理工具。它的主要功能是安全且快速地清理磁盘上的临时文件和系统缓存&#xff0c;从而释放磁盘空间。该软件体积小巧&#xff08;仅有826KB&#xff09;&#xff0c;并且是无广告的绿色软件&#xff0c;…

智能交通(3)——Learning Phase Competition for Traffic Signal Control

论文分享 https://dl.acm.org/doi/pdf/10.1145/3357384.3357900https://dl.acm.org/doi/pdf/10.1145/3357384.3357900 论文代码 https://github.com/gjzheng93/frap-pubhttps://github.com/gjzheng93/frap-pub 摘要 越来越多可用的城市数据和先进的学习技术使人们能够提…

初学Spring之 AOP 面向切面编程

AOP&#xff08;Aspect Oriented Programming&#xff09;面向切面编程 通过预编译方式和运行期间动态代理实现程序功能的统一维护的一种技术 是面向对象&#xff08;OOP&#xff09;的延续 AOP 在 Spring 中的作用&#xff1a; 1.提供声明式事务 2.允许用户自定义切面 导…

Java 基础--File - IO流(2)

I/O流 定义 数据从硬盘流向内存为输入流&#xff0c;数据从内存流向硬盘为输出流。输入也叫读取数据&#xff0c;输出也叫写出数据。 IO分类 1.按照数据的流向分为&#xff1a;输入流和输出流 ①输入流&#xff1a;把数据从其他设备上读取到内存中的流 ②输出流&#xff1…

pdf怎么转换成图片格式文件,pdf文档怎么转换成图片格式

在数字化时代&#xff0c;pdf文件转换成图片格式是一种常见的操作&#xff0c;无论是在工作还是日常生活中&#xff0c;我们总会遇到需要将pdf文件转换为图片的需求。这可能是因为图片格式更易于分享、展示或编辑。那么&#xff0c;如何高效地将pdf转换成图片呢&#xff1f;本文…

240705_昇思学习打卡-Day17-基于 MindSpore 实现 BERT 对话情绪识别

240705_昇思学习打卡-Day17-基于 MindSpore 实现 BERT对话情绪识别 近期确实太忙&#xff0c;此处仅作简单记录&#xff1a; 模型简介 BERT全称是来自变换器的双向编码器表征量&#xff08;Bidirectional Encoder Representations from Transformers&#xff09;&#xff0c…

#数据结构 顺序表

线性表 顺序表 每种结构都有它存在意义 线性表的顺序存储实现指的是用一组连续的存储单元存储线性表的数据元素。 概念 顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性表&#xff0c;一般情况下采用数组存储。在数组上完成数据的增查改删。 逻辑结构&#…

阶段三:项目开发---大数据开发运行环境搭建:任务8:安装配置Redis

任务描述 知识点&#xff1a;安装配置Redis 重 点&#xff1a; 安装配置Redis 难 点&#xff1a;无 内 容&#xff1a; Redis&#xff08;Remote Dictionary Server )&#xff0c;即远程字典服务&#xff0c;是一个开源的使用ANSI C语言编写、支持网络、可基于内存亦可…

数据结构1:C++实现变长数组

数组作为线性表的一种&#xff0c;具有内存连续这一特点&#xff0c;可以通过下标访问元素&#xff0c;并且下标访问的时间复杂的是O(1)&#xff0c;在数组的末尾插入和删除元素的时间复杂度同样是O(1)&#xff0c;我们使用C实现一个简单的边长数组。 数据结构定义 class Arr…

【手写数据库内核组件】01 解析树的结构,不同类型的数据结构组多层的链表树,抽象类型统一引用格式

不同类型的链表 ​专栏内容&#xff1a; postgresql使用入门基础手写数据库toadb并发编程 个人主页&#xff1a;我的主页 管理社区&#xff1a;开源数据库 座右铭&#xff1a;天行健&#xff0c;君子以自强不息&#xff1b;地势坤&#xff0c;君子以厚德载物. 文章目录 不同类型…