SPI Master
简介
SPI 是一种高速的全双工同步串行通信协议。在 SPI 通信中,设备分为主设备(Master)和从设备(Slave)。SPI-Master 作为主控制器,负责发起通信过程,控制数据传输的时序和速率, 并管理整个通信流程。它在 SPI 通信中起主导作用,能够主动向 SPI 从设备发送指令或数据,并接收来自从设备的响应。
功能列表
功能概述
全双工通信 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 前需调用
wm_drv_spim_init()
函数为 SPI 分配资源,利用wm_device_t
结构体接收 SPI 设备标识符。示例如下:wm_device_t *spi_dev; spi_dev=wm_drv_spim_init("spi");初始化时只需要传入
"spi"
字符串即可进行备注
如果 SPI 已经初始化,也可以直接调用
wm_dt_get_device_by_name
来获取 SPI 设备指针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_t
和transceive_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_t
和transceive_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()
删除驱动程序,释放已分配的资源。
注意事项
备注
收发的起始地址 4 字节对齐,以及长度 4 字节对齐能使 SPI 效率达到最高,
发送的长度最好不小于接收长度, 不然对方可能接收到一些无效数据
支持只发送或者只接收
收发长度没有限制
应用实例
使用 SPI 基本示例请参照 examples/peripheral/spi_master
API 参考
查找 SPI 相关 API 请参考: