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.配置SPISPI_InitTypeDef SPI_InitStructure;SPI_InitStructure.SPI_BaudRatePrescaler = SPI_BaudRatePrescaler_2; //APB2的2分频-36MHzSPI_InitStructure.SPI_CPHA = SPI_CPHA_1Edge;                       //第一个边沿采样,第二个边沿输出SPI_InitStructure.SPI_CPOL = SPI_CPOL_Low;                         //时钟空闲时低电平SPI_InitStructure.SPI_DataSize = SPI_DataSize_8b;                  //数据位宽8bitSPI_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用不到,所以默认值7SPI_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置1SPI_I2S_SendData(SPI1,SendByte);                          //发送数据到TDRwhile(SPI_I2S_GetFlagStatus(SPI1,SPI_I2S_FLAG_RXNE)!=SET);//等待RNXE置1return SPI_I2S_ReceiveData(SPI1);                         //从RDR接收数据
}

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


总结

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

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

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

含并行连结的网络

一、Inception块 1、白色部分通过降低通道数来控制模型复杂度,蓝色做特征提取工作,每条路上的通道数可能不同,大概我们会把更重要的那部分特征分配更多的通道数 2、Inception只改变高宽,不改变通道数 3、在不同的情况下需要选择…

pin是什么?管脚

1.平面分割 1)启动Allegro PCB design ,打开.brd。深色部分属于一个net,要做一下修改,将上面的pin包含进shape中,i进行a,b两步操作,删除以前存在的Anti Etch下的line,再将其进行补齐 使它保住上…

【帧中继实验-ensp】

实验要求 在R1上开启一个点对点子接口,用于连接 R1–R2,两端IP地址为12.1.1.x 。开启一个多点子接口 ,用于连接R1–R3,R4,两段IP地址为134.1.1.x。 具体DLCI分配和映射关系如下: R1 102 R2 201—动态映射…

论文略读:Can Long-Context Language Models Subsume Retrieval, RAG, SQL, and More?

202406 arxiv 1 intro 传统上,复杂的AI任务需要多个专门系统协作完成。 这类系统通常需要独立的模块来进行信息检索、问答和数据库查询等任务大模型时代,尤其是上下文语言模型(LCLM)时代,上述问题可以“一体化”完成…

《python程序语言设计》2018版第5章第53题利用turtle绘制sin和cos函数 sin蓝色,cos红色和52题类似

直接上题和代码 5.53 (Turtle:绘制sin和cos函数)编写程序绘制蓝色的sin函数和红色的cos函数。 代码和结果 turtle.speed(10) turtle.penup() # sin 用蓝色 turtle.color("blue") #这道题和上道题一样,先把turtle放到起始…

从0到1制作单只鳌虾运动轨迹追踪软件

前言 需要准备windows10操作系统,python3.11.9,cuDNN8.9.2.26,CUDA11.8,paddleDetection2.7 流程: 准备数据集-澳洲鳌虾VOC数据集 基于RT-DETR目标检测模型训练导出onnx模型进行python部署平滑滤波处理视频帧保留的…

简介时间复杂度

好了,今天我们来了解一下,我们在做练习题中常出现的一个名词。时间复杂度。我相信大家如果有在练习过题目的话。对这个名词应该都不陌生吧。但是可能很少的去思考它是干什么的代表的什么意思。反正我以前练习的时候就是这样。我只知道有这么一个名词在题…

【全面讲解下iPhone新机官网验机流程】

🎥博主:程序员不想YY啊 💫CSDN优质创作者,CSDN实力新星,CSDN博客专家 🤗点赞🎈收藏⭐再看💫养成习惯 ✨希望本文对您有所裨益,如有不足之处,欢迎在评论区提出…

MybatisPlus实现插入/修改数据自动设置时间

引言 插入数据时自动设置当前时间,更新数据时自动修改日期为修改时的日期。 使用MybatisPlus的扩展接口MetaObjectHandler 步骤 实现接口 实体类加注解 实现接口 package com.example.vueelementson.common;import com.baomidou.mybatisplus.core.handlers.M…

C++ 模版进阶

目录 前言 1. 非类型模版参数 1.1 概念与讲解 1.2 array容器 2. 模版的特化 2.1 概念 2.2 函数模版特化 2.3 类模版特化 2.3.1 全特化 2.3.2 偏特化 3.模版的编译分离 3.1 什么是分离编译 3.2 模版的分离编译 3.3 解决方法 4. 模版总结 总结 前言 本篇文章主要…

包/final/权限修饰符/代码块

包package 1、包的作用 包用来管理不同的类。 2、包名 包名要全部小写,一般是域名反写,如com.liu。在Java中,java解释器会将package中的.解释为目录分隔符/,也就是说该文件的目录结构为:...com/liu/... 3、全类名…

1.pwn的汇编基础(提及第一个溢出:整数溢出)

汇编掌握程度 能看懂就行,绝大多数情况不需要真正的编程(shellcode题除外) 其实有时候也不需要读汇编,ida F5 通常都是分析gadget,知道怎么用, 调试程序也不需要分析每一条汇编指令,单步执行然后查看寄存器状态即可 但…

实现多数相加,但是传的参不固定

一、情景 一般实现的加法和减法等简单的相加减函数的话。一般都是写好固定传的参数。比如: function add(a,b) {return a b;} 这是固定的传入俩个,如果是三个呢,有人说当然好办! 这样写不就行了! function add(a…

vue中自定义设置多语言(包括使用vue-i18n),并且运行js脚本自动生成多语言文件

在项目中需要进行多个国家语言的切换时,可以用到下面方法其中一个 一、自定义设置多语言 方法一: 可以自己编写一个设置多语言文件 在项目新建js文件,命名为:language.js,代码如下 // language.js 文档 let languagePage {CN…

聊一下Maven打包的问题(jar要发布)

文章目录 一、问题和现象二、解决方法(1)方法一、maven-jar-pluginmaven-dependency-plugin(2)方法二、maven-assembly-plugin 一、问题和现象 现在的开发一直都是用spring boot,突然有一天,要自己开发一个…

Django之项目开发(二)

目录 一、安装和使用uWSGI 1.1、安装 1.2、配置文件 1.3、启动与停止uwsgi 二、安装nginx 三、Nginx 配置uWSGI 四、Nginx配置静态文件 五、Nginx配置负载均衡 一、安装和使用uWSGI uWSGI 是一个 Web 服务器,可以用来部署 Python Web 应用。它是一个高性能的通用的 We…

味蕾与理解:应对自闭症儿童挑食的策略与理解

在星贝育园自闭症康复学校,我们深知饮食习惯对孩子们的成长至关重要,而自闭症儿童的挑食问题往往比同龄儿童更为突出,给家长和照顾者带来了额外的挑战。今天,作为这里的老师,我想与大家分享一些应对自闭症儿童挑食的策…

(南京观海微电子)——电阻应用及选取

什么是电阻? 电阻是描述导体导电性能的物理量,用R表示。 电阻由导体两端的电压U与通过导体的电流I的比值来定义,即: 所以,当导体两端的电压一定时,电阻愈大,通过的电流就愈小;反之&…

鸿蒙应用实践:利用扣子API开发起床文案生成器

前言 扣子是一个新一代 AI 应用开发平台,无需编程基础即可快速搭建基于大模型的 Bot,并发布到各个渠道。平台优势包括无限拓展的能力集(内置和自定义插件)、丰富的数据源(支持多种数据格式和上传方式)、持…

[Unity入门01] Unity基本操作

参考的傅老师的教程学了一下Unity的基础操作: [傅老師/Unity教學] Unity3D基礎入門 [華梵大學] 遊戲引擎應用基礎(Unity版本) Class#01 移动:鼠标中键旋转:鼠标右键放大:鼠标滚轮飞行模式:右键WASDQEFocus模式&…