这是最新(主)开发分支的文档。如果您正在查找以前版本的文档,使用左侧的下拉菜单选择所需的版本。

SPI Master

简介

SPI 是一种高速的全双工同步串行通信协议。在 SPI 通信中,设备分为主设备(Master)和从设备(Slave)。SPI-Master 作为主控制器,负责发起通信过程,控制数据传输的时序和速率, 并管理整个通信流程。它在 SPI 通信中起主导作用,能够主动向 SPI 从设备发送指令或数据,并接收来自从设备的响应。

功能列表

  1. 初始化——初始化 SPI 驱动。

  2. 数据同步传输——数据传输完成或传输超时,结束传输。

  3. 数据异步传输——在数据传输完成后,结束传输并进入回调函数。

功能概述

全双工通信 SPI 同时支持数据的发送和接收,每个时钟周期内可以同时进行数据传输和接收

时钟控制 SPI Master 生成和控制串行时钟信号(SCLK),用于同步数据传输

片选管理 通过控制片选信号(CS),SPI-M 可以选择不同的从设备进行通信

数据传输控制 SPI Master 控制数据传输方向,并决定何时发送和接收数据

高传输速率 相比于 I2C 等接口,SPI 具有更高的传输速率,适用于高速数据传输的应用

SPI 有四种传输模式,如下表

SPI Mode

CPOL

CPHA

说明

Mode 0

0

0

空闲时 SCLK 为低电平,在上升沿对数据进行采样

Mode 1

0

1

空闲时 SCLK 为低电平,在下降沿对数据进行采样

Mode 2

1

0

空闲时 SCLK 为高电平,在下升沿对数据进行采样

Mode 3

1

1

空闲时 SCLK 为高电平,在上降沿对数据进行采样

SPI Master 硬件连线

SPI 连线示意图

初始化 SPI

使用 SPI 前需调用 wm_drv_spim_init() 函数为 SPI 分配资源,利用 wm_device_t 结构体接收 SPI 设备标识符。示例如下:

wm_device_t *spi_dev;
spi_dev=wm_drv_spim_init("spi");

初始化时只需要传入 "spi" 字符串即可进行

备注

  1. 如果 SPI 已经初始化,也可以直接调用 wm_dt_get_device_by_name 来获取 SPI 设备指针

  2. SPI 相关配置在设备树中去更改

SPI 同步传输

设置传输参数

  • 收发结束之后 API 才会返回,用户可设置最大等待时间,如果在该时间内,收发没有结束,也会立即返回。

  • SPI device 可利用 SPI 和 slave进行通信, SPI 使用了默认的 GPIO 引脚有3根,CLK: GPIO17, MISO:GPIO16, MOSI: GPIO21,如需修改,可在设备树中修改

  • 不同的 slave 需选择自己的 CS 引脚线, W800 提供的 CS GPIO 有: GPIO0, GPIO20, GPIO30, GPIO39

  • CS引脚以及其它参数都放在结构体 wm_dt_hw_spim_dev_cfg_t 当中

使用同步传输可调用 wm_drv_spim_transceive_sync() 并向其传递 wm_dt_hw_spim_dev_cfg_ttransceive_t 结构体,

1.SPI 设备参数配置

SPI 的传输频率、传输模式和引脚可在 wm_dt_hw_spim_dev_cfg_t 结构体中进行配置。配置示例如下:

wm_device_t *spi_dev;
spi_dev=wm_drv_spim_init("spi");

wm_dt_hw_spim_dev_cfg_t config = {
.freq = 2, //2M clock
.mode = 0,  // SPI modle
.pin_cs = {
    .pin_num = WM_GPIO_NUM_20,
    .pin_mux = WM_GPIO_IOMUX_FUN5,
    },
};

2.SPI 片选引脚配置

SPI 传输引脚需要单独进行配置,设置为浮空输出模式, 作为片选引脚,低电平有效。配置示例如下:

//SPI GPIO config
wm_drv_gpio_iomux_func_sel(config.pin_cs.pin_num, WM_GPIO_IOMUX_FUN5);
wm_drv_gpio_set_pullmode(config.pin_cs.pin_num, WM_GPIO_FLOAT);
wm_drv_gpio_set_dir(config.pin_cs.pin_num, WM_GPIO_DIR_OUTPUT);
wm_drv_gpio_data_set(config.pin_cs.pin_num);

3.SPI 传输参数配置

  • SPI 发送和传输的数据需要设置 tx_buffer 和 rx_buffer。需要发送的数据存储在 tx_buffer 中,接收到的数据存储在 rx_buffer 中

  • 支持 tx buffer 和 rx buffer 都不为空, 收发同时进行

  • 支持 tx buffer 为空, rx buffer 不为空, 只接收不发送数据

  • 支持 rx buffer 为空, tx buffer 不为空, 只发送不接收数据

配置示例如下:

uint32_t tx_len   = 8;
uint8_t *tx_buf   = NULL;
uint32_t rx_len   = 8;
uint8_t *rx_buf   = NULL;

tx_buf = malloc(tx_len);
rx_buf = malloc(rx_len);

transceive_t desc ={
.tx_buf=tx_buf,
.tx_len=tx_len,
.rx_buf=rx_buf,
.rx_len=rx_len,
};

启动同步传输数据

完成同步传输参数配置后可调用 wm_drv_spim_transceive_sync() 进行同步传输。需要传入设备描述符,SPI 设备参数、传输参数、超时时间:单位 ms

//set TX data
for (int i = 0; i < tx_len; i++) {
    tx_buf[i] = 0xAA;
}

wm_drv_spim_transceive_sync(spi_dev, &config, &desc, 1000);

去初始化 SPI

如不再需要使用 SPI 进行数据传输,则可调用 wm_drv_spim_deinit() 删除驱动程序,释放已分配的资源。

SPI 异步传输

设置传输参数

  • 调用该接口,相关参数给到驱动之后, API 就会理解返回, 底层收发结束会主动调用用户注册的 callback

  • SPI device 可利用 SPI 和 slave进行通信, SPI 使用了默认的 GPIO 引脚有3根,CLK: GPIO17, MISO:GPIO16, MOSI: GPIO21,如需修改,可在设备树中修改

  • 不同的 slave 需选择自己的 CS 引脚线, W800 提供的 CS GPIO 有: GPIO0, GPIO20, GPIO30, GPIO39

  • CS引脚以及其它参数都放在结构体 wm_dt_hw_spim_dev_cfg_t 当中

  • 使用同步传输可调用 wm_drv_spim_transceive_sync() 并向其传递 wm_dt_hw_spim_dev_cfg_ttransceive_t 结构体

1.SPI 设备参数配置

SPI 的传输频率、传输模式和引脚可在 wm_dt_hw_spim_dev_cfg_t 结构体中进行配置。配置示例如下:

wm_device_t *spi_dev;
spi_dev=wm_drv_spim_init("spi");

wm_dt_hw_spim_dev_cfg_t config = {
.freq = 2, //2M clock
.mode = 0,
.pin_cs = {
    .pin_num = WM_GPIO_NUM_20,
    .pin_mux = WM_GPIO_IOMUX_FUN5,
    },
};

2.SPI 片选引脚配置

SPI 传输引脚需要单独进行配置,设置为浮空输出模式, 作为片选引脚,低电平有效。配置示例如下:

//SPI GPIO config
wm_drv_gpio_iomux_func_sel(config.pin_cs.pin_num, WM_GPIO_IOMUX_FUN5);
wm_drv_gpio_set_pullmode(config.pin_cs.pin_num, WM_GPIO_FLOAT);
wm_drv_gpio_set_dir(config.pin_cs.pin_num, WM_GPIO_DIR_OUTPUT);
wm_drv_gpio_data_set(config.pin_cs.pin_num);

3.SPI 传输参数配置

  • SPI 发送和传输的数据需要设置 tx_buffer 和 rx_buffer ,需要发送的数据存储在 tx_buffer 中,接收到的数据存储在 rx_buffer 中

  • 支持 tx buffer 和 rx buffer 都不为空, 收发同时进行

  • 支持 tx buffer 为空, rx buffer 不为空, 只接收不发送数据

  • 支持 rx buffer 为空, tx buffer 不为空, 只发送不接收数据

配置示例如下:

uint32_t tx_len   = 8;
uint8_t *tx_buf   = NULL;
uint32_t rx_len   = 8;
uint8_t *rx_buf   = NULL;

tx_buf = malloc(tx_len);
rx_buf = malloc(rx_len);

transceive_t desc ={
.tx_buf=tx_buf,
.tx_len=tx_len,
.rx_buf=rx_buf,
.rx_len=rx_len,
};

4. 配置 SPI 回调函数

异步传输结束后会调用回调函数,该函数会传入整型的 result 和用户数据 data,返回的数据类型为 wm_spim_callback_t。具体示例如下:

void example_spim_aysnc_callback(int result, void *data){
    printf("SPI callback:transmit result:%d\n", result);
}

启动异步传输数据

完成异步传输参数配置后可调用 wm_drv_spim_transceive_sync() 进行同步传输。需要传入设备描述符,SPI 设备参数、传输参数、回调函数和用户数据。

//set TX data
for (int i = 0; i < tx_len; i++) {
    tx_buf[i] = 0xAA;
}

wm_drv_spim_transceive_async(spi_dev, &config, &desc, example_spim_aysnc_callback, NULL);

去初始化 SPI

如不再需要使用 SPI 进行数据传输,则可调用 wm_drv_spim_deinit() 删除驱动程序,释放已分配的资源。

注意事项

备注

  1. 收发的起始地址 4 字节对齐,以及长度 4 字节对齐能使 SPI 效率达到最高,

  2. 发送的长度最好不小于接收长度, 不然对方可能接收到一些无效数据

  3. 支持只发送或者只接收

  4. 收发长度没有限制

应用实例

使用 SPI 基本示例请参照 examples/peripheral/spi_master

API 参考

查找 SPI 相关 API 请参考:

SPI master API 参考