小型的做网站公司从哪里接的项目,wordpress封面外链,网站策划与建设,网站推广的渠道1.SPI外设简介
STM32内部集成了硬件SPI收发电路#xff0c;可以由硬件自动执行时钟生成、数据收发等功能#xff0c;减轻CPU的负担可配置8位/16位数据帧、高位先行/低位先行时钟频率#xff1a;fpclk/(2,4,8,16,32,64,128,256)支持多主机模型、主或从操作可精简为半双工/单…1.SPI外设简介
STM32内部集成了硬件SPI收发电路可以由硬件自动执行时钟生成、数据收发等功能减轻CPU的负担可配置8位/16位数据帧、高位先行/低位先行时钟频率fpclk/(2,4,8,16,32,64,128,256)支持多主机模型、主或从操作可精简为半双工/单工通信支持DMA兼容I2S协议STM32F103C8T6 硬件SPI资源SPI1APB2外设、SPI2APB1外设
2.SPI框图 我们可以大致把它分成两部分左上角就是数据寄存器和移位寄存器打配合的过程这个和串口、12C那里的设计思路都是异曲同工的主要是为了实现连续的数据流一个个数据前仆后继的一个效果然后右下角就是一些控制逻辑了寄存器的哪些位控制哪些部分会产生哪些效果这个可以通过手册的寄存器描述来得知
首先左上角核心部分就是这个移位寄存器右边的数据低位一位一位地从MOSI移出去然后MISO的数据一位一位地移入到左边的数据高位显然移位寄存器应该是一个右移的状态所以目前图上表示的是低位先行的配置对应右下角有一个LSBFIRST控制位这一位可以控制是低位先行还是高位先行LSBFIRST给1低位先行LSBFIRST给0高位先行
然后继续看左边这一块这里画了个方框里面把MOSI和MISO做了个交叉这一块主要是用来进行主从模式引脚变换的我们这个SPI外设可以做主机也可以做从机做主机时这个交叉就不用MOSI为MO主机输出MISO为MI主机输入这是主机的情况如果我们STM32作为从机的话MOSl为Sl从机输入这时它就要走交又的这一路输入到移位寄存器 接下来上下两个缓冲区就还是我们熟悉的设计这两个缓冲区实际上就是数据寄存器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的数据就会被覆盖就不能实现连续的数据流了这就是移位寄存器配合数据寄存器实现连续数据流的过程
简而言之就是发送数据先写入TDR再转到移位寄存器发送发送的同时接收数据接收到的数据转到RDR我们再从RDR读取数据数据寄存器和移位寄存器配合可以实现无延迟的数据传输这就是这一块的设计思路是不是和之前串口、12C的都差不多的意思啊当然这三者也是有一些区别的比如这里SPI是全双工发送和接收同步进行所以它的数据寄存器发送和接收是分离的而移位寄存器发送和接收可以共用
左上角是比较重要的它是SPI通信的核心部分体现了发送和接收的执行流程 右下角部分首先是波特率发生器这个主要就是用来产生SCK时钟的它的内部主要就是一个分频器输入时钟是PCLK72M或36M经过分频器之后输出到SCK引脚当然这里生成的时钟肯定是和移位寄存器同步的了每产生一个周期的时钟移入移出一个bit
然后右边CR1寄存器的三个位BR0、BR1、BR2用来控制分频系数 接着后面这些通信电路和各种寄存器都是一些黑盒子电路比如LSBFIRST刚才说过决定高位先行还是低位先行SPE(SPl Enable)是SPI使能就是SPlCmd函数配置的位BR(Baud Rate)配置波特率就是SCK时钟频率MSTR(Master)配置主从模式1是主模式0是从模式我们一般用主模式CPOL和CPHA这个之前讲过用来选择SPI的4种模式然后这里SR状态寄存器最后两个TXE发送寄存器空RXNE接收寄存器非这两个比较重要我们发送接收数据的时候需要关注这两位之后CR2寄存器就是一些使能位了比如中断使能DMA使能等
那最后这里还有个NSS引l脚SS就是从机选择低电平有效所以这里前面加了个N这个NSS和我们想象的从机选择可能不太一样我们想象的应该是用来指定某个从机对吧但是根据手册里的描述我也研究了一下这里的NSS设计可能更偏向于实现这里说的多主机模型总的来说这个NSS我们并不会用到SS引脚我们直接使用一个GPIO模拟就行因为SS引脚很简单就置一个高低电平就行了而且多从机的情况下SS还会有多个这里硬件的NSS也完成不了我们想要的功能那这个NSS是如何实现多主机切换的功能呢不重要 假如这里有3个STM32设备我们需要把这3个设备的NSS全都连接在一起首先这个NSS可以配置为输出或者输入当配置为输出时可以输出电平告诉别的设备我现在要变为主机你们其他设备都给我变成从机不要过来捣乱当配置为输入时可以接收别设备的信号当有设备是主机拉低NSS后我就无论如何也变不成主机了内部电路的设计当这里这个SSOE1时NSS作为输出引脚并在当前设备变为主设备时给NSS输出低电平这个输出的低电平就是告诉其他设备我现在是主机了当主机结束后SSOE要清0NSS变为输入这时输入信号就会跑到右边这里这有个数据选择器SSM位决定选择哪一路当选择上面一路时是硬件NSS模式也就是说这时外部如果输入了低电平那当前的设备就进入不了主模式了因为NSS低电平肯定是外部已经有设备进入了主模式它已经提前告诉我它是主模式了我就不能再跟它抢了当数据选择器选择下面一路时是软件管理NSS输入NSS是1还是0由这一位SSl来决定
3.SPI基本结构 这里移位寄存器我画的是左移高位移出去通过GPIO到MOSI从MOSI输出显然这是SPI的主机对吧之后移入的数据从MISO进来通过GPIO到移位寄存器的低位这样循环8次就能实现主机和从机交换一个字节然后TDR和RDR的配合可以实现连续的数据流另外TDR数据整体转入移位寄存器的时刻置TXE标志位移位寄存器数据整体转入RDR的时刻置RXNE标志位
剩下的部分波特率发生器产生时钟输出到SCK引脚数据控制器呢就看成是一个管理员它控制着所有电路的运行最后开关控制就是SPlCmd初始化之后给个ENABLE使能整个外设另外这里我并没有画SS从机选择引脚这个引脚我们还是使用普通的GPIO口来模拟即可在一主多从的模型下GPIO模拟的SS是最佳选择
4.主模式全双工连续传输
如何来产生具体的时序呢什么时候写DR什么时候读DR呢
这个图演示的是借助缓冲区数据前价后继实现连续数据流的过程但是这个流程稍微比较复架也不太方便封装所以在实际过程中如果对性能没有极致的追求我们更倾向使用下面这个非连续传输的示意图这个非连续传输使用起来更加简单实际用的话只需要4行代码就能完成任务了非连续传输的好处就是容易封装好理解好用但是会损失一丢丢性能连续传输呢传输更快但是操作起来相对复杂
首先第一行是SCK时钟线这里CPOL1CPHA1示例使用的是SPI模式3所以SCK默认是高电平然后在第一个下降沿MOSI和MISO移出数据之后上升沿移入数据依次这样来进行那下面第二行是MOS|和MISO输出的波形跟随SCK时钟变换数据位依次出现这里从前到后依次出现的是b0、b1一直到b7所以这里示例演示的是低位先行的模式实际SPI高位先行用的多一些
之后第三行是TXE发送寄存器空标志位下面继续看是发送缓冲器括号写入SPI_DR实际上就是这里的TDR然后BSYBUSY是由硬件自动设置和清除的当有数据传输时BUSY置1那上面这部分演示的就是输出的流程和现象然后下面是输入的流程和现象
第一个是MISO/MOSl的输入数据之后是RXNE接收数据寄存器非空标志位最后是接收缓冲器读出SPI_DR显然就是这里的RDR了 我们来从左到右依次分析首先SS置低电平开始时序这个没画但是是必须得有的在刚开始时TXE为1表示TDR空可以写入数据开始传输然后下面指示的第一步就是软件写入0xF1至SPI_DR0xF1就是要发送的第一个数据之后可以看到写入之后TDR变为0xF1同时TXE变为0表示TDR已经有数据了那此时TDR是等候区移位寄存器才是真正的发送区那此时TDR是等候区移位寄存器才是真正的发送区所以在等候区TDR里的F1就会立刻转入移位寄存器开始发送转入瞬间置TXE标志为1表示发送寄存器空然后移位寄存器有数据了波形就自动开始生成
数据转入移位寄存器之后数据F1的波形就开始产生了在移位产生F1波形的同时等候区TDR是空的为了移位完成时下一个数据能不间断地跟随这里我们就要提早把下一个数据写入到TDR里等着了所以下面指示第二步的操作是写入F1之后软件等待TXE1在这个位置一旦TDR空了我们就写入F2至SPI DR写入之后可以看到TDR的内容就变成F2了也就是把下一个数据放到TDR里候着之后的发送流程也是同理P1数据波形产生完毕后F2转入移位寄存器开始发送这时TXE1我们尽快把下一个数据F3放入到TDR等着这就是这里的操作软件等待TXE1然后写入F3至DR写入之后TDR变为F3最后在这里如果我们只想发送3个类据F3转入移位寄存器之后TXE1我们就不需要继续写入了TXE之后-直是1注意在最后一个TXE1之后还需要继续等待一段时间F3的波形才能完整发送等波形全部完整发送之后BUSY标志由硬件清除这才表示波形发送完成了那这些就是发送的流程 然后继续看一下下面接收的流程SPI是全双工发送的同时还有接收所以可以看到在第一个字节发送完成后第一个字节的接收也完成了接收到的数据1是A1这时移位寄存器的数据整体转入RDRRDR随后存储的就是A1转入的同时RXNE标志位也置1表示收到数据了转入的同时我们的操作是下面这里写的RXNE标志位也置1表示收到数据了然后从SPIDR也就是RDR读出数据A1这就是第一个接收到的数据接收之后软件清除RXNE标志位然后当下一个数据2收到之后RXNE重新置1我们监测到RXNE1时就继续读出RDR这是第二个数据A2最后在最后一个字节时序完全产生之后数据3才能收到数据3才能收到所以数据3直到这里才能读出来然后注意一个字节波形收到后移位寄存器的数据自动转入RDR会覆盖原有的数据所以我们读取RDR要及时比如A1这个数据收到之后最迟你也要A2前面把它读走否则下一个数据A2覆盖A1就不能实现连续数据流的接收了这就是整个发送和接收的流程这个连续数据流对软件的配合要求较高在每个标志位产生后你的数据都要及时处理配合的好时钟可以连续不间断地产生每个字节之间没有任何空隙传输效率是最高的如果你对传输效率有非常高的要求那需要好好研究这个连续数据流传输
但是我们入门的话可以先不用这个因为这个操作比较复杂而且数据的位置交叉比较多比如我们发送数据1按理说交换字节发送了我们就想看一下接收的是什么对吧但是这里接收的数据1直到这里才能收到而在这之前我们就要把发送的数据2写入到TDR了所以它的流程并不是我们想象的发送数据1、接收数据1、发送数据2、接收数据2这样依次交换而是发送数据1、发送数据2、之后接收数据1然后再发送数据3、接收数据2、发送数据4、接收数据3这个交换的流程是交错的对我们程序设计不太友好总之如果你对效率要求很高就研究一下这个
5.非连续传输
非连续传输对于程序设计非常友好 这个非连续传输和连续传输有什么区别呢首先这个配置还是SPI模式3SCK默认高电平我们想发送数据时如果检测到TXE1了TDR为空就软件写入0xF1至SPI_DR这时TDR的值变为F1TXE变为0目前移位寄存器也是空所以这个F1会立刻转入移位寄存器开始发送波形产生并且TXE置回1表示你可以把下一个数据放在TDR里候着了但是现在区别就来了在连续传输的这里一旦TXE1了我们就会把下一个数据写到TDR里候着这样是为了连续传输数据衔接更紧密但是这样的话流程就比较混乱程序写起来比较复杂所以在非连续传输这里TXE1了我们不着急把下一个数据写进去而是一直等待等第一个字节时序结束在这个位置时序结束了是不是意味着接收第一个字节也完成了这时接收的RXNE会置1我们等待RXNE置1后先把第一个接收到的数据读出来之后再写入下一个字节数据也就是这里的软件等待TXE1但是较晚写入0xF2至SPI_DR较晚写入TDR后数据2开始发送我们还是不急着写数据3等到了这里先把接收的数据2收着再继续写入数据3数据3时序结束后最后再接收数据3置换回来的数据按照这个流程我们的整体步骤就是第1步等待TXE为1第2步写入发送的数据至TDR第3步等待RXNE为1第4步读取RDR接收的数据之后交换第二个字节重复这4步就是发送一个等到接收一个之后再发送下一个那这样我们就可以把这4步封装到一个函数调用一次交换一个字节这样程序逻辑是不是就非常简单了和之前软件SPI的流程基本上是一样的我们只需要稍作修改就可以把软件SPI改成硬件SPI
那非连续传输缺点就是在这个位置没有及时把下一个数据写入TDR候着所以等到第一个字节时序完成后第二个字节还没有送过来那这个数据传输就会在这里等着所以这里时钟和数据的时序在字节与字节之间会产生间隙拖慢了整体数据传输的速度这个间隙在SCK频率低的时候影响不大但是在SCK频率非常高时间隙拖后腿的现象就比较严重了
6.软件/硬件波形对比 上面软件下面硬件
首先它们的数据变换趋势肯定是一样的采样得到的数据也是一样的区别就是硬件波形数据线的变化是紧贴SCK边沿的而软件波形数据线的变化在边沿后有一些延迟实际上我们还可以发现12C所描述的SCL低电平期间数据变化高电平期间数据采样和SPI描述的SCK下降沿数据移出上升沿数据移入最终波形的表现形式都是一样的无论是下降沿变化还是低电平期间变化它们都是一个意思下降沿和低电平期间都可以作为数据变化的时刻只是硬件波形一般会紧贴边沿软件波形一般只能在电平期间当然无论是哪种方式最终都不会影响数据传输不过软件波形如果能贴近边沿我们还是贴远边沿为好否则如果你等太久比较靠近下一个边沿了数据也容易出错