1e41f4b71Sopenharmony_ci# SPI 2e41f4b71Sopenharmony_ci 3e41f4b71Sopenharmony_ci## 概述 4e41f4b71Sopenharmony_ci 5e41f4b71Sopenharmony_ci### 功能简介 6e41f4b71Sopenharmony_ci 7e41f4b71Sopenharmony_ciSPI指串行外设接口(Serial Peripheral Interface),是一种高速的,全双工,同步的通信总线。SPI是由Motorola公司开发,用于在主设备和从设备之间进行通信。 8e41f4b71Sopenharmony_ci 9e41f4b71Sopenharmony_ciSPI接口定义了操作SPI设备的通用方法集合,包括: 10e41f4b71Sopenharmony_ci 11e41f4b71Sopenharmony_ci- SPI设备句柄获取和释放。 12e41f4b71Sopenharmony_ci 13e41f4b71Sopenharmony_ci- SPI读写:从SPI设备读取或写入指定长度数据。 14e41f4b71Sopenharmony_ci 15e41f4b71Sopenharmony_ci- SPI自定义传输:通过消息传输结构体执行任意读写组合过程。 16e41f4b71Sopenharmony_ci 17e41f4b71Sopenharmony_ci- SPI设备配置:获取和设置SPI设备属性。 18e41f4b71Sopenharmony_ci 19e41f4b71Sopenharmony_ci### 运作机制 20e41f4b71Sopenharmony_ci 21e41f4b71Sopenharmony_ci在HDF框架中,SPI的接口适配模式采用独立服务模式,在这种模式下,每一个设备对象会独立发布一个设备服务来处理外部访问,设备管理器收到API的访问请求之后,通过提取该请求的参数,达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力,但需要为每个设备单独配置设备节点,若设备过多可能增加内存占用。 22e41f4b71Sopenharmony_ci 23e41f4b71Sopenharmony_ci独立服务模式下,核心层不会统一发布一个服务供上层使用,因此这种模式下驱动要为每个控制器发布一个服务,具体表现为: 24e41f4b71Sopenharmony_ci 25e41f4b71Sopenharmony_ci- 驱动适配者需要实现HdfDriverEntry的Bind钩子函数以绑定服务。 26e41f4b71Sopenharmony_ci 27e41f4b71Sopenharmony_ci- device_info.hcs文件中deviceNode的policy字段为1或2,不能为0。 28e41f4b71Sopenharmony_ci 29e41f4b71Sopenharmony_ci**图 1** SPI独立服务模式结构图<a name="fig1"></a> 30e41f4b71Sopenharmony_ci 31e41f4b71Sopenharmony_ci 32e41f4b71Sopenharmony_ci 33e41f4b71Sopenharmony_ciSPI模块各分层作用: 34e41f4b71Sopenharmony_ci 35e41f4b71Sopenharmony_ci- 接口层提供打开SPI设备、SPI写数据、SPI读数据、SPI传输、配置SPI设备属性、获取SPI设备属性、关闭SPI设备的接口。 36e41f4b71Sopenharmony_ci 37e41f4b71Sopenharmony_ci- 核心层主要提供SPI控制器的添加、移除以及管理的能力,通过钩子函数与适配层交互。 38e41f4b71Sopenharmony_ci 39e41f4b71Sopenharmony_ci- 适配层主要是将钩子函数的功能实例化,实现具体的功能。 40e41f4b71Sopenharmony_ci 41e41f4b71Sopenharmony_ciSPI以主从方式工作,通常有一个主设备和一个或者多个从设备。主设备和从设备之间一般用4根线相连,它们分别是: 42e41f4b71Sopenharmony_ci 43e41f4b71Sopenharmony_ci- SCLK:时钟信号,由主设备产生; 44e41f4b71Sopenharmony_ci 45e41f4b71Sopenharmony_ci- MOSI:主设备数据输出,从设备数据输入; 46e41f4b71Sopenharmony_ci 47e41f4b71Sopenharmony_ci- MISO:主设备数据输入,从设备数据输出; 48e41f4b71Sopenharmony_ci 49e41f4b71Sopenharmony_ci- CS:片选,从设备使能信号,由主设备控制。 50e41f4b71Sopenharmony_ci 51e41f4b71Sopenharmony_ci一个主设备和两个从设备的连接示意图如图2所示,Device A和Device B共享主设备的SCLK、MISO和MOSI三根引脚,Device A的片选CS0连接主设备的CS0,Device B的片选CS1连接主设备的CS1。 52e41f4b71Sopenharmony_ci 53e41f4b71Sopenharmony_ci**图 2** SPI主从设备连接示意图 54e41f4b71Sopenharmony_ci 55e41f4b71Sopenharmony_ci 56e41f4b71Sopenharmony_ci 57e41f4b71Sopenharmony_ci- SPI通信通常由主设备发起,通过以下步骤完成一次通信: 58e41f4b71Sopenharmony_ci 59e41f4b71Sopenharmony_ci 1. 通过CS选中要通信的从设备,在任意时刻,一个主设备上最多只能有一个从设备被选中。 60e41f4b71Sopenharmony_ci 61e41f4b71Sopenharmony_ci 2. 通过SCLK给选中的从设备提供时钟信号。 62e41f4b71Sopenharmony_ci 63e41f4b71Sopenharmony_ci 3. 基于SCLK时钟信号,主设备数据通过MOSI发送给从设备,同时通过MISO接收从设备发送的数据,完成通信。 64e41f4b71Sopenharmony_ci 65e41f4b71Sopenharmony_ci- 根据SCLK时钟信号的CPOL(Clock Polarity,时钟极性)和CPHA(Clock Phase,时钟相位)的不同组合,SPI有以下四种工作模式: 66e41f4b71Sopenharmony_ci 67e41f4b71Sopenharmony_ci - CPOL=0,CPHA=0 时钟信号idle状态为低电平,第一个时钟边沿采样数据。 68e41f4b71Sopenharmony_ci 69e41f4b71Sopenharmony_ci - CPOL=0,CPHA=1 时钟信号idle状态为低电平,第二个时钟边沿采样数据。 70e41f4b71Sopenharmony_ci 71e41f4b71Sopenharmony_ci - CPOL=1,CPHA=0 时钟信号idle状态为高电平,第一个时钟边沿采样数据。 72e41f4b71Sopenharmony_ci 73e41f4b71Sopenharmony_ci - CPOL=1,CPHA=1 时钟信号idle状态为高电平,第二个时钟边沿采样数据。 74e41f4b71Sopenharmony_ci 75e41f4b71Sopenharmony_ci### 约束与限制 76e41f4b71Sopenharmony_ci 77e41f4b71Sopenharmony_ciSPI模块当前只支持主机模式,不支持从机模式。 78e41f4b71Sopenharmony_ci 79e41f4b71Sopenharmony_ci## 使用指导 80e41f4b71Sopenharmony_ci 81e41f4b71Sopenharmony_ci### 场景介绍 82e41f4b71Sopenharmony_ci 83e41f4b71Sopenharmony_ciSPI通常用于与闪存、实时时钟、传感器以及模数/数模转换器等支持SPI协议的设备进行通信。 84e41f4b71Sopenharmony_ci 85e41f4b71Sopenharmony_ci### 接口说明 86e41f4b71Sopenharmony_ci 87e41f4b71Sopenharmony_ciSPI模块提供的主要接口如表1所示,具体API详见//drivers/hdf_core/framework/include/platform/spi_if.h。 88e41f4b71Sopenharmony_ci 89e41f4b71Sopenharmony_ci**表 1** SPI驱动API接口功能介绍 90e41f4b71Sopenharmony_ci 91e41f4b71Sopenharmony_ci| 接口名 | 接口描述 | 92e41f4b71Sopenharmony_ci| -------- | -------- | 93e41f4b71Sopenharmony_ci| DevHandle SpiOpen(const struct SpiDevInfo \*info) | 获取SPI设备句柄 | 94e41f4b71Sopenharmony_ci| void SpiClose(DevHandle handle) | 释放SPI设备句柄 | 95e41f4b71Sopenharmony_ci| int32_t SpiRead(DevHandle handle, uint8_t \*buf, uint32_t len) | 读取指定长度的数据 | 96e41f4b71Sopenharmony_ci| int32_t SpiWrite(DevHandle handle, uint8_t \*buf, uint32_t len) | 写入指定长度的数据 | 97e41f4b71Sopenharmony_ci| int32_t SpiTransfer(DevHandle handle, struct SpiMsg \*msgs, uint32_t count) | SPI数据传输接口 | 98e41f4b71Sopenharmony_ci| int32_t SpiSetCfg(DevHandle handle, struct SpiCfg \*cfg) | 根据指定参数,配置SPI设备 | 99e41f4b71Sopenharmony_ci| int32_t SpiGetCfg(DevHandle handle, struct SpiCfg \*cfg) | 获取SPI设备配置参数 | 100e41f4b71Sopenharmony_ci 101e41f4b71Sopenharmony_ci### 使用流程 102e41f4b71Sopenharmony_ci 103e41f4b71Sopenharmony_ci使用SPI的一般流程如下图所示。 104e41f4b71Sopenharmony_ci 105e41f4b71Sopenharmony_ci**图 3** SPI使用流程图 106e41f4b71Sopenharmony_ci 107e41f4b71Sopenharmony_ci 108e41f4b71Sopenharmony_ci 109e41f4b71Sopenharmony_ci#### 获取SPI设备句柄 110e41f4b71Sopenharmony_ci 111e41f4b71Sopenharmony_ci在使用SPI进行通信时,首先要调用SpiOpen获取SPI设备句柄,该函数会返回指定总线号和片选号的SPI设备句柄。 112e41f4b71Sopenharmony_ci 113e41f4b71Sopenharmony_ci```c 114e41f4b71Sopenharmony_ciDevHandle SpiOpen(const struct SpiDevInfo *info); 115e41f4b71Sopenharmony_ci``` 116e41f4b71Sopenharmony_ci 117e41f4b71Sopenharmony_ci**表 2** SpiOpen参数和返回值描述 118e41f4b71Sopenharmony_ci 119e41f4b71Sopenharmony_ci| **参数** | **参数描述** | 120e41f4b71Sopenharmony_ci| -------- | -------- | 121e41f4b71Sopenharmony_ci| info | 结构体类型,SPI设备描述符 | 122e41f4b71Sopenharmony_ci| **返回值** | **返回值描述** | 123e41f4b71Sopenharmony_ci| NULL | 获取SPI设备句柄失败 | 124e41f4b71Sopenharmony_ci| 设备句柄 | 获取对应的SPI设备句柄成功 | 125e41f4b71Sopenharmony_ci 126e41f4b71Sopenharmony_ci假设系统中的SPI设备总线号为0,片选号为0,获取该SPI设备句柄的示例如下: 127e41f4b71Sopenharmony_ci 128e41f4b71Sopenharmony_ci```c 129e41f4b71Sopenharmony_cistruct SpiDevInfo spiDevinfo; // SPI设备描述符 130e41f4b71Sopenharmony_ciDevHandle spiHandle = NULL; // SPI设备句柄 131e41f4b71Sopenharmony_cispiDevinfo.busNum = 0; // SPI设备总线号 132e41f4b71Sopenharmony_cispiDevinfo.csNum = 0; // SPI设备片选号 133e41f4b71Sopenharmony_ci 134e41f4b71Sopenharmony_ci// 获取SPI设备句柄 135e41f4b71Sopenharmony_cispiHandle = SpiOpen(&spiDevinfo); 136e41f4b71Sopenharmony_ciif (spiHandle == NULL) { 137e41f4b71Sopenharmony_ci HDF_LOGE("SpiOpen: spi open fail!\n"); 138e41f4b71Sopenharmony_ci return HDF_FAILURE; 139e41f4b71Sopenharmony_ci} 140e41f4b71Sopenharmony_ci``` 141e41f4b71Sopenharmony_ci 142e41f4b71Sopenharmony_ci#### 获取SPI设备属性 143e41f4b71Sopenharmony_ci 144e41f4b71Sopenharmony_ci在获取到SPI设备句柄之后,需要配置SPI设备属性。配置SPI设备属性之前,可以先获取SPI设备属性,获取SPI设备属性的函数如下所示: 145e41f4b71Sopenharmony_ci 146e41f4b71Sopenharmony_ci```c 147e41f4b71Sopenharmony_ciint32_t SpiGetCfg(DevHandle handle, struct SpiCfg *cfg); 148e41f4b71Sopenharmony_ci``` 149e41f4b71Sopenharmony_ci 150e41f4b71Sopenharmony_ci**表 3** SpiGetCfg参数和返回值描述 151e41f4b71Sopenharmony_ci 152e41f4b71Sopenharmony_ci| **参数** | **参数描述** | 153e41f4b71Sopenharmony_ci| -------- | -------- | 154e41f4b71Sopenharmony_ci| handle | DevHandle类型,SPI设备句柄 | 155e41f4b71Sopenharmony_ci| cfg | 结构体指针类型,SPI设备配置参数 | 156e41f4b71Sopenharmony_ci| **返回值** | **返回值描述** | 157e41f4b71Sopenharmony_ci| HDF_SUCCESS | 获取设备属性成功 | 158e41f4b71Sopenharmony_ci| 负数 | 获取设备属性失败 | 159e41f4b71Sopenharmony_ci 160e41f4b71Sopenharmony_ci```c 161e41f4b71Sopenharmony_ciint32_t ret; 162e41f4b71Sopenharmony_cistruct SpiCfg cfg = {0}; // SPI配置信息 163e41f4b71Sopenharmony_ciret = SpiGetCfg(spiHandle, &cfg); // 获取SPI设备属性 164e41f4b71Sopenharmony_ciif (ret != HDF_SUCCESS) { 165e41f4b71Sopenharmony_ci HDF_LOGE("SpiGetCfg: failed, ret %d\n", ret); 166e41f4b71Sopenharmony_ci return ret; 167e41f4b71Sopenharmony_ci} 168e41f4b71Sopenharmony_ci``` 169e41f4b71Sopenharmony_ci 170e41f4b71Sopenharmony_ci#### 配置SPI设备属性 171e41f4b71Sopenharmony_ci 172e41f4b71Sopenharmony_ci在获取到SPI设备句柄之后,需要配置SPI设备属性,配置SPI设备属性的函数如下所示: 173e41f4b71Sopenharmony_ci 174e41f4b71Sopenharmony_ci```c 175e41f4b71Sopenharmony_ciint32_t SpiSetCfg(DevHandle handle, struct SpiCfg *cfg); 176e41f4b71Sopenharmony_ci``` 177e41f4b71Sopenharmony_ci 178e41f4b71Sopenharmony_ci**表 4** SpiSetCfg参数和返回值描述 179e41f4b71Sopenharmony_ci 180e41f4b71Sopenharmony_ci| **参数** | **参数描述** | 181e41f4b71Sopenharmony_ci| -------- | -------- | 182e41f4b71Sopenharmony_ci| handle | DevHandle类型,SPI设备句柄 | 183e41f4b71Sopenharmony_ci| cfg | 结构体指针类型,SPI设备配置参数 | 184e41f4b71Sopenharmony_ci| **返回值** | **返回值描述** | 185e41f4b71Sopenharmony_ci| HDF_SUCCESS | 配置设备属性成功 | 186e41f4b71Sopenharmony_ci| 负数 | 配置设备属性失败 | 187e41f4b71Sopenharmony_ci 188e41f4b71Sopenharmony_ci```c 189e41f4b71Sopenharmony_ciint32_t ret; 190e41f4b71Sopenharmony_cistruct SpiCfg cfg = {0}; // SPI配置信息 191e41f4b71Sopenharmony_cicfg.mode = SPI_MODE_LOOP; // 以回环模式进行通信 192e41f4b71Sopenharmony_cicfg.transferMode = PAL_SPI_POLLING_TRANSFER; // 以轮询的方式进行通信 193e41f4b71Sopenharmony_cicfg.maxSpeedHz = 115200; // 最大传输频率 194e41f4b71Sopenharmony_cicfg.bitsPerWord = 8; // 读写位宽为8比特 195e41f4b71Sopenharmony_ciret = SpiSetCfg(spiHandle, &cfg); // 配置SPI设备属性 196e41f4b71Sopenharmony_ciif (ret != HDF_SUCCESS) { 197e41f4b71Sopenharmony_ci HDF_LOGE("SpiSetCfg: failed, ret %d\n", ret); 198e41f4b71Sopenharmony_ci return ret; 199e41f4b71Sopenharmony_ci} 200e41f4b71Sopenharmony_ci``` 201e41f4b71Sopenharmony_ci 202e41f4b71Sopenharmony_ci#### 进行SPI通信 203e41f4b71Sopenharmony_ci 204e41f4b71Sopenharmony_ci- 向SPI设备写入指定长度的数据 205e41f4b71Sopenharmony_ci 206e41f4b71Sopenharmony_ci 如果只向SPI设备写一次数据,则可以通过以下函数完成: 207e41f4b71Sopenharmony_ci 208e41f4b71Sopenharmony_ci ```c 209e41f4b71Sopenharmony_ci int32_t SpiWrite(DevHandle handle, uint8_t *buf, uint32_t len); 210e41f4b71Sopenharmony_ci ``` 211e41f4b71Sopenharmony_ci 212e41f4b71Sopenharmony_ci **表 5** SpiWrite参数和返回值描述 213e41f4b71Sopenharmony_ci 214e41f4b71Sopenharmony_ci | **参数** | **参数描述** | 215e41f4b71Sopenharmony_ci | -------- | -------- | 216e41f4b71Sopenharmony_ci | handle | DevHandle类型,SPI设备句柄 | 217e41f4b71Sopenharmony_ci | buf | uint8_t类型指针,待写入数据 | 218e41f4b71Sopenharmony_ci | len | uint32_t类型,待写入的数据长度 | 219e41f4b71Sopenharmony_ci | **返回值** | **返回值描述** | 220e41f4b71Sopenharmony_ci | HDF_SUCCESS | 写入成功 | 221e41f4b71Sopenharmony_ci | 负数 | 写入失败 | 222e41f4b71Sopenharmony_ci 223e41f4b71Sopenharmony_ci ```c 224e41f4b71Sopenharmony_ci int32_t ret; 225e41f4b71Sopenharmony_ci uint8_t wbuff[4] = {0x12, 0x34, 0x56, 0x78}; 226e41f4b71Sopenharmony_ci // 向SPI设备写入指定长度的数据 227e41f4b71Sopenharmony_ci ret = SpiWrite(spiHandle, wbuff, 4); 228e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 229e41f4b71Sopenharmony_ci HDF_LOGE("SpiWrite: failed, ret %d\n", ret); 230e41f4b71Sopenharmony_ci return ret; 231e41f4b71Sopenharmony_ci } 232e41f4b71Sopenharmony_ci ``` 233e41f4b71Sopenharmony_ci 234e41f4b71Sopenharmony_ci- 从SPI设备读取指定长度的数据 235e41f4b71Sopenharmony_ci 236e41f4b71Sopenharmony_ci 如果只读取一次数据,则可以通过以下函数完成: 237e41f4b71Sopenharmony_ci 238e41f4b71Sopenharmony_ci ```c 239e41f4b71Sopenharmony_ci int32_t SpiRead(DevHandle handle, uint8_t *buf, uint32_t len); 240e41f4b71Sopenharmony_ci ``` 241e41f4b71Sopenharmony_ci 242e41f4b71Sopenharmony_ci **表 6** SpiRead参数和返回值描述 243e41f4b71Sopenharmony_ci 244e41f4b71Sopenharmony_ci | **参数** | **参数描述** | 245e41f4b71Sopenharmony_ci | -------- | -------- | 246e41f4b71Sopenharmony_ci | handle | DevHandle类型,SPI设备句柄 | 247e41f4b71Sopenharmony_ci | buf | uint8_t类型指针,待读取数据 | 248e41f4b71Sopenharmony_ci | len | uint32_t类型,待读取的数据长度 | 249e41f4b71Sopenharmony_ci | **返回值** | **返回值描述** | 250e41f4b71Sopenharmony_ci | HDF_SUCCESS | 读取成功 | 251e41f4b71Sopenharmony_ci | 负数 | 读取失败 | 252e41f4b71Sopenharmony_ci 253e41f4b71Sopenharmony_ci ```c 254e41f4b71Sopenharmony_ci int32_t ret; 255e41f4b71Sopenharmony_ci uint8_t rbuff[4] = {0}; 256e41f4b71Sopenharmony_ci // 从SPI设备读取指定长度的数据 257e41f4b71Sopenharmony_ci ret = SpiRead(spiHandle, rbuff, 4); 258e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 259e41f4b71Sopenharmony_ci HDF_LOGE("SpiRead: failed, ret %d\n", ret); 260e41f4b71Sopenharmony_ci return ret; 261e41f4b71Sopenharmony_ci } 262e41f4b71Sopenharmony_ci ``` 263e41f4b71Sopenharmony_ci 264e41f4b71Sopenharmony_ci- 自定义传输 265e41f4b71Sopenharmony_ci 266e41f4b71Sopenharmony_ci 如果需要发起一次自定义传输,则可以通过以下函数完成: 267e41f4b71Sopenharmony_ci 268e41f4b71Sopenharmony_ci ```c 269e41f4b71Sopenharmony_ci int32_t SpiTransfer(DevHandle handle, struct SpiMsg *msgs, uint32_t count); 270e41f4b71Sopenharmony_ci ``` 271e41f4b71Sopenharmony_ci 272e41f4b71Sopenharmony_ci **表 7** SpiTransfer参数和返回值描述 273e41f4b71Sopenharmony_ci 274e41f4b71Sopenharmony_ci | **参数** | **参数描述** | 275e41f4b71Sopenharmony_ci | -------- | -------- | 276e41f4b71Sopenharmony_ci | handle | DevHandle类型,SPI设备句柄 | 277e41f4b71Sopenharmony_ci | msgs | 结构体指针,待传输数据的数组 | 278e41f4b71Sopenharmony_ci | count | uint32_t类型,msgs数组长度 | 279e41f4b71Sopenharmony_ci | **返回值** | **返回值描述** | 280e41f4b71Sopenharmony_ci | HDF_SUCCESS | 传输执行成功 | 281e41f4b71Sopenharmony_ci | 负数 | 传输执行失败 | 282e41f4b71Sopenharmony_ci 283e41f4b71Sopenharmony_ci ```c 284e41f4b71Sopenharmony_ci int32_t ret; 285e41f4b71Sopenharmony_ci uint8_t wbuff[1] = {0x12}; 286e41f4b71Sopenharmony_ci uint8_t rbuff[1] = {0}; 287e41f4b71Sopenharmony_ci struct SpiMsg msg; // 自定义传输的消息 288e41f4b71Sopenharmony_ci msg.wbuf = wbuff; // 写入的数据 289e41f4b71Sopenharmony_ci msg.rbuf = rbuff; // 读取的数据 290e41f4b71Sopenharmony_ci msg.len = 1; // 读取、写入数据的长度都是1 291e41f4b71Sopenharmony_ci msg.csChange = 1; // 进行下一次传输前关闭片选 292e41f4b71Sopenharmony_ci msg.delayUs = 0; // 进行下一次传输前不进行延时 293e41f4b71Sopenharmony_ci msg.speed = 115200; // 本次传输的速度 294e41f4b71Sopenharmony_ci // 进行一次自定义传输,传输的msg个数为1 295e41f4b71Sopenharmony_ci ret = SpiTransfer(spiHandle, &msg, 1); 296e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 297e41f4b71Sopenharmony_ci HDF_LOGE("SpiTransfer: failed, ret %d\n", ret); 298e41f4b71Sopenharmony_ci return ret; 299e41f4b71Sopenharmony_ci } 300e41f4b71Sopenharmony_ci ``` 301e41f4b71Sopenharmony_ci 302e41f4b71Sopenharmony_ci#### 销毁SPI设备句柄 303e41f4b71Sopenharmony_ci 304e41f4b71Sopenharmony_ciSPI通信完成之后,需要销毁SPI设备句柄,销毁SPI设备句柄的函数如下所示: 305e41f4b71Sopenharmony_ci 306e41f4b71Sopenharmony_ci```c 307e41f4b71Sopenharmony_civoid SpiClose(DevHandle handle); 308e41f4b71Sopenharmony_ci``` 309e41f4b71Sopenharmony_ci 310e41f4b71Sopenharmony_ci该函数会释放掉申请的资源。 311e41f4b71Sopenharmony_ci 312e41f4b71Sopenharmony_ci**表 8** SpiClose参数描述 313e41f4b71Sopenharmony_ci 314e41f4b71Sopenharmony_ci| **参数** | **参数描述** | 315e41f4b71Sopenharmony_ci| -------- | -------- | 316e41f4b71Sopenharmony_ci| handle | DevHandle类型,SPI设备句柄 | 317e41f4b71Sopenharmony_ci 318e41f4b71Sopenharmony_ci```c 319e41f4b71Sopenharmony_ciSpiClose(spiHandle); // 销毁SPI设备句柄 320e41f4b71Sopenharmony_ci``` 321e41f4b71Sopenharmony_ci 322e41f4b71Sopenharmony_ci### 使用实例 323e41f4b71Sopenharmony_ci 324e41f4b71Sopenharmony_ci本例拟对Hi3516DV300开发板上SPI设备进行操作。 325e41f4b71Sopenharmony_ci 326e41f4b71Sopenharmony_ciSPI设备完整的使用示例如下所示,首先获取SPI设备句柄,然后配置SPI设备属性,接着调用读写接口进行数据传输,最后销毁SPI设备句柄。 327e41f4b71Sopenharmony_ci 328e41f4b71Sopenharmony_ci```c 329e41f4b71Sopenharmony_ci#include "hdf_log.h" 330e41f4b71Sopenharmony_ci#include "spi_if.h" 331e41f4b71Sopenharmony_ci 332e41f4b71Sopenharmony_civoid SpiTestSample(void) 333e41f4b71Sopenharmony_ci{ 334e41f4b71Sopenharmony_ci int32_t ret; 335e41f4b71Sopenharmony_ci struct SpiCfg cfg; // SPI配置信息 336e41f4b71Sopenharmony_ci struct SpiDevInfo spiDevinfo; // SPI设备描述符 337e41f4b71Sopenharmony_ci DevHandle spiHandle = NULL; // SPI设备句柄 338e41f4b71Sopenharmony_ci struct SpiMsg msg; // 自定义传输的消息 339e41f4b71Sopenharmony_ci uint8_t rbuff[4] = { 0 }; 340e41f4b71Sopenharmony_ci uint8_t wbuff[4] = { 0x12, 0x34, 0x56, 0x78 }; 341e41f4b71Sopenharmony_ci uint8_t wbuff2[4] = { 0xa1, 0xb2, 0xc3, 0xd4 }; 342e41f4b71Sopenharmony_ci 343e41f4b71Sopenharmony_ci spiDevinfo.busNum = 0; // SPI设备总线号 344e41f4b71Sopenharmony_ci spiDevinfo.csNum = 0; // SPI设备片选号 345e41f4b71Sopenharmony_ci spiHandle = SpiOpen(&spiDevinfo); // 根据spiDevinfo获取SPI设备句柄 346e41f4b71Sopenharmony_ci if (spiHandle == NULL) { 347e41f4b71Sopenharmony_ci HDF_LOGE("SpiTestSample: spi open fail!\n"); 348e41f4b71Sopenharmony_ci return; 349e41f4b71Sopenharmony_ci } 350e41f4b71Sopenharmony_ci // 获取SPI设备属性 351e41f4b71Sopenharmony_ci ret = SpiGetCfg(spiHandle, &cfg); 352e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 353e41f4b71Sopenharmony_ci HDF_LOGE("SpiTestSample: spi get cfg fail, ret:%d!\n", ret); 354e41f4b71Sopenharmony_ci goto err; 355e41f4b71Sopenharmony_ci } 356e41f4b71Sopenharmony_ci cfg.maxSpeedHz = 115200; // 将最大时钟频率改为115200 357e41f4b71Sopenharmony_ci cfg.bitsPerWord = 8; // 传输位宽改为8比特 358e41f4b71Sopenharmony_ci // 配置SPI设备属性 359e41f4b71Sopenharmony_ci ret = SpiSetCfg(spiHandle, &cfg); 360e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 361e41f4b71Sopenharmony_ci HDF_LOGE("SpiTestSample: spi set cfg fail, ret:%d!\n", ret); 362e41f4b71Sopenharmony_ci goto err; 363e41f4b71Sopenharmony_ci } 364e41f4b71Sopenharmony_ci /* 向SPI设备写入指定长度的数据 */ 365e41f4b71Sopenharmony_ci ret = SpiWrite(spiHandle, wbuff, 4); 366e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 367e41f4b71Sopenharmony_ci HDF_LOGE("SpiTestSample: spi write fail, ret:%d!\n", ret); 368e41f4b71Sopenharmony_ci goto err; 369e41f4b71Sopenharmony_ci } 370e41f4b71Sopenharmony_ci /* 从SPI设备读取指定长度的数据 */ 371e41f4b71Sopenharmony_ci ret = SpiRead(spiHandle, rbuff, 4); 372e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 373e41f4b71Sopenharmony_ci HDF_LOGE("SpiTestSample: spi read fail, ret:%d!\n", ret); 374e41f4b71Sopenharmony_ci goto err; 375e41f4b71Sopenharmony_ci } 376e41f4b71Sopenharmony_ci msg.wbuf = wbuff2; // 写入的数据 377e41f4b71Sopenharmony_ci msg.rbuf = rbuff; // 读取的数据 378e41f4b71Sopenharmony_ci msg.len = 4; // 读取写入数据的长度为4 379e41f4b71Sopenharmony_ci msg.keepCs = 0; // 当前传输完成后是否保持CS活动,1表述保持,0表示关闭CS 380e41f4b71Sopenharmony_ci msg.delayUs = 0; // 进行下一次传输前不进行延时 381e41f4b71Sopenharmony_ci msg.speed = 115200; // 本次传输的速度 382e41f4b71Sopenharmony_ci // 进行一次自定义传输,传输的msg个数为1 383e41f4b71Sopenharmony_ci ret = SpiTransfer(spiHandle, &msg, 1); 384e41f4b71Sopenharmony_ci if (ret != HDF_SUCCESS) { 385e41f4b71Sopenharmony_ci HDF_LOGE("SpiTestSample: spi transfer fail, ret:%d!\n", ret); 386e41f4b71Sopenharmony_ci goto err; 387e41f4b71Sopenharmony_ci } 388e41f4b71Sopenharmony_ci HDF_LOGD("SpiTestSample: function tests end!"); 389e41f4b71Sopenharmony_cierr: 390e41f4b71Sopenharmony_ci // 销毁SPI设备句柄 391e41f4b71Sopenharmony_ci SpiClose(spiHandle); 392e41f4b71Sopenharmony_ci} 393e41f4b71Sopenharmony_ci``` 394