STM32模拟SPI通信实现方法

目录

简介

spi物理层

连接方式

框图

协议层:

数据处理

传输模式

模式0

起始和停止信号

 发送和接收数据

模式1

模式2 

模式3

总结


简介

spi物理层

        SPI( Serial Peripheral Interface, 串行外设接口)是一种全双工同步串行通信接口,它用于MCU与各种外围设备以串行方式进行通信以交换信息,通信速度最高可达25MHz以上。SPI 总线具有三种传输方式:全双工、单工以及半双工传输方式。

        SPI通常由四条线组成,一条主设备输出与从设备输入( Master Output Slave Input, MOSI),一条主设备输入与从设备输出( Master Input Slave Output, MISO),一条时钟信号( Serial Clock, SCLK),一条从设备使能选择( Chip Select, CS)。与I²C类似,也可以使用GPIO模拟SPI时序

        SPI可以同时发出和接收数据,因此SPI的理论传输速度比I²C更快。 SPI通过片选引脚选择从机,一个片选一个从机,因此在多从机结构中,需要占用较多引脚,而I²C通过设备地址选择从机,只要设备地址不冲突,始终只需要两个引脚

连接方式

 

        CS片选线:从设备选择信号线,常称为片选信号线,也称为 NSS、 SS,无论有多少个从设备,都共同只使用这 3 条总线;而每个从设备都有独立的这一条 NSS 信号线,本信号线独占主机的一个引脚,即有多少个从设备,就有多少条片选信号线。当主机要选择从设备时,把该从设备的 CS信号线设置为低电平,该从设备即被选中,即片选有效,为开始信号;被拉高作为结束信号

        SCK :时钟信号线,用于通讯数据同步,两个设备之间通讯,速率受限于低速设备

        MOSI:主设备输出/从设备输入引脚,即这条线上数据的方向为主机到从机

        MISO:主设备输入/从设备输出引脚,即在这条线上数据的方向为从机到主机

框图

        ①STM32F10x芯片有3个 SPI 外设,SPI1 是 APB2 上的设备,最高通信速率达 36Mbtis/s, SPI2、 SPI3 是 APB1 上的设备,最高通信速率为 18Mbits/s,除了通讯速率,在其它功能上没有差异。因为SPI3 用到了下载接口的引脚,这几个引脚默认功能是下载,第二功能才是 IO 口,如果想使用 SPI3 接口,则程序上必须先禁用掉这几个 IO 口的下载功能。

        ②波特率发生器根据“控制寄存器 CR1”中的 BR[0:2] 位控制,对 fpclk 的分频结果就是 SCK 引脚的输出时钟频率

         配置“控制寄存器 CR”的“CPOL 位”及“CPHA”位可以把 SPI 设置成的 4 种 SPI模式,后续在协议层分析

        ③通过写 SPI 的“数据寄存器 DR”把数据填充到发送缓冲区中,通讯读“数据寄存器 DR”,可以获取接收缓冲区中的内容。其中数据帧长度可以通过“控制寄存器 CR1”的“DFF 位”配置成 8 位及 16 位模式;配置“LSBFIRST 位”可选择 MSB (高位)先行还是 LSB(低位) 先行

        ④:负责协调整个 SPI 外设,工作模式根据配置的“控制寄存器(CR1/CR2)”的参数而改变,控制参数包括前面提到的 SPI 模式、波特率、 LSB 先行、主从模式、单双向模式等等;在外设工作时,控制逻辑会根据外设的工作状态修改“状态寄存器(SR)”,我们只要读取状态寄存器相关的寄存器位,就可以了解 SPI 的工作状态了。

        一般不使用 STM32 SPI 外设的标准 NSS 信号线,而是更简单地使用普通的GPIO,软件控制它的电平输出,从而产生通讯起始和停止信号。也就是用模拟方式拉低拉高片选信号

协议层:

数据处理

        在SCK时钟周期的驱动下, MOSI和MISO同时进行,数据输入输出是同时进行的

         主机和从机都有一个移位寄存器,主机移位寄存器数据经过MOSI将数据写入从机的移位寄存器,此时从机移位寄存器的数据也通过MISO传给了主机,实现了两个移位寄存器的数据交换,外设的写操作和读操作是同步完成的。无论主机还是从机,发送和接收都是同时进行的,如同一个“环”
        如果主机只对从机进行写操作,主机只需忽略接收的从机数据即可。如果主机要读取从机数据,需要主机发送一个空数据来引发从机发送数据。

传输模式

        CPOL( Clock Polarity,时钟极性) 表示SCK在空闲时为高电平还是低电平。 当CPOL=0, SCK空闲时为低电平, 当CPOL=1, SCK空闲时为高电平。
        CPHA( Clock Phase,时钟相位) 表示SCK在第几个时钟边缘采样数据。 当CPHA=0, 在SCK第一个边沿采样数据,当CPHA=1, 在SCK第二个边沿采样数据 

        实际中采用较多的是“模式 0”与“模式 3”

模式0

        CPOL=0&&CPHA=0 的时序如下图,可以看到串行时钟的奇数边沿上升沿采样:

CPOL=0:看到对应时序中当数据未发送或者发送完毕, SCL 的状态是低电平;

CPHA=0:即是奇数边沿(第一个边沿)采集,可以看到传输的数据会在奇数边沿上升沿被采集;

MOSI和 MISO :数据的有效信号需要在 SCK 奇数边沿保持稳定且被采样,在非采样时刻(下降沿), MOSI 和MISO 的有效信号才发生变化

模式0

起始和停止信号

         NSS 信号线由高变低,是 SPI 通讯的起始信号。 NSS 是每个从机各自独占的信号线,当从机在自己的 NSS 线检测到起始信号后,就知自己被主机选中了,开始准备与主机通讯。

void spi_start(void)
{
    /*片选线高电平拉低*/
    ctrl_cs(0);
}

        NSS 信号由低变高,是 SPI 通讯的停止信号,表示本次通讯结束,从机的选中状态被取消

void spi_stop(void)
{
    /*片选线低电平拉高*/
    ctrl_cs(1);
}
 发送和接收数据
/*数据交换(收发)*/
uint8_t spi_swap_byte(uint8_t byte_send)
{
    uint8_t i,byte_receive = 0x00;
    for(i=0;i<8;i++)
    {
        /*开始sck默认低电平,现在就可以交换数据*/
        ctrl_mosi(byte_send & (0x80 >> i));/*通过控制对应的GPIO进行高位先发*/
        ctrl_sck(1);/*控制对应的GPIO拉高sck读取数据*/
        if(1 == read_miso())/*读取对应的GPIO接收数据*/
        {
            byte_receive |= (0x80 >> i);
        }
        ctrl_sck(0);/*拉低时钟结束*/
    }
    return byte_receive;/*交换得到的数据*/
}
模式1

        CPOL=0&CPHA=1 的时序如下图,串行时钟的偶数边沿下降沿采样:

CPOL=0:所以 SCL 的空闲状态依然是低电平

CPHA=1: 数据就从偶数边沿(第二个边沿)采样,下降沿

模式1
模式2 

         CPOL=1&&CPHA=0 的时序如下图

CPOL=1:SCL 空闲状态为高电平

CPHA=0:奇数边沿采样的情况下,数据在奇数边沿下降沿要保持稳定并等待采样

模式2
模式3

          CPOL=1&&CPHA=1 的时序如下图

CPOL=1:SCL状态是高电平,奇数边沿的边沿极性是上升沿,偶数边沿的边沿极性是下降沿
CPHA=1:数据在偶数边沿上升沿被采样。

在奇数边沿的时候 MOSI 和 MISO 会发生变化,在偶数边沿时候是稳定的。

总结

        先看CPHA,时钟相位为0,第一个(奇)边沿采样;为1,第二个(偶)边沿采样;再看CPOL,时钟极性为0,说明空闲的时候是低电平,低电平第一个采样信号肯定是拉高,由此判断是上升沿还是下降沿采样;同理时钟极性为1,说明空闲的时候是高电平,高电平第一个采样信号肯定是拉低,由此判断是上升沿还是下降沿采样

作者:把车开起来

物联沃分享整理
物联沃-IOTWORD物联网 » STM32模拟SPI通信实现方法

发表评论