i.MX6ull-SPI总线

一、SPI介绍

        SPI(Serial Peripheral Interface) 串行外围设备接口。是由Motorola公司开发,用来在微控制器和外围 设备芯片之间提供一个低成本、易使用的接口。这种接口可以用来连接存储器、AD转换器、DA转换 器、实时时钟、LCD驱动器、传感器、音频芯片、甚至其他处理器。
        与标准的串行端口不同, SPI是一个同步协议接口 ,所有的传输都参照一个共同的时钟,这个同步时钟 信号由主机(理器)产生。 接收数据的外设(从设备)使用时钟对串行比特流的接收进行同步化 当有多个 芯片连接到主机的同一个SPI接口上 这时主机通过触发从设备芯片的片选输入引脚[片选管脚]来选择接 收数据的从设备 ,没有被选中的外设将不会参与SPI传输。
        SPI主要使用4个信号:
                主机输输出/从机输入(MOSI: Master Output Slave Input)
                主机输入/从机输出(MISO:Master Input Slave Output)
                串行时钟(SCLK或SCK)
                外设片选管脚(CS)

1.1 主机和从机连接方式

1.2 主机和从机数据传输

        主机和从机都包含一个串行移位器,主机通过向它的SPI串行移位器写入一个字节发起一次传输。 移位 器通过MOSI信号线将字节传送给从机,从机也将自己的移位器中的内容通过MISO信号线返回给主机。 这样两个移位寄存器中的内容就被交换了。 从机的写操作和读操作时同步完成的,因此SPI成为一个很 有效的协议。
        注意:
                如果只是进行写操作,主机只需忽略收到的字节;反过来,如果主机要读取从机的一个字
节,就必须发送一个空字节来引发从机的传输。

二、SPI时序

        通过SPI线在主机和从机之间传输数据,必须保证主机发出的时序和从机所要求的时序一致才可以。在SPI总线时序中有两个非常重要的概念。

2.1 时钟极性与时钟相位

时钟极性
        Clock Polarity :简称CPOL或POL, 指SPI CLK在空闲时的电平是0还是1
时钟相位
Clock Phase :简称CPHA或PHA, 指数据采样的时候,是CLK的第一个边沿还是第二个边沿。
        CPHA=0,CLK的第一个边沿采样
        CPHA=1,CLK的第二个边沿采样
将CPOL和CPHA进行组合,可以得到SPI主要有四种模式的时序
对应到时序图的关系如下:

2.2 SPI的四种时序

1 CPOL = 0,CPHA = 0

        SPI CLK空闲时为低电平,所以CPOL=0,CLK的第一个边沿采样,所以 CPHA=0
.2 CPOL = 0,CPHA = 1
        SPI CLK空闲时为低电平,所以CPOL=0,CLK的第二个边沿采样,所以 CPHA=1
3 CPOL = 1,CPHA = 0
        SPI CLK空闲时为高电平,所以CPOL=1,CLK第一个边沿采样,所以CPHA=0
4 CPOL = 1,CPHA = 1
        
SPI CLK空闲时为高电平,所以CPOL=1,CLK第二个边沿采样,所以 CPHA=1

三、i.MX6ull SPI控制器介绍

        spi增强型可配置串行外设接口(ECSPI)是一种全双工、同步、四线串行通信 模块。
        ECSPI具有64 x 32位接收缓冲区(RXFIFO)和64 x 32位发送缓冲区 (TXFIFO),可以在减少软件中断的情况下实现快速数据通信。ECSPI的框 图如下所示。

3.1 主要特性

        全双工同步串行接口
       主/从模式可配置
        四个片选(SS)信号以支持多个外围设备
        传输延续功能可实现无限长度的数据传输
        传输和接收数据的FIFO为32位宽,有64个存储单元
        SPI时钟(SCLK)和片选(SS)的极性和相位可配置
        支持直接内存访问(DMA)
        最大操作频率可达到参考时钟频率。

3.2 Clocks

        eCSPI的时钟源如下表所示。请参阅时钟控制器模块(CCM)时钟设置,配置和门控信息。

3.3 Master Mode

        当ECSPI配置为主设备时,它使用串行链路在ECSPI和外部从设备之间传输数据.
        时钟信号(SCLK)和芯片选择(SS)信号中的一个用于在两个设备之间传输 数据。如果外部设备是仅传输设备,则可以忽略ECSPI主机的输出端口并 将其用于其他目的。为了使用内部的TXFIFO和RXFIFO,使用两个辅助输 出信号Chip Select (SS)和SPI_RDY来控制数据传输速率。软件还可以 将采样周期控制寄存器配置为固定的数据传输率
        ECSPI主机使用芯片选择(SS)信号启用外部SPI设备,并使用SCLK信号将 数据传输到移位寄存器内外。
        SPI_RDY支持以较少的软件中断进行快速数据通信。通过相应地编程ECSPI_PERIODREG寄存器,ECSPI可以用于固定的数据传输速率。
        当ECSPI处于主模式时,SS、SCLK和MOSI为输出信号,MISO为输入信号。
        在上图中,芯片选择(SS)信号启用选定的外部SPI设备,SCLK同步数据 搬迁。MOSI和MISO信号沿SCLK的上升沿变化,MISO信号锁存在SCLK的下降沿。上图显示一个0xD2的数据移出, 一个0x66的数据移入。

四. spi和i2c的区别

SPI 总线和 I2C(Inter - Integrated Circuit)总线都是常见的串行通信总线,在嵌入式系统中广泛应用,以下从多个方面对它们进行比较:

4.1. 硬件连接

 
  • SPI
    • 通常需要 4 根线进行全双工通信,分别是时钟线(SCK)、主出从入线(MOSI)、主入从出线(MISO)和从设备选择线(SS)。当连接多个从设备时,每个从设备都需要一根独立的 SS 线,硬件连接相对复杂,但这种方式使得主设备可以快速选择特定的从设备进行通信。
  • I2C
    • 只需要两根线,即串行数据线(SDA)和串行时钟线(SCL)。所有的主设备和从设备都连接到这两根总线上,通过设备地址来识别不同的从设备,硬件连接简单,节省了微控制器的引脚资源。

4.2. 通信方式

 
  • SPI
    • 是全双工通信方式,主设备和从设备可以同时进行数据的发送和接收,数据传输效率高,适用于需要高速数据交换的场景,例如高速数据采集、大容量存储设备的数据读写等。
  • I2C
    • 是半双工通信方式,同一时刻只能进行单向的数据传输,要么主设备向从设备发送数据,要么从设备向主设备发送数据,数据传输效率相对较低,但能满足大多数低速外设的通信需求。

4.3. 同步方式

 
  • SPI
    • 属于同步通信,主设备提供时钟信号(SCK),主从设备依据该时钟信号同步进行数据传输,确保数据准确收发,即使在高速通信时也能保证较好的稳定性。
  • I2C
    • 同样是同步通信,主设备在 SCL 线上产生时钟信号来同步数据传输。不过,I2C 总线允许从设备在处理数据较慢时拉低 SCL 线,强制主设备等待,这种机制称为时钟拉伸,增加了通信的灵活性,但也可能降低整体通信速度。

4.4. 寻址方式

 
  • SPI
    • 没有统一的寻址机制,主设备通过拉低相应从设备的 SS 线来选择与之通信的从设备。这种方式简单直接,通信速度快,但当从设备数量较多时,会占用较多的主设备引脚。
  • I2C
    • 采用设备地址进行寻址,每个从设备都有唯一的 7 位或 10 位地址。主设备在通信开始时,会在总线上发送要通信的从设备地址,只有地址匹配的从设备才会响应主设备的请求。这种寻址方式使得 I2C 总线上可以连接多个从设备,最多理论上可以连接 127 个 7 位地址的从设备。

4.5. 传输速率

 
  • SPI
    • 传输速率较高,一般可以达到几兆赫兹甚至几十兆赫兹,能够满足高速数据传输的要求,如与高速 ADC、DAC 芯片通信,或者进行大容量数据的快速读写。
  • I2C
    • 传输速率相对较低,标准模式下传输速率为 100kbps,快速模式下可达 400kbps,高速模式下能达到 3.4Mbps。不过,大多数应用场景中 I2C 的速率已经能够满足需求。

4.6. 总线仲裁

 
  • SPI
    • 由于每个从设备有独立的 SS 线,主设备直接控制与哪个从设备进行通信,不存在总线仲裁问题,设计和实现相对简单。
  • I2C
    • 多个主设备可以连接到同一 I2C 总线上,当多个主设备同时尝试发起通信时,需要进行总线仲裁来决定哪个主设备可以占用总线。总线仲裁机制基于 SDA 线上的电平竞争,确保通信的有序进行,但增加了系统的复杂性。

五. 代码实现

        SPI硬件原理图分析

回环测试SPI通信是否正常:
#include "spi.h"

// 管脚初始化
void spi_gpio_init()
{
    IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO21 &= ~(0xf << 0);
    IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO21 |= (0x8 << 0);

    IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO20 &= ~(0xf << 0);
    IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO20 |= (0x8 << 0);

    IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO22 &= ~(0xf << 0);
    IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO22 |= (0x8 << 0);

    IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO23 &= ~(0xf << 0);
    IOMUXC_SW_MUX_CTL_PAD_GPIO1_IO23 |= (0x8 << 0);
}

// 控制器初始化
void spi_controller_init()
{
    // 1,将该寄存器所有位清零
    ECSPI3->CONREG &= 0;
    ECSPI3->CONREG = (0x7 << 20) | (0x9 << 12) | (0x1 << 3) | (0x1 << 0);
    return;
}

// spi通道配置
void spi_channel_config(uint_fast8_t channel, uint_fast8_t pol, uint_fast8_t pha)
{
    // 1,选择通道
    ECSPI3->CONREG |= (channel << 18);
    // 2,通道模式选择
    ECSPI3->CONREG |= (0x1 << (channel + 4));
    // 3,设置极性和相位
    ECSPI3->CONREG |= (pol << 4);
    ECSPI3->CONREG |= (pha << 0);
}
// 片选信号
// 开始信号
void spi_start_signal()
{
    GPIO1->GDIR |= (0x1 << 3);
    GPIO1->DR &= ~(1 << 3);
}
// 结束信号
void spi_stop_signal()
{
    GPIO1->GDIR |= (0x1 << 3);
    GPIO1->DR |= (1 << 3);
}

// 数据传送
uint_fast8_t spi_data_transfer(uint_fast8_t data)
{
    // 保存接受的数据
    uint_fast8_t result;
    // 保存传输的数据
    ECSPI3->TXDATA = data;
    // 判断发送有没有完成
    int flag;
    do
    {
        flag = ECSPI3->STATREG & (0x1 << 1);
    } while (!flag);

    // 接受数据
    do
    {
        /* code */
        flag = ECSPI3->STATREG & (1 << 3);
    } while (!flag);

    result = ECSPI3->RXDATA ;

    return result;
}

    // 测试

void spi_test()
{
    spi_gpio_init();
    spi_controller_init();
    spi_channel_config(1, 0, 1); // 通道为1,极性为0,相位为1
    // 发送数据
    char c;
    while (1)
    {
        for (c = 'a'; c <= 'z'; c++)
        {
            spi_start_signal();
            uint_fast8_t rx_data = spi_data_transfer(c);
            spi_start_signal();
            uart_printf("rx_data=%d\r\n", rx_data);
            delay_ms(500);
        }
    }

    return;
}

        总的来说,SPI适用于对数据传输速率要求较高、通信距离较短、从设备数量相对较少的场景,比如LCD 显示驱动.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值