STM32 SPI(三)通信外设

STM32 SPI(三)通信外设

SPI外设简介

  • STM32内部集成了硬件SPI收发电路,可以由硬件自动执行时钟生成、数据收发等功能,减轻CPU的负担,硬件电路自动生成时序,不用手动翻转电平,节省软件资源。

  • 可配置8位/16位数据帧、高位先行/低位先行

    • 16位数据帧,可以在DR写入一个uint16_t类型的数据,这样一次性就可以发16位,也就是两个字节。
    • 低位先行,比如发送0x55,转化为二进制是0101 0101,左边是数据高位,右边是数据低位,在产生波形时,数据由低位到高位依次出现,所以这里的波形,是1010 1010,在看它对应的数据时,要从右往左看,0101 0101对应0x55。
  • 时钟频率: fPCLK / (2, 4, 8, 16, 32, 64, 128, 256),就是SCK波形的频率。

    • 一个SCK时钟,交换一个Bit。时钟频率一般体现的是传输速度,单位是Hz或者bit/s。
    • 这里的时钟频率是fPCLK除一个分频系数,分频系数可以配置为8、16、32、64、128、256。SPI的时钟,其实就是由PCLK分频得来的,PCLK(Peripheral Clock)就是外设时钟,APB2的PCLK是72MHZ,APB1的PCLK是26MHZ。
    • 频率数值并不是任意指定,只能是PCLK执行8个分频系数分频后的数值,最低频率是PCLK的256分频,最高频率是PCLK的2分频。
  • 支持多主机模型、主或从操作

  • 可精简为半双工/单工通信

    • 半双工,去掉一根数据线,只在其中一根线上分时进行发送或接收,节省一根通信线。
    • 单工
      • 只发模式 直接去掉接收的数据线,在发送线进行只发的数据传输
      • 只收模式 直接去掉发送的数据线,在接收线进行只收的数据传输
  • 支持DMA,自动转运数据

  • 兼容I2S协议,I2S是一种数字音频传输的专用协议。

比如主控芯片中存了一首音乐的数据,这个数据其实就是一个点一个点的电压数值,是数字信号,如果我们要把这个音乐给播放出来,就得外挂一个音频解码器,音频解码器其实就是DAC,数模转换器,负责把数字信号转换成模拟信号,然后输出到扬声器,把音乐播放出来,那我们把数字信号发送到DAC的这条线路,数据怎么发,每位数据的定义是什么,时序该怎么产生,传输速度是多快,这些配置都可以指定一个标准,这个标准就是数字音频传输协议。I2S就是其中一种。

  • STM32F103C8T6 硬件SPI资源:SPI1(APB2的外设 PCLK=72MHZ)、SPI2(APB1的外设 PCLK=32MHZ),同样的配置,SPI1的时钟频率比SPI2的大一倍。

SPI框图

  • 移位寄存器,右边的数据低位,一位一位地,从MOSI移出去,然后MISO的数据,一位一位地,移入到左边的数据高位。移位寄存器是一个右移的状态,所以目前图上表示的是低位先行的配置。对应有一个LSBFIRST控制位,这一位可以控制是低位先行还是高位先行。如果LSBFIRST置0,高位先行,那么移位寄存器变为左移,输出,从左边移出去,输入,从右边移进来。

LSBFIRST 帧格式,置0,先发送MSB,高位先行;置1,先发送LSB,低位先行。

  • MOSI和MISO可以交叉输入输出,主要用于进行主从模式引脚变换的。SPI外设,可以做主机也可以做从机。
    • STM32做主机时,就不用交叉,MOSI,为MO,主机输出,MISO,为MI,主机输入。
    • STM32做从机,MOSI,为SI,从机输入,这时就要走交叉的这一路,输入到移位寄存器;同理,MISO,为SO,从机输出,这时输出的数据,也走交叉的这一路,输出到MISO。
    • 主机和从机的输入输出模式不同,如果要切换主机和从机的话,线路就需要交叉一下。
  • 发送缓冲区TDR和接收缓冲区RDR,实际上就是数据寄存器DR,TDR和RDR占用同一个地址(SPI_DR),写入DR时,数据写入到TDR,读取DR时,数据从RDR读出,数据寄存器和移位寄存器配合,可以实现连续的数据流。
    • 比如我们需要连续发送一批数据,第一个数据写入到TDR,当移位寄存器没有数据移位时,TDR的数据会立刻转入移位寄存器,开始移位,这个转入时刻,会置状态寄存器的TXE为1,表示发送寄存器空。当我们检查TXE置1后,下一个数据,就可以提前写入到TDR里等待了,一旦上一个数据发完,下一个数据就可以立刻跟进,实现不间断的连续传输。
    • 然后移位寄存器,一旦有数据过来了,就会自动产生时钟,将数据移出去,在移出的过程中,MISO的数据也会移入,一旦数据移出完成,数据移入也完成了,这时移入的数据,就会整体地从移位寄存器转入到接收缓冲区RDR,这个时刻,会置状态寄存器的RXNE为1,表示接收寄存器非空,当我们检查RXNE置1后,就要尽快把数据从RDR读出来。在下一个数据到来之前,读出RDR,就可以实现数据连续接收。
    • 简而言之,就是发送数据先写入到TDR,再转到移位寄存器发送,发送的同时,接收数据,接收到的数据,转到RDR,我们再从RDR读取数据。数据寄存器和移位寄存器配合,可以实现无延迟的连续传输。
  • 波特率发生器,用于产生SCK时钟,内部主要就是一个分频器。输入时钟时PCLK,36MHZ或72MHZ,经过分频器之后,输出到SCK引脚,生成的时钟与移位寄存器同步。每产生一个周期的时钟,移入移出一个Bit。
  • CR1寄存器
    • BR(Baud Rate)配置波特率,就是SCK的时钟频率,BR0、BR1、BR2,用来控制分频系数(BR[2:0],波特率控制),可以对PCLK进行2~256的分频,分频之后就得到SCK的时钟。
    • LSBFIRST,决定高位先行还是低位先行。
    • SPE(SPI Enable)SPI使能,就是SPI_Cmd()函数配置的位。
    • MSTR(Master),配置主从模式。置1,主模式;置0,从模式。
    • CPOL和CPHA,用来选择SPI的4种模式。
  • SR状态寄存器
    • TXE 发送寄存器空
    • RXNE 接收寄存器非空
  • CR2寄存器
    • 中断使能
    • DMA使能
  • NSS 偏向于实现多主机模型,SS引脚直接用一个GPIO模拟即可。

在这里插入图片描述

SPI基本结构

  • 移位寄存器高位移出,通过GPIO,到MOSI,从MOSI输出。移入的数据,从MISO进来,通过GPIO,到移位寄存器的低位,这样循环8次,就能实现主机和从机交换一个字节。TDR和RDR的配合,可以实现连续的数据流。TDR中的数据,整体转入移位寄存器的时刻,置TXE标志位,移位寄存器中的数据,整体转入RDR的时刻,置RXNE标志位。
  • 波特率发生器,产生时钟,输出到SCK引脚。
  • 数据控制器,控制着所有电路的运行。
  • 开关控制,SPI_Cmd(),使能SPI。
  • SS从机选择,用普通的GPIO来模拟即可。

在这里插入图片描述

主模式全双工连续传输

  • CPOL=1,CPHA=1,示例使用SPI模式3。
  • SCK默认高电平,在第一个下降沿,MOSI和MISO移出数据,之后,上升沿移入数据,依次这样来进行。
  • MOSI和MISO输出的波形,跟随SCK时钟变换,数据位依次出现,图中从前到后,依次出现的是b0(bit 0)、b1(bit 1)一直到b7(bit 7),所以示例演示的是低位先行的模式。实际SPI高位先行用的较多。
  • TXE,发送寄存器空标志位。
  • 发送缓冲器(写入SPI_DR),实际上就是TDR。
  • BSY标志,BUSY,是由硬件自动设置和清除的。当有数据传输时,BUSY置1。
  • MISO/MOSI(输入)输入数据。
  • RXNE,接收数据寄存器非空标志位。
  • 接收缓冲器(读出SPI_DR)

发送流程

  • 首先,SS置低电平,开始时序,在刚开始时,TXE为1,表示TDR空,可以写入数据开始传输。
  • 第一步操作:软件写入0xF1至SPI_DR(TDR),0xF1。就是要发送的第一个数据,之后可以看到,写入之后,TDR变为0xF1,同时TXE变为0,表示TDR已经有数据了。此时,TDR是等候区,移位寄存器才是真正的发送区,移位寄存器刚开始肯定没有数据,所以在等候区TDR里的F1,就会立刻转入移位寄存器,开始发送,转入瞬间,置TXE标志位为1,表示发送寄存器空。然后移位寄存器有数据了,MISO/MOSI(输出)的波形就自动开始生成。数据转入移位寄存器之后,数据F1的波形就开始产生了,在移位产生F1波形的同时,等候区TDR是空的,为了移位完成时,下一个数据能不间断地跟随,需要提早把下一个数据写入到TDR里等待。
  • 第二步操作:软件等待TXE=1,然后写入0xF2至SPI_DR。写入之后可以看到,TDR的内容,就变成F2了,也就是把下一个数据放到TDR种等待,之后的发送流程也是同理,F1数据波形产生完毕后,F2转入移位寄存器开始发送,这时TXE=1,我们尽快把下一个数据F3,放在TDR里等待。这就是软件等待TXE=1,然后写入0xF3至SPI_DR。写入之后TDR变为F3。
  • 如果我们只想发送三个数据,F3转入移位寄存器后,TXE=1,就不需要继续写入了,TXE之后一直是1。在最后一个TXE=1之后,还需要继续等待一段时间,F3的波形才能完整发送。等波形全部完整发送之后,BUSY标志由硬件清除,表示波形发送完成。

接收流程

  • 在第一个字节发送完成后,第一个字节的接收也完成了,接收到的数据1,是A1。这时,移位寄存器的数据,整体转入RDR,RDR随后存储的就是A1。转入的同时,RXNE标志位也置1,表示接收寄存器非空。我们的操作是软件等待RXNE=1,然后从SPI_DR(RDR)读出0xA1。
  • 接收之后,软件清除RXNE标志位,当下一个数据2收到之后,RXNE重新置1,检测到RXNE=1,就继续读出RDR,这是第二个数据A2。
  • 最后,在最后一个字节时序完全产生之后,数据3才能收到。
  • 一个字节波形收到后,移位寄存器的数据自动转入RDR,会覆盖原有的数据,所以我们读取RDR要及时,比如A1这个数据,收到之后,最迟要在A2数据全部收到之前,将A1读走,否则下一个数据A2,将覆盖A1,就不能实现连续数据流的接收了。

在这里插入图片描述

非连续传输

缺点:

没有及时把下一个数据写入TDR中等待,所以,等到第一个字节时序完成后,第二个字节还没有送过来,那这个数据传输,就会进入等待。所以这里时钟和数据的时序,在字节与字节之间,会产生间隙,拖慢了整体数据传输的速度。这个间隙,在SCK频率低的时候,影响不大,但是在SCK频率非常高的时候,间隙拖慢速度的现象,就比较严重了。

如果想在极限频率下,进一步提高数据传输速率,也就是追求最高性能,最好使用连续传输的操作逻辑,或者进一步采用DMA自动转运。

  • SPI模式3 SCK默认高电平
  • 想发送数据时,如果检测到TXE=1,TDR为空,就软件写入0xF1至SPI_DR,这时,TDR的值变为F1,TXE=0,目前移位寄存器也是空,所以这个F1会立刻转入移位寄存器开始发送,波形产生,并且TXE置回1,表示可以把下一个数据放在TDR等待了。
  • TXE=1时,我们不着急将下一个数据写入,而是一直等待,等第一个字节时序结束。第一个字节时序结束,意味着接收第一个字节也完成了,接收的RXNE会置1,我们等待RXNE置1后,先把数据1置换回来的数据读出来,之后,再写入下一个字节,也就是这里的软件等待TXE=1但是较晚写入0xF2至SPI_DR。
  • 数据2较晚写入TDR后,数据2开始发送,我们还是不着急写数据3,等到第二个字节时序结束,先读出数据2置换回来的数据,再写入数据3。
  • 数据3时序结束后,再接收数据3置换回来的数据。
    • 第一步,等待TXE为1
    • 第二步,写入发送的数据至TDR
    • 第三步,等待RXNE为1
    • 第四步,读取RDR接收的数据
    • 之后交换字节,重复这四步即可

在这里插入图片描述

软件/硬件波形对比

下降沿数据移出,上升沿数据移入

软件

  • 软件波形数据线的变化,在边沿后有一些延迟。

在这里插入图片描述

硬件

  • 硬件波形数据线的变化,是紧贴SCK边沿的。

在这里插入图片描述

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

YRr YRr

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值