超简单的SPI流程讲解附录SPI程序


一、SPI概述

另一种超级常用的硬件协议就是SPI协议,I2C的速度上限是400Khz,速度想更快点的话可以使用SPI通信。
SPI 是 Motorola 公司推出的一种同步串行接口技术,是一种高速、全双工的同步通信总线, SPI 时钟频率相比 I2C 要高很多,最高可以工作在上百 MHz。 SPI一般为4线也可以是3线。


常见的为四线模式,分别是下面四根线

CS/SS片选信号线,选择需要进行通信的从设备。拉低有效。
SCK串行时钟信号线,为SPI提供时钟(主机发出)
MOSI/SDO主出从入信号线,主机向从机发送数据。
MISO/SDI主入从出信号线,从机向主机发送数据。

一、SPI通信硬件连接图

SPI协议的建立需要主机发出SCK信号,主从机的MISO\MOSI连接,下图是个简单的一主三从连接示意图
MOSI:Master Out Slave In,主机数据出从机数据入即从机发主机收
MISO:Master In Slave Out,主机数据入从机数据出即主机发从机收
在这里插入图片描述

二、SPI工作模式

与I2C协议不同,SPI有个工作模式的区别,SPI一共有四种工作模式,通过串行时钟极性(CPOL)和相位(CPHA)两两组合得到。
①、 CPOL=0,串行时钟空闲状态为低电平。
②、 CPOL=1,串行时钟空闲状态为高电平。
③、 CPHA=0,串行时钟的第一个跳变沿(上升沿或下降沿)采集数据。
④、 CPHA=1,串行时钟的第二个跳变沿(上升沿或下降沿)采集数据。

模式组合
0CPOL=0,CPHA=0 SCL,SDA空闲为低电平,在SCL上升沿采集数据(最常用的模式)
1CPOL=0,CPHA=1
2CPOL=1,CPHA=0
3CPOL=1,CPHA=1

三、为什么SPI会有这么多种工作模式,而I2C没有?

I2C的硬件连接决定了I2C的模式较为单一,I2C的硬件有两个上拉的4.7K电阻,所以I2C总线上,默认的空闲状态为SDA和SCL都为高
即为空闲模式
在这里插入图片描述
相位的概念:
相位描述的比较抽象了,同步通信是共用一个时钟源SCL的,一个时钟周期内只有一个上升沿一个下降沿,数据的变化都是在边沿发生的,边沿可能是上升沿也可能是下降沿,可能是前一个沿也可能是后一个沿,所以区分相位,参考下图四种模式的图解,这里我建议不理解的记住模式0就行,后面实战中用几次就会明白了。

在这里插入图片描述

四、SPI时序,以模式0详细讲解

在这里插入图片描述
①.CS片选拉低,整个通讯周期都是拉低,拉高意味结束
②.此时主机上的SCLK和MOSI和MISO都是拉低的,空闲状态
③.SCLK拉高,拉高期间,MOSI和MISO上的数据变化都是有效的,MOSI发送了高电平到从机,MISO接受到了从机的低电平,
数据发送了8个bit
④.CS拉高了,通信结束,收发各8bit

最终通信数据:
主机发从机:11010010
从机发主机:01100110


五、关于模式1,2,3

附录SPI通信代码

个人项目上的SPI裸机代码,保证可用,很多刚接触单片机的搞不清主从机概念,简单来说主机就是你的MCU,从机就是你要通信的芯片,
一般从机可能是FLASH芯片,DAC,ADC芯片等等,也有可能是两个mcu之间的通信但是得看你的mcu是否支持从机模式,两个MCU之间通信的方式太多了,使用SPI我感觉是有点麻烦了。485会是个不错的选择。

代码如下

// SPI 发送数据代码
static void spiBusSendData(uint8_t data)
{
    uint8_t i = 0;


    for (i = 0; i < 8; i++)
    {
        (data & 0x80) ?  writeGpioPin(Board_SPI_FLASH_CPLD_MOSI, 1) : writeGpioPin(Board_SPI_FLASH_CPLD_MOSI, 0);  //如果data最高位为1写入1否则写入0
        data <<= 1;  //写入1位后左移1位,次高位变成最高位
        writeGpioPin(Board_SPI_FLASH_CPLD_CLK, 1);
  CPUdelay(1);/* 3 cycles per loop: 1 loop @ 48 Mhz ~= 62 ns */
  writeGpioPin(Board_SPI_FLASH_CPLD_CLK, 0);
  CPUdelay(1);/* 3 cycles per loop: 1 loop @ 48 Mhz ~= 62 ns */
 }
}

// SPI写数据代码
static uint8_t spiBusRecvData(void)
{
    uint8_t i = 0;
    uint8_t data = 0;


    for (i = 0; i < 8; i++)
    {
        writeGpioPin(Board_SPI_FLASH_CPLD_CLK, 1);
        CPUdelay(1);/* 3 cycles per loop: 1 loop @ 48 Mhz ~= 62 ns */
  		data <<= 1;
   if (readGpioPin(Board_SPI_FLASH_CPLD_MISO))
        {
            data |= 0x01;
        }
  writeGpioPin(Board_SPI_FLASH_CPLD_CLK, 0);
  CPUdelay(1);/* 3 cycles per loop: 1 loop @ 48 Mhz ~= 62 ns */
    }


    return data;
}

  • 27
    点赞
  • 35
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值