深入解析SPI通信协议及工作原理

文章目录

  • 一、SPI简介
  • 特征
  • 二、SPI功能描述
  • 1. 概述
  • 2. 配置SPI为从模式
  • 3. 配置SPI为主模式
  • 4. 配置SPI为单工通信
  • 5. 数据发送与接收过程
  • 6. CRC计算
  • 7. 状态标志
  • 8. 关闭SPI
  • 9. 利用DMA的SPI通信
  • 10. 错误标志
  • 11. SPI中断
  • 三、SPI寄存器描述
  • 1. SPI控制寄存器 1(SPI_CR1)
  • 2. SPI控制寄存器 2(SPI_CR2)
  • 3. SPI 状态寄存器(SPI_SR)
  • 4. SPI 数据寄存器(SPI_DR)
  • 5. SPI CRC多项式寄存器(SPI_CRCPR)
  • 6. SPI Rx CRC寄存器(SPI_RXCRCR)
  • 7. SPI Tx CRC寄存器(SPI_TXCRCR)
  • 8. SPI_I2S配置寄存器(SPI_I2S_CFGR)
  • 9. SPI_I2S预分频寄存器(SPI_I2SPR)
  • 10. SPI 寄存器地址映象

  • 一、SPI简介

    SPI 是英语 Serial Peripheral interface 的缩写,顾名思义就是串行外围设备接口。是 Motorola首先在其 MC68HCXX 系列处理器上定义的。SPI 接口主要应用在 EEPROM,FLASH,实时时钟,AD 转换器,还有数字信号处理器和数字信号解码器之间。SPI,是一种高速的,全双工,同步的通信总线,并且在芯片的管脚上只占用四根线,节约了芯片的管脚,同时为 PCB 的布局上节省空间,提供方便,正是出于这种简单易用的特性,现在越来越多的芯片集成了这种通信协议,STM32 也有 SPI 接口。

    特征

    ● 3线全双工同步传输
    ● 带或不带第三根双向数据线的双线单工同步传输
    ● 8或16位传输帧格式选择
    ● 主或从操作
    ● 支持多主模式
    ● 8个主模式波特率预分频系数(最大为fPCLK/2)
    ● 从模式频率 (最大为fPCLK/2)
    ● 主模式和从模式的快速通信
    ● 主模式和从模式下均可以由软件或硬件进行NSS管理:主/从操作模式的动态改变
    ● 可编程的时钟极性和相位
    ● 可编程的数据顺序,MSB在前或LSB在前
    ● 可触发中断的专用发送和接收标志
    ● SPI总线忙状态标志
    ● 支持可靠通信的硬件CRC
    ─ 在发送模式下,CRC值可以被作为最后一个字节发送
    ─ 在全双工模式中对接收到的最后一个字节自动进行CRC校验
    ● 可触发中断的主模式故障、过载以及CRC错误标志
    ● 支持DMA功能的1字节发送和接收缓冲器:产生发送和接受请求

    二、SPI功能描述

    1. 概述


    通常SPI通过4个引脚与外部器件相连:
    ● MISO:主设备输入/从设备输出引脚。该引脚在从模式下发送数据,在主模式下接收数据。
    ● MOSI:主设备输出/从设备输入引脚。该引脚在主模式下发送数据,在从模式下接收数据。
    ● SCK:串口时钟,作为主设备的输出,从设备的输入
    ● NSS:从设备选择。这是一个可选的引脚,用来选择主/从设备。

    它的功能是用来作为“片选引脚”,让主设备可以单独地与特定从设备通讯,避免数据线上的冲突。从设备的NSS引脚可以由主设备的一个标准I/O引脚来驱动。一旦被使能(SSOE位),NSS引脚也可以作为输出引脚,并在SPI处于主模式时拉低;此时,所有的SPI设备,如果它们的NSS引脚连接到主设备的NSS引脚,则会检测到低电平,如果它们被设置为NSS硬件模式,就会自动进入从设备状态。当配置为主设备、NSS配置为输入引脚(MSTR=1SSOE=0)时,如果NSS被拉低,则这个SPI设备进入主模式失败状态:即MSTR位被自动清除,此设备进入从模式(参见) 下图是一个单主和单从设备互连的例子。

    1. 这里NSS引脚设置为输入
      MOSI脚相互连接,MISO脚相互连接。这样,数据在主和从之间串行地传输(MSB位在前)。通信总是由主设备发起。主设备通过MOSI脚把数据发送给从设备,从设备通过MISO引脚回传数据。这意味全双工通信的数据输出和数据输入是用同一个时钟信号同步的;时钟信号由主设备通过SCK脚提供。

    从选择(NSS)脚管理
    有2种NSS模式:
    ● 软件NSS模式:可以通过设置SPI_CR1寄存器的SSM位来使能这种模式。在这种模式下NSS引脚可以用作它用,而内部NSS信号电平可以通过写SPI_CR1的SSI位来驱动
    ● 硬件NSS模式,分两种情况:
    ─ NSS输出被使能:当STM32F10xxx工作为主SPI,并且NSS输出已经通过SPI_CR2寄存器的SSOE位使能,这时NSS引脚被拉低,所有NSS引脚与这个主SPI的NSS引脚相连并配置为硬件NSS的SPI设备,将自动变成从SPI设备。
    当一个SPI设备需要发送广播数据,它必须拉低NSS信号,以通知所有其它的设备它是主设备;如果它不能拉低NSS,这意味着总线上有另外一个主设备在通信,这时将产生一个硬件失败错误(Hard Fault)。
    ─ NSS输出被关闭:允许操作于多主环境。


    时钟信号的相位和极性
    SPI_CR寄存器的CPOL和CPHA位,能够组合成四种可能的时序关系。CPOL(时钟极性)位控制在没有数据传输时时钟的空闲状态电平,此位对主模式和从模式下的设备都有效。如果CPOL被 清’0’,SCK引脚在空闲状态保持低电平;如果CPOL被置’1’,SCK引脚在空闲状态保持高电平。

    如果CPHA(时钟相位)位被置’1’,SCK时钟的第二个边沿(CPOL位为0时就是下降沿,CPOL位 为’1’时就是上升沿)进行数据位的采样,数据在第二个时钟边沿被锁存。如果CPHA位被清’0’,SCK时钟的第一边沿(CPOL位为’0’时就是下降沿,CPOL位为’1’时就是上升沿)进行数据位采样,数据在第一个时钟边沿被锁存。

    CPOL时钟极性和CPHA时钟相位的组合选择数据捕捉的时钟边沿。
    下图为显示SPI传输的4种CPHA和CPOL位组合。此图可以解释为主设备和从设备的SCK脚、MISO脚、MOSI脚直接连接的主或从时序图。

    注意:

    1. 在改变CPOL/CPHA位之前,必须清除SPE位将SPI禁止。
    2. 主和从必须配置成相同的时序模式。
    3. SCK的空闲状态必须和SPI_CR1寄存器指定的极性一致(CPOL为’1’时,空闲时应上拉SCK为高电平;CPOL为’0’时,空闲时应下拉SCK为低电平)。
    4. 数据帧格式(8位或16位)由SPI_CR1寄存器的DFF位选择,并且决定发送/接收的数据长度。


    数据帧格式
    根据SPI_CR1寄存器中的LSBFIRST位,输出数据位时可以MSB在先也可以LSB在先。根据SPI_CR1寄存器的DFF位,每个数据帧可以是8位或是16位。所选择的数据帧格式对发送和/或接收都有效。

    2. 配置SPI为从模式

    在从模式下,SCK引脚用于接收从主设备来的串行时钟。SPI_CR1寄存器中BR[2:0]的设置不影响数据传输速率。

    注: 建议在主设备发送时钟之前使能SPI从设备,否则可能会发生意外的数据传输。在通信时钟的第一个边沿到来之前或正在进行的通信结束之前,从设备的数据寄存器必须就绪。在使能从设备和主设备之前,通信时钟的极性必须处于稳定的数值。请按照以下步骤配置SPI为从模式:

    配置步骤

    1. 设置DFF位以定义数据帧格式为8位或16位。
    2. 选择CPOL和CPHA位来定义数据传输和串行时钟之间的相位关系。为保证正确的数据传输,从设备和主设备的CPOL和CPHA位必须配置成相同的方式。
    3. 帧格式(SPI_CR1寄存器中的LSBFIRST位定义的”MSB在前”还是”LSB在前”)必须与主设备相同。
    4. 硬件模式下(参考从选择(NSS)脚管理部分),在完整的数据帧(8位或16位)传输过程中,NSS引脚必须为低电平。在NSS软件模式下,设置SPI_CR1寄存器中的SSM位并清除SSI位。
    5. 清除MSTR位、设置SPE位(SPI_CR1寄存器),使相应引脚工作于SPI模式下。在这个配置中,MOSI引脚是数据输入,MISO引脚是数据输出。

    数据发送过程
    在写操作中,数据字被并行地写入发送缓冲器。当从设备收到时钟信号,并且在MOSI引脚上出现第一个数据位时,发送过程开始(译注:此时第一个位被发送出去)。余下的位(对于8位数据帧格式,还有7位;对于16位数据帧格式,还有15位)被装进移位寄存器。当发送缓冲器中的数据传输到移位寄存器时,SPI_SP寄存器的TXE标志被设置,如果设置了SPI_CR2寄存器的TXEIE位,将会产生中断。

    数据接收过程
    对于接收器,当数据接收完成时:
    ● 移位寄存器中的数据传送到接收缓冲器,SPI_SR 寄存器中的RXNE标志被设置。
    ● 如果设置了SPI_CR2寄存器中的RXNEIE位,则产生中断。
    在最后一个采样时钟边沿后,RXNE位被置’1’,移位寄存器中接收到的数据字节被传送到接收缓冲器。当读SPI_DR寄存器时,SPI设备返回这个接收缓冲器的数值。读SPI_DR寄存器时,RXNE位被清除。

    3. 配置SPI为主模式

    在主配置时,在SCK脚产生串行时钟。
    配置步骤

    1. 通过SPI_CR1寄存器的BR[2:0]位定义串行时钟波特率。
    2. 选择CPOL和CPHA位,定义数据传输和串行时钟间的相位关系。
    3. 设置DFF位来定义8位或16位数据帧格式。
    4. 配置SPI_CR1寄存器的LSBFIRST位定义帧格式。
    5. 如果需要NSS引脚工作在输入模式,硬件模式下,在整个数据帧传输期间应把NSS脚连接到高电平;在软件模式下,需设置SPI_CR1寄存器的SSM位和SSI位。如果NSS引脚工作在输出模式,则只需设置SSOE位。
    6. 必须设置MSTR位和SPE位(只当NSS脚被连到高电平,这些位才能保持置位)。在这个配置中,MOSI引脚是数据输出,而MISO引脚是数据输入。

    数据发送过程
    当写入数据至发送缓冲器时,发送过程开始。在发送第一个数据位时,数据字被并行地(通过内部总线)传入移位寄存器,而后串行地移出到MOSI脚上;MSB在先还是LSB在先,取决于SPI_CR1寄存器中的LSBFIRST位的设置。数据从发送缓冲器传输到移位寄存器时TXE标志将被置位,如果设置了SPI_CR1寄存器中的TXEIE位,将产生中断。

    数据接收过程
    对于接收器来说,当数据传输完成时:
    ● 传送移位寄存器里的数据到接收缓冲器,并且RXNE标志被置位。
    ● 如果设置了SPI_CR2寄存器中的RXNEIE位,则产生中断。
    在最后采样时钟沿,RXNE位被设置,在移位寄存器中接收到的数据字被传送到接收缓冲器。

    读SPI_DR寄存器时,SPI设备返回接收缓冲器中的数据。
    读SPI_DR寄存器将清除RXNE位。一旦传输开始,如果下一个将发送的数据被放进了发送缓冲器,就可以维持一个连续的传输流。在试图写发送缓冲器之前,需确认TXE标志应该为’1’。

    注: 在NSS硬件模式下,从设备的NSS输入由NSS引脚控制或另一个由软件驱动的GPIO引脚控制。

    4. 配置SPI为单工通信

    SPI模块能够以两种配置工作于单工方式:
    ● 1条时钟线和1条双向数据线;
    ● 1条时钟线和1条数据线(只接收或只发送);

    1条时钟线和1条双向数据线(BIDIMODE=1)
    设置SPI_CR1寄存器中的BIDIMODE位而启用此模式。在这个模式下,SCK引脚作为时钟,主设备使用MOSI引脚而从设备使用MISO引脚作为数据通信。传输的方向由SPI_CR1寄存器里的BIDIOE控制,当这个位是’1’的时候,数据线是输出,否则是输入。
    1条时钟和1条单向数据线(BIDIMODE=0)
    在这个模式下,SPI模块可以或者作为只发送,或者作为只接收。
    ● 只发送模式类似于全双工模式(BIDIMODE=0,RXONLY=0):数据在发送引脚(主模式时是MOSI、从模式时是MISO)上传输,而接收引脚(主模式时是MISO、从模式时是MOSI)可以作为通用的I/O使用。此时,软件不必理会接收缓冲器中的数据(如果读出数据寄存器,它不包含任何接收数据)。
    ● 在只接收模式,可以通过设置SPI_CR2寄存器的RXONLY位而关闭SPI的输出功能;此时,发送引脚(主模式时是MOSI、从模式时是MISO)被释放,可以作为其它功能使用。

    配置并使能SPI模块为只接收模式的方式是:
    ● 在主模式时,一旦使能SPI,通信立即启动,当清除SPE位时立即停止当前的接收。在此模式下,不必读取BSY标志,在SPI通信期间这个标志始终为’1’。
    ● 在从模式时,只要NSS被拉低(或在NSS软件模式时,SSI位为’0’)同时SCK有时钟脉冲,SPI就一直在接收。

    5. 数据发送与接收过程

    接收与发送缓冲器
    在接收时,接收到的数据被存放在一个内部的接收缓冲器中;在发送时,在被发送之前,数据将首先被存放在一个内部的发送缓冲器中。
    对SPI_DR寄存器的读操作,将返回接收缓冲器的内容;写入SPI_DR寄存器的数据将被写入发送缓冲器中。

    主模式下开始传输
    全双工模式(BIDIMODE=0并且RXONLY=0)
    ─ 当写入数据到SPI_DR寄存器(发送缓冲器)后,传输开始;
    ─ 在传送第一位数据的同时,数据被并行地从发送缓冲器传送到8位的移位寄存器中,然后按顺序被串行地移位送到MOSI引脚上;
    ─ 与此同时,在MISO引脚上接收到的数据,按顺序被串行地移位进入8位的移位寄存器中,然后被并行地传送到SPI_DR寄存器(接收缓冲器)中。
    单向的只接收模式(BIDIMODE=0并且RXONLY=1)
    ─ SPE=1时,传输开始;
    ─ 只有接收器被激活,在MISO引脚上接收到的数据,按顺序被串行地移位进入8位的移位寄存器中,然后被并行地传送到SPI_DR寄存器(接收缓冲器)中。
    双向模式,发送时(BIDIMODE=1并且BIDIOE=1)
    ─ 当写入数据到SPI_DR寄存器(发送缓冲器)后,传输开始;
    ─ 在传送第一位数据的同时,数据被并行地从发送缓冲器传送到8位的移位寄存器中,然后按顺序被串行地移位送到MOSI引脚上;
    ─ 不接收数据。
    双向模式,接收时(BIDIMODE=1并且BIDIOE=0)
    ─ SPE=1并且BIDIOE=0时,传输开始;
    ─ 在MOSI引脚上接收到的数据,按顺序被串行地移位进入8位的移位寄存器中,然后被并行地传送到SPI_DR寄存器(接收缓冲器)中。
    ─ 不激活发送器,没有数据被串行地送到MOSI引脚上。

    从模式下开始传输
    全双工模式(BIDIMODE=0并且RXONLY=0)
    ─ 当从设备接收到时钟信号并且第一个数据位出现在它的MOSI时,数据传输开始,随后的数据位依次移动进入移位寄存器;
    ─ 与此同时,在传输第一个数据位时,发送缓冲器中的数据被并行地传送到8位的移位寄存器,随后被串行地发送到MISO引脚上。软件必须保证在SPI主设备开始数据传输之前在发送寄存器中写入要发送的数据。
    单向的只接收模式(BIDIMODE=0并且RXONLY=1)
    ─ 当从设备接收到时钟信号并且第一个数据位出现在它的MOSI时,数据传输开始,随后数据位依次移动进入移位寄存器;
    ─ 不启动发送器,没有数据被串行地传送到MISO引脚上。
    双向模式,发送时(BIDIMODE=1并且BIDIOE=1)
    ─ 当从设备接收到时钟信号并且发送缓冲器中的第一个数据位被传送到MISO引脚上的时候,数据传输开始;
    ─ 在第一个数据位被传送到MISO引脚上的同时,发送缓冲器中要发送的数据被平行地传送到8位的移位寄存器中,随后被串行地发送到MISO引脚上。软件必须保证在SPI主设备开始数据传输之前在发送寄存器中写入要发送的数据;
    ─ 不接收数据。
    双向模式,接收时(BIDIMODE=1并且BIDIOE=0)
    ─ 当从设备接收到时钟信号并且第一个数据位出现在它的MOSI时,数据传输开始;
    ─ 从MISO引脚上接收到的数据被串行地传送到8位的移位寄存器中,然后被平行地传送到SPI_DR寄存器(接收缓冲器); ─ 不启动发送器,没有数据被串行地传送MISO引脚上。

    处理数据的发送与接收
    当数据从发送缓冲器传送到移位寄存器时,设置TXE标志(发送缓冲器空),它表示内部的发送缓冲器可以接收下一个数据;如果在SPI_CR2寄存器中设置了TXEIE位,则此时会产生一个中断;写入SPI_DR寄存器即可清除TXE位。
    注: 在写入发送缓冲器之前,软件必须确认TXE标志为’1’,否则新的数据会覆盖已经在发送缓冲器中的数据。

    在采样时钟的最后一个边沿,当数据被从移位寄存器传送到接收缓冲器时,设置RXNE标志(接收缓冲器非空);它表示数据已经就绪,可以从SPI_DR寄存器读出;如果在SPI_CR2寄存器中设置了RXNEIE位,则此时会产生一个中断;读出SPI_DR寄存器即可清除RXNIE标志位。在一些配置中,传输最后一个数据时,可以使用BSY标志等待数据传输的结束。

    主或从模式下(BIDIMODE=0并且RXONLY=0)全双工发送和接收过程模式
    软件必须遵循下述过程,发送和接收数据:

    1. 设置SPE位为’1’,使能SPI模块;
    2. 在SPI_DR寄存器中写入第一个要发送的数据,这个操作会清除TXE标志;
    3. 等待TXE=1,然后写入第二个要发送的数据。等待RXNE=1,然后读出SPI_DR寄存器并获得第一个接收到的数据,读SPI_DR的同时清除了RXNE位。重复这些操作,发送后续的数据同时接收n-1个数据;
    4. 等待RXNE=1,然后接收最后一个数据;
    5. 等待TXE=1,在BSY=0之后关闭SPI模块。
      也可以在响应RXNE或TXE标志的上升沿产生的中断的处理程序中实现这个过程


      只发送过程(BIDIMODE=0并且RXONLY=0)
      在此模式下,传输过程可以简要说明如下,使用BSY位等待传输的结束:
    6. 设置SPE位为’1’,使能SPI模块;
    7. 在SPI_DR寄存器中写入第一个要发送的数据,这个操作会清除TXE标志;
    8. 等待TXE=1,然后写入第二个要发送的数据。重复这个操作,发送后续的数据;
    9. 写入最后一个数据到SPI_DR寄存器之后,等待TXE=1;然后等待BSY=0,这表示最后一个数据的传输已经完成。也可以在响应TXE标志的上升沿产生的中断的处理程序中实现这个过程。

    注:

    1. 对于不连续的传输,在写入SPI_DR寄存器的操作与设置BSY位之间有2个APB时钟周期的延
      迟,因此在只发送模式下,写入最后一个数据后,最好先等待TXE=1,然后再等待BSY=0。
    2. 只发送模式下,在传输2个数据之后,由于不会读出接收到的数据,SPI_SR寄存器中的OVR位会变为’1’。(译注:软件不必理会这个OVR标志位)



    双向发送过程(BIDIMODE=1并且BIDIOE=1)
    在此模式下,操作过程类似于只发送模式,不同的是:在使能SPI模块之前,需要在SPI_CR2寄存器中同时设置BIDIMODE和BIDIOE位为’1’。

    单向只接收模式(BIDIMODE=0并且RXONLY=1)
    在此模式下,传输过程可以简要说明如下(见):

    1. 在SPI_CR2寄存器中,设置RXONLY=1;
    2. 设置SPE=1,使能SPI模块:
      a) 主模式下,立刻产生SCK时钟信号,在关闭SPI(SPE=0)之前,不断地接收串行数据;
      b) 从模式下,当SPI主设备拉低NSS信号并产生SCK时钟时,接收串行数据。
    3. 等待RXNE=1,然后读出SPI_DR寄存器以获得收到的数据(同时会清除RXNE位)。重复这个操作接收所有数据。也可以在响应RXNE标志的上升沿产生的中断的处理程序中实现这个过程。

    注: 如果在最后一个数据传输结束后关闭SPI模块,请按照第23.3.8节的建议操作。


    单向接收过程(BIDIMODE=1并且BIDIOE=0)
    在此模式下,操作过程类似于只接收模式,不同的是:在使能SPI模块之前,需要在SPI_CR2寄存器中设置BIDIMODE为’1’并清除BIDIOE位为’0’。

    连续和非连续传输
    当在主模式下发送数据时,如果软件足够快,能够在检测到每次TXE的上升沿(或TXE中断),并立即在正在进行的传输结束之前写入SPI_DR寄存器,则能够实现连续的通信;此时,在每个数据项的传输之间的SPI时钟保持连续,同时BSY位不会被清除。

    如果软件不够快,则会导致不连续的通信;这时,在每个数据传输之间会被清除(见下图)。在主模式的只接收模式下(RXONLY=1),通信总是连续的,而且BSY标志始终为’1’。在从模式下,通信的连续性由SPI主设备决定。不管怎样,即使通信是连续的,BSY标志会在每个数据项之间至少有一个SPI时钟周期为低

    6. CRC计算

    CRC校验用于保证全双工通信的可靠性。数据发送和数据接收分别使用单独的CRC计算器。通过对每一个接收位进行可编程的多项式运算来计算CRC。CRC的计算是在由SPI_CR1寄存器中CPHA和CPOL位定义的采样时钟边沿进行的。

    注意: 该SPI接口提供了两种CRC计算方法,取决于所选的发送和/或接收的数据帧格式:8位数据帧采用CR8;16位数据帧采用CRC16。

    CRC计算是通过设置SPI_CR1寄存器中的CRCEN位启用的。设置CRCEN位时同时复位CRC寄存器(SPI_RXCRCR和SPI_TXCRCR)。当设置SPI_CR1的CRCNEXT位,SPI_TXCRCR的内容将在当前字节发送之后发出。
    在传输SPI_TXCRCR的内容时,如果在移位寄存器中收到的数值与SPI_RXCRCR的内容不匹配,则SPI_SR寄存器的CRCERR标志位被置1。
    如果在TX缓冲器中还有数据,CRC的数值仅在数据字节传输结束后传送。在传输CRC期间,CRC计算器关闭,寄存器的数值保持不变。

    注意: 请参考产品说明书,以确认有此功能(不是所有型号都有此功能)。

    SPI通信可以通过以下步骤使用CRC:
    ● 设置CPOL、CPHA、LSBFirst、BR、SSM、SSI和MSTR的值;
    ● 在SPI_CRCPR寄存器输入多项式;
    ● 通过设置SPI_CR1寄存器CRCEN位使能CRC计算,该操作也会清除寄存器SPI_RXCRCR 和SPI_TXCRC;
    ● 设置SPI_CR1寄存器的SPE位启动SPI功能;
    ● 启动通信并且维持通信,直到只剩最后一个字节或者半字;
    ● 在把最后一个字节或半字写进发送缓冲器时,设置SPI_CR1的CRCNext位,指示硬件在发送完成最后一个数据之后,发送CRC的数值。在发送CRC数值期间,停止CRC计算;
    ● 当最后一个字节或半字被发送后,SPI发送CRC数值,CRCNext位被清除。同样,接收到的CRC与SPI_RXCRCR值进行比较,如果比较不相配,则设置SPI_SR上的CRCERR标志位,当设置了SPI_CR2寄存器的ERRIE时,则产生中断。

    注意:

    1. 当SPI模块处于从设备模式时,请注意在时钟稳定之后再使能CRC计算,否则可能会得到错误的CRC计算结果。事实上,只要设置了CRCEN位,只要在SCK引脚上有输入时钟,不管SPE位的状态,都会进行CRC的计算。
    2. 当SPI时钟频率较高时,用户在发送CRC时必须小心。在CRC传输期间,使用CPU的时间应尽可能少;为了避免在接收最后的数据和CRC时出错,在发送CRC过程中应禁止函数调用。必须在发送/接收最后一个数据之前完成设置CRCNEXT位的操作。
    3. 当SPI时钟频率较高时,因为CPU的操作会影响SPI的带宽,建议采用DMA模式以避免SPI降低的速度。
    4. 当STM32F10xxx配置为从模式并且使用了NSS硬件模式,NSS引脚应该在数据传输和CRC传输期间保持为低。
    5. 当配置SPI为从模式并且使用CRC的功能,即使NSS引脚为高时仍然会执行CRC的计算(译注:当NSS信号为高时,如果SCK引脚上有时钟脉冲,则CRC计算会继续执行)。例如:当主设备交替地与多个从设备进行通信时,将会出现这种情况(译注:此时要想办法避免CRC的误操作)。在不选中一个从设备(NSS信号为高)转换到选中一个新的从设备(NSS信号为低)的时候,为了保持主从设备端下次CRC计算结果的同步,应该清除主从两端的CRC数值。

    按照下述步骤清除CRC数值:

    1. 关闭SPI模块(SPE=0);
    2. 清除CRCEN位为’0’;
    3. 设置CRCEN位为’1’;
    4. 使能SPI模块(SPE=1)。

    7. 状态标志

    应用程序通过3个状态标志可以完全监控SPI总线的状态。
    发送缓冲器空闲标志(TXE)
    此标志为’1’时表明发送缓冲器为空,可以写下一个待发送的数据进入缓冲器中。当写入SPI_DR时,TXE标志被清除。
    接收缓冲器非空(RXNE)
    此标志为’1’时表明在接收缓冲器中包含有效的接收数据。读SPI数据寄存器可以清除此标志。
    忙(Busy)标志
    BSY标志由硬件设置与清除(写入此位无效果),此标志表明SPI通信层的状态。
    当它被设置为’1’时,表明SPI正忙于通信,但有一个例外:在主模式的双向接收模式下(MSTR=1、BDM=1并且BDOE=0),在接收期间BSY标志保持为低。在软件要关闭SPI模块并进入停机模式(或关闭设备时钟)之前,可以使用BSY标志检测传输是否结束,这样可以避免破坏最后一次传输,因此需要严格按照下述过程执行。BSY标志还可以用于在多主系统中避免写冲突。
    除了主模式的双向接收模式(MSTR=1、BDM=1并且BDOE=0),当传输开始时,BSY标志被置’1’。

    以下情况时此标志将被清除为’0’:
    ● 当传输结束(主模式下,如果是连续通信的情况例外);
    ● 当关闭SPI模块;
    ● 当产生主模式失效(MODF=1)。
    如果通信不是连续的,则在每个数据项的传输之间,BSY标志为低。
    当通信是连续时:
    ● 主模式下:在整个传输过程中,BSY标志保持为高;
    ● 从模式下:在每个数据项的传输之间,BSY标志在一个SPI时钟周期中为低。

    注: 不要使用BSY标志处理每一个数据项的发送和接收,最好使用TXE和RXNE标志。

    8. 关闭SPI

    当通讯结束,可以通过关闭SPI模块来终止通讯。清除SPE位即可关闭SPI。
    在某些配置下,如果再传输还未完成时,就关闭SPI模块并进入停机模式,则可能导致当前的传输被破坏,而且BSY标志也变得不可信。

    为了避免发生这种情况,关闭SPI模块时,建议按照下述步骤操作:
    在主或从模式下的全双工模式(BIDIMODE=0,RXONLY=0)

    1. 等待RXNE=1并接收最后一个数据;
    2. 等待TXE=1;
    3. 等待BSY=0;
    4. 关闭SPI(SPE=0),最后进入停机模式(或关闭该模块的时钟)。

    在主或从模式下的单向只发送模式(BIDIMODE=0,RXONLY=0)或双向的发送模式(BIDIMODE=1,BIDIOE=1)
    在SPI_DR寄存器中写入最后一个数据后:

    1. 等待TXE=1;
    2. 等待BSY=0;
    3. 关闭SPI(SPE=0),最后进入停机模式(或关闭该模块的时钟)。

    在主或从模式下的单向只接收模式(MSTR=1,BIDIMODE=0,RXONLY=1)或双向的接收模式(MSTR=1,BIDIMODE=1,BIDIOE=0)
    这种情况需要特别地处理,以保证SPI不会开始一次新的传输:

    1. 等待倒数第二个(第n-1个)RXNE=1;
    2. 在关闭SPI(SPE=0)之前等待一个SPI时钟周期(使用软件延迟);
    3. 在进入停机模式(或关闭该模块的时钟)之前等待最后一个RXNE=1。

    注: 在主模式下的单向只发送模式(MSTR=1,BDM=1,BDOE=0)时,传输过程中BSY标志始终为低。

    在从模式下的只接收模式(MSTR=0,BIDIMODE=0,RXONLY=1)或双向的接收模式(MSTR=0,BIDIMODE=1,BIDIOE=0)

    1. 可以在任何时候关闭SPI(SPE=0),SPI会在当前的传输结束后被关闭;
    2. 如果希望进入停机模式,在进入停机模式(或关闭该模块的时钟)之前必须首先等待BSY=0。

    9. 利用DMA的SPI通信

    为了达到最大通信速度,需要及时往SPI发送缓冲器填数据,同样接收缓冲器中的数据也必须及时读走以防止溢出。为了方便高速率的数据传输,SPI实现了一种采用简单的请求/应答的DMA机制。

    当SPI_CR2寄存器上的对应使能位被设置时,SPI模块可以发出DMA传输请求。发送缓冲器和接收缓冲器亦有各自的DMA请求(见)。
    ● 发送时,在每次TXE被设置为’1’时发出DMA请求,DMA控制器则写数据至SPI_DR寄存器,TXE标志因此而被清除。
    ● 接收时,在每次RXNE被设置为’1’时发出DMA请求,DMA控制器则从SPI_DR寄存器读出数据,RXNE标志因此而被清除。

    当只使用SPI发送数据时,只需使能SPI的发送DMA通道。此时,因为没有读取收到的数据,OVR被置为’1’(译注:软件不必理会这个标志)。当只使用SPI接收数据时,只需使能SPI的接收DMA通道。

    在发送模式下,当DMA已经传输了所有要发送的数据(DMA_ISR寄存器的TCIF标志变为’1’)后,可以通过监视BSY标志以确认SPI通信结束,这样可以避免在关闭SPI或进入停止模式时,破坏最后一个数据的传输。因此软件需要先等待TXE=1,然后等待BSY=0。

    注: 在不连续的通信中,在写数据到SPI_DR的操作与BSY位被置为’1’之间,有2个APB时钟周期的延迟,因此,在写完最后一个数据后需要先等待TXE=1再等待BSY=0。


    带CRC的DMA功能
    当使能SPI使用CRC检验并且启用DMA模式时,在通信结束时,CRC字节的发送和接收是自动完成的。
    数据和CRC传输结束时,SPI_SR寄存器的CRCERR标志为’1’表示在传输期间发生错误。

    10. 错误标志

    主模式失效错误(MODF)
    主模式失效仅发生在:NSS引脚硬件模式管理下,主设备的NSS脚被拉低;或者在NSS引脚软件模式管理下,SSI位被置为’0’时;MODF位被自动置位。主模式失效对SPI设备有以下影响:
    ● MODF位被置为’1’,如果设置了ERRIE位,则产生SPI中断;
    ● SPE位被清为’0’。这将停止一切输出,并且关闭SPI接口;
    ● MSTR位被清为’0’,因此强迫此设备进入从模式。

    下面的步骤用于清除MODF位:

    1. 当MODF位被置为’1’时,执行一次对SPI_SR寄存器的读或写操作;
    2. 然后写SPI_CR1寄存器。
      在有多个MCU的系统中,为了避免出现多个从设备的冲突,必须先拉高该主设备的NSS脚,再对MODF位进行清零。在完成清零之后,SPE和MSTR位可以恢复到它们的原始状态。出于安全的考虑,当MODF位为’1’时,硬件不允许设置SPE和MSTR位。通常配置下,从设备的MODF位不能被置为’1’。然而,在多主配置里,一个设备可以在设置了MODF位的情况下,处于从设备模式;此时,MODF位表示可能出现了多主冲突。中断程序可以执行一个复位或返回到默认状态来从错误状态中恢复。

    溢出错误
    当主设备已经发送了数据字节,而从设备还没有清除前一个数据字节产生的RXNE时,即为溢出错误。当产生溢出错误时:
    ● OVR位被置为’1’;当设置了ERRIE位时,则产生中断。
    此时,接收器缓冲器的数据不是主设备发送的新数据,读SPI_DR寄存器返回的是之前未读的数据,所有随后传送的数据都被丢弃。
    依次读出SPI_DR寄存器和SPI_SR寄存器可将OVR清除。

    CRC 错误
    当设置了SPI_CR寄存器上的CRCEN位时,CRC错误标志用来核对接收数据的有效性。如果移位寄存器中接收到的值(发送方发送的SPI_TXCRCR数值)与接收方SPI_RXCRCR寄存器中的数值不匹配,则SPI_SR寄存器上的CRCERR标志被置位为’1’。

    11. SPI中断

    三、SPI寄存器描述

    1. SPI控制寄存器 1(SPI_CR1)


    2. SPI控制寄存器 2(SPI_CR2)



    3. SPI 状态寄存器(SPI_SR)



    4. SPI 数据寄存器(SPI_DR)

    5. SPI CRC多项式寄存器(SPI_CRCPR)

    6. SPI Rx CRC寄存器(SPI_RXCRCR)

    7. SPI Tx CRC寄存器(SPI_TXCRCR)

    8. SPI_I2S配置寄存器(SPI_I2S_CFGR)


    9. SPI_I2S预分频寄存器(SPI_I2SPR)


    10. SPI 寄存器地址映象

    物联沃分享整理
    物联沃-IOTWORD物联网 » 深入解析SPI通信协议及工作原理

    发表评论