1, 概述

串行外设接口(Serial Peripheral Interface Bus, SPI)是一种用于短程通信的同步串行通信接口规范,装置之间使用全双工模式通信,是一个主机和一个或多个从机的主从模式。SPI 使用 4 根线完成全双工的通信,这 4 根信号线分别是:CS(片选)、SCLK(时钟)、MOSI(主机输出从机输入)、MISO(主机输入从机输出)。

2, API参考

2.1 重要枚举、结构体介绍

2.1.1 SPI CLK枚举

  1. enum HAL_SPI_MOD_CLK_SEL_T {
  2. HAL_SPI_MOD_CLK_SEL_NONE,
  3. HAL_SPI_MOD_CLK_SEL_OSC,
  4. HAL_SPI_MOD_CLK_SEL_OSC_X2,
  5. HAL_SPI_MOD_CLK_SEL_PLL,
  6. };

2.1.2 SPI CTRL寄存器结构体

struct HAL_SPI_CTRL_T {
    uint32_t sspcr0_tx;
    uint32_t sspcr0_rx;
    uint16_t sspcr1;
    uint16_t sspcpsr;
    uint16_t sspdmacr;
    uint16_t ssprxcr_tx;
    uint16_t ssprxcr_rx;
    enum HAL_SPI_MOD_CLK_SEL_T clk_sel;
};

2.1.3 SPI配置结构体

struct HAL_SPI_CFG_T {
    uint32_t rate;           
    bool clk_delay_half :1;
    bool clk_polarity :1;
    bool slave :1;
    bool dma_rx :1;
    bool dma_tx :1;
    bool rx_sep_line :1;
    uint8_t cs;
    uint8_t tx_bits;
    uint8_t rx_bits;
    uint8_t rx_frame_bits;
};

2.1.4 SPI DMA模式枚举

enum SPI_RX_DMA_MODE_T {
    SPI_RX_DMA_MODE_NORMAL,
    SPI_RX_DMA_MODE_PINGPANG,
    SPI_RX_DMA_MODE_STREAM,
};

2.1.5 SPI DMA回调函数指针

typedef void (*HAL_SPI_DMA_HANDLER_T)(int error);

2.2 主要函数介绍

  • 在介绍函数前首先看一下SPI在7种工作模式下支持的API,每组API基本内容相似,只是用不同SPI_id调用一组后缀带_id的函数,因此接下来将在SPI模式下对API进行介绍

image.png

除上表中的API外,还有三个SPI通用API:寄存器初始化、睡眠、唤醒,这三个API所有SPI工作模式下都能使用

2.2.1 SPI CTRL寄存器初始化

  • 函数原型:

    int hal_spi_init_ctrl(const struct HAL_SPI_CFG_T *cfg, struct HAL_SPI_CTRL_T *ctrl);
    
  • 函数功能:初始化SPI的CTRL寄存器

  • 函数参数:
    • *cfg:SPI配置
    • *crtl:寄存器配置
  • 返回值:

    • 0:初始化完成

      2.2.2 SPI睡眠

  • 函数原型:

    void hal_spi_sleep(void);
    
  • 函数功能:使SPI进入睡眠模式

    2.2.3 SPI唤醒

  • 函数原型:

    void hal_spi_wakeup(void);
    
  • 函数功能:唤醒SPI

    2.2.4 SPI开启

  • 函数原型:

    int hal_spi_open(const struct HAL_SPI_CFG_T *cfg);
    
  • 函数功能:开启SPI

  • 函数参数:
    • *cfg:SPI配置
  • 返回值:

    • 片选信号值
    • -1:大于片选信号最大值

      2.2.5 SPI关闭

  • 函数原型:

    int hal_spi_close(uint32_t cs);
    
  • 函数功能:关闭SPI

  • 函数参数:
    • cs:需要一同关闭的片选信号
  • 返回值:

    • 0:关闭成功

      2.2.6 SPI启用片选

  • 函数原型:

    int hal_spi_activate_cs(uint32_t cs);
    
  • 函数功能:开启所选的SPI片选信号

  • 函数参数:
    • cs:需要开启的片选信号
  • 返回值:

    • 0:开启成功

      2.2.7 判断SPI是否繁忙

  • 函数原型:

    int hal_spi_busy(void);
    
  • 函数功能:判断SPI是否繁忙

  • 返回值:

    • 0:空闲
    • 1:繁忙

      2.2.8 SPI发送数据

  • 函数原型:

    int hal_spi_send(const void *data, uint32_t len);
    
  • 函数功能:SPI发送数据

  • 函数参数:
    • *data:待发送数据
    • len:待发送数据长度
  • 返回值:

    • -31:SPI正在使用中
    • -1:数据长度错误
    • 0:发送成功
    • 1:数据未完全发送

      2.2.9 SPI接收数据

  • 函数原型:

    int hal_spi_recv(const void *cmd, void *data, uint32_t len);
    
  • 函数功能:SPI接收数据

  • 函数参数:
    • *cmd:接收数据地址偏移量
    • *data:待接收数据
    • len:待接收数据长度
  • 返回值:

    • -31:SPI使用中
    • 0:接收成功
    • 1:接收失败

      2.2.10 SPI DMA使能与发送

  • 函数原型:

    int hal_spi_enable_and_send(const struct HAL_SPI_CTRL_T *ctrl,
                              const void *data, uint32_t len);
    
  • 函数功能:开启SPI并用DMA传输指定数据

  • 函数参数:
    • *ctrl:SPI控制寄存器配置
    • *data:待发送数据
    • len:待发送数据长度
  • 返回值:

    • -1:数据长度错误
    • 0:发送成功
    • 1:数据未完全发送

      2.2.11 SPI DMA使能与接收

  • 函数原型:

    int hal_spi_enable_and_recv(const struct HAL_SPI_CTRL_T *ctrl, const void *cmd, 
                              void *data, uint32_t len);
    
  • 函数功能:开启SPI并用DMA接收数据

  • 函数参数:
    • *ctrl:SPI控制寄存器配置
    • *cmd:接收数据地址偏移量
    • *data:待接收数据
    • len:待接收数据长度
  • 返回值:

    • 0:接收成功
    • 1:接收失败

      2.2.12 SPI DMA停止发送

  • 函数原型:

    void hal_spi_stop_dma_send(void);
    
  • 函数功能:SPI DMA发送停止

    2.2.13 SPI DMA停止接收

  • 函数原型:

    void hal_spi_stop_dma_recv(void);
    
  • 函数功能:SPI DMA接收停止

    3,使用教程

    3.1 头文件引用

    #include "hal_iomux.h"
    #include "hal_spi.h"
    

    3.2 SPI初始化与开启

  • 首先对SPI的IO口进行初始化,利用iomux头文件中的API即可

    void hal_iomux_set_spi(void);
    
  • 随后需要实例化HAL_SPI_CFG_T结构体

    static const struct HAL_SPI_CFG_T _spi_cfg_default =
    {
      .rate = 200000,
      .clk_delay_half = true,
      .clk_polarity = true,
      .slave = false,
      .dma_rx = true,
      .dma_tx = true,
      .rx_sep_line = true,
      .cs = 0,
      .tx_bits = 32,
      .rx_bits = 32,
      .rx_frame_bits = 0,
    };
    
  • 调用SPI开启接口

    hal_spi_open(&_spi_cfg_default);
    

    3.3 数据发送

  • SPI发送数据 ```c uint8_t cmd[4];

      cmd[0] = 0XAA;
      cmd[1] = 0X55;
      cmd[2] = 0XAA;
      cmd[3] = 0X55;
    

hal_spi_send(cmd, sizeof(cmd)); ```