长沙专业网站建设公司排名,装饰工程设计东莞网站建设,wordpress 站点地址,空间域名一年要多少钱功能简介
SPI指串行外设接口#xff08;Serial Peripheral Interface#xff09;#xff0c;是一种高速的#xff0c;全双工#xff0c;同步的通信总线。SPI是由Motorola公司开发#xff0c;用于在主设备和从设备之间进行通信。
SPI接口定义了操作SPI设备的通用方法集合…功能简介
SPI指串行外设接口Serial Peripheral Interface是一种高速的全双工同步的通信总线。SPI是由Motorola公司开发用于在主设备和从设备之间进行通信。
SPI接口定义了操作SPI设备的通用方法集合包括 SPI设备句柄获取和释放。 SPI读写从SPI设备读取或写入指定长度数据。 SPI自定义传输通过消息传输结构体执行任意读写组合过程。 SPI设备配置获取和设置SPI设备属性。
运作机制
在HDF框架中SPI的接口适配模式采用独立服务模式在这种模式下每一个设备对象会独立发布一个设备服务来处理外部访问设备管理器收到API的访问请求之后通过提取该请求的参数达到调用实际设备对象的相应内部方法的目的。独立服务模式可以直接借助HDFDeviceManager的服务管理能力但需要为每个设备单独配置设备节点若设备过多可能增加内存占用。
独立服务模式下核心层不会统一发布一个服务供上层使用因此这种模式下驱动要为每个控制器发布一个服务具体表现为 驱动适配者需要实现HdfDriverEntry的Bind钩子函数以绑定服务。 device_info.hcs文件中deviceNode的policy字段为1或2不能为0。
图 1 SPI独立服务模式结构图 SPI模块各分层作用 接口层提供打开SPI设备、SPI写数据、SPI读数据、SPI传输、配置SPI设备属性、获取SPI设备属性、关闭SPI设备的接口。 核心层主要提供SPI控制器的添加、移除以及管理的能力通过钩子函数与适配层交互。 适配层主要是将钩子函数的功能实例化实现具体的功能。
SPI以主从方式工作通常有一个主设备和一个或者多个从设备。主设备和从设备之间一般用4根线相连它们分别是 SCLK时钟信号由主设备产生 MOSI主设备数据输出从设备数据输入 MISO主设备数据输入从设备数据输出 CS片选从设备使能信号由主设备控制。
一个主设备和两个从设备的连接示意图如图2所示Device A和Device B共享主设备的SCLK、MISO和MOSI三根引脚Device A的片选CS0连接主设备的CS0Device B的片选CS1连接主设备的CS1。
图 2 SPI主从设备连接示意图 SPI通信通常由主设备发起通过以下步骤完成一次通信 通过CS选中要通信的从设备在任意时刻一个主设备上最多只能有一个从设备被选中。 通过SCLK给选中的从设备提供时钟信号。 基于SCLK时钟信号主设备数据通过MOSI发送给从设备同时通过MISO接收从设备发送的数据完成通信。 根据SCLK时钟信号的CPOLClock Polarity时钟极性和CPHAClock Phase时钟相位的不同组合SPI有以下四种工作模式 CPOL0CPHA0 时钟信号idle状态为低电平第一个时钟边沿采样数据。 CPOL0CPHA1 时钟信号idle状态为低电平第二个时钟边沿采样数据。 CPOL1CPHA0 时钟信号idle状态为高电平第一个时钟边沿采样数据。 CPOL1CPHA1 时钟信号idle状态为高电平第二个时钟边沿采样数据。
约束与限制
SPI模块当前只支持主机模式不支持从机模式。
使用指导
场景介绍
SPI通常用于与闪存、实时时钟、传感器以及模数/数模转换器等支持SPI协议的设备进行通信。
接口说明
SPI模块提供的主要接口如表1所示具体API详见//drivers/hdf_core/framework/include/platform/spi_if.h。
表 1 SPI驱动API接口功能介绍
接口名接口描述DevHandle SpiOpen(const struct SpiDevInfo *info)获取SPI设备句柄void SpiClose(DevHandle handle)释放SPI设备句柄int32_t SpiRead(DevHandle handle, uint8_t *buf, uint32_t len)读取指定长度的数据int32_t SpiWrite(DevHandle handle, uint8_t *buf, uint32_t len)写入指定长度的数据int32_t SpiTransfer(DevHandle handle, struct SpiMsg *msgs, uint32_t count)SPI数据传输接口int32_t SpiSetCfg(DevHandle handle, struct SpiCfg *cfg)根据指定参数配置SPI设备int32_t SpiGetCfg(DevHandle handle, struct SpiCfg *cfg)获取SPI设备配置参数
使用流程
使用SPI的一般流程如下图所示。
图 3 SPI使用流程图 获取SPI设备句柄
在使用SPI进行通信时首先要调用SpiOpen获取SPI设备句柄该函数会返回指定总线号和片选号的SPI设备句柄。
DevHandle SpiOpen(const struct SpiDevInfo *info);
表 2 SpiOpen参数和返回值描述
参数参数描述info结构体类型SPI设备描述符返回值返回值描述NULL获取SPI设备句柄失败设备句柄获取对应的SPI设备句柄成功
假设系统中的SPI设备总线号为0片选号为0获取该SPI设备句柄的示例如下
struct SpiDevInfo spiDevinfo; // SPI设备描述符
DevHandle spiHandle NULL; // SPI设备句柄
spiDevinfo.busNum 0; // SPI设备总线号
spiDevinfo.csNum 0; // SPI设备片选号// 获取SPI设备句柄
spiHandle SpiOpen(spiDevinfo);
if (spiHandle NULL) {HDF_LOGE(SpiOpen: spi open fail!\n);return HDF_FAILURE;
}
获取SPI设备属性
在获取到SPI设备句柄之后需要配置SPI设备属性。配置SPI设备属性之前可以先获取SPI设备属性获取SPI设备属性的函数如下所示
int32_t SpiGetCfg(DevHandle handle, struct SpiCfg *cfg);
表 3 SpiGetCfg参数和返回值描述
参数参数描述handleDevHandle类型SPI设备句柄cfg结构体指针类型SPI设备配置参数返回值返回值描述HDF_SUCCESS获取设备属性成功负数获取设备属性失败
int32_t ret;
struct SpiCfg cfg {0}; // SPI配置信息
ret SpiGetCfg(spiHandle, cfg); // 获取SPI设备属性
if (ret ! HDF_SUCCESS) {HDF_LOGE(SpiGetCfg: failed, ret %d\n, ret);return ret;
}
配置SPI设备属性
在获取到SPI设备句柄之后需要配置SPI设备属性配置SPI设备属性的函数如下所示
int32_t SpiSetCfg(DevHandle handle, struct SpiCfg *cfg);
表 4 SpiSetCfg参数和返回值描述
参数参数描述handleDevHandle类型SPI设备句柄cfg结构体指针类型SPI设备配置参数返回值返回值描述HDF_SUCCESS配置设备属性成功负数配置设备属性失败
int32_t ret;
struct SpiCfg cfg {0}; // SPI配置信息
cfg.mode SPI_MODE_LOOP; // 以回环模式进行通信
cfg.transferMode PAL_SPI_POLLING_TRANSFER; // 以轮询的方式进行通信
cfg.maxSpeedHz 115200; // 最大传输频率
cfg.bitsPerWord 8; // 读写位宽为8比特
ret SpiSetCfg(spiHandle, cfg); // 配置SPI设备属性
if (ret ! HDF_SUCCESS) {HDF_LOGE(SpiSetCfg: failed, ret %d\n, ret);return ret;
}
进行SPI通信 向SPI设备写入指定长度的数据 如果只向SPI设备写一次数据则可以通过以下函数完成 int32_t SpiWrite(DevHandle handle, uint8_t *buf, uint32_t len); 表 5 SpiWrite参数和返回值描述 参数参数描述handleDevHandle类型SPI设备句柄bufuint8_t类型指针待写入数据lenuint32_t类型待写入的数据长度返回值返回值描述HDF_SUCCESS写入成功负数写入失败int32_t ret;
uint8_t wbuff[4] {0x12, 0x34, 0x56, 0x78};
// 向SPI设备写入指定长度的数据
ret SpiWrite(spiHandle, wbuff, 4);
if (ret ! HDF_SUCCESS) {HDF_LOGE(SpiWrite: failed, ret %d\n, ret);return ret;
} 从SPI设备读取指定长度的数据 如果只读取一次数据则可以通过以下函数完成 int32_t SpiRead(DevHandle handle, uint8_t *buf, uint32_t len); 表 6 SpiRead参数和返回值描述 参数参数描述handleDevHandle类型SPI设备句柄bufuint8_t类型指针待读取数据lenuint32_t类型待读取的数据长度返回值返回值描述HDF_SUCCESS读取成功负数读取失败int32_t ret;
uint8_t rbuff[4] {0};
// 从SPI设备读取指定长度的数据
ret SpiRead(spiHandle, rbuff, 4);
if (ret ! HDF_SUCCESS) {HDF_LOGE(SpiRead: failed, ret %d\n, ret);return ret;
} 自定义传输 如果需要发起一次自定义传输则可以通过以下函数完成 int32_t SpiTransfer(DevHandle handle, struct SpiMsg *msgs, uint32_t count); 表 7 SpiTransfer参数和返回值描述 参数参数描述handleDevHandle类型SPI设备句柄msgs结构体指针待传输数据的数组countuint32_t类型msgs数组长度返回值返回值描述HDF_SUCCESS传输执行成功负数传输执行失败int32_t ret;
uint8_t wbuff[1] {0x12};
uint8_t rbuff[1] {0};
struct SpiMsg msg; // 自定义传输的消息
msg.wbuf wbuff; // 写入的数据
msg.rbuf rbuff; // 读取的数据
msg.len 1; // 读取、写入数据的长度都是1
msg.csChange 1; // 进行下一次传输前关闭片选
msg.delayUs 0; // 进行下一次传输前不进行延时
msg.speed 115200; // 本次传输的速度
// 进行一次自定义传输传输的msg个数为1
ret SpiTransfer(spiHandle, msg, 1);
if (ret ! HDF_SUCCESS) {HDF_LOGE(SpiTransfer: failed, ret %d\n, ret);return ret;
}
销毁SPI设备句柄
SPI通信完成之后需要销毁SPI设备句柄销毁SPI设备句柄的函数如下所示
void SpiClose(DevHandle handle);
该函数会释放掉申请的资源。
表 8 SpiClose参数描述
参数参数描述handleDevHandle类型SPI设备句柄
SpiClose(spiHandle); // 销毁SPI设备句柄
使用实例
本例拟对Hi3516DV300开发板上SPI设备进行操作。
SPI设备完整的使用示例如下所示首先获取SPI设备句柄然后配置SPI设备属性接着调用读写接口进行数据传输最后销毁SPI设备句柄。
#include hdf_log.h
#include spi_if.hvoid SpiTestSample(void)
{int32_t ret;struct SpiCfg cfg; // SPI配置信息struct SpiDevInfo spiDevinfo; // SPI设备描述符DevHandle spiHandle NULL; // SPI设备句柄struct SpiMsg msg; // 自定义传输的消息uint8_t rbuff[4] { 0 };uint8_t wbuff[4] { 0x12, 0x34, 0x56, 0x78 };uint8_t wbuff2[4] { 0xa1, 0xb2, 0xc3, 0xd4 };spiDevinfo.busNum 0; // SPI设备总线号spiDevinfo.csNum 0; // SPI设备片选号spiHandle SpiOpen(spiDevinfo); // 根据spiDevinfo获取SPI设备句柄if (spiHandle NULL) {HDF_LOGE(SpiTestSample: spi open fail!\n);return;}// 获取SPI设备属性ret SpiGetCfg(spiHandle, cfg);if (ret ! HDF_SUCCESS) {HDF_LOGE(SpiTestSample: spi get cfg fail, ret:%d!\n, ret);goto err;}cfg.maxSpeedHz 115200; // 将最大时钟频率改为115200cfg.bitsPerWord 8; // 传输位宽改为8比特// 配置SPI设备属性ret SpiSetCfg(spiHandle, cfg);if (ret ! HDF_SUCCESS) {HDF_LOGE(SpiTestSample: spi set cfg fail, ret:%d!\n, ret);goto err;}/* 向SPI设备写入指定长度的数据 */ret SpiWrite(spiHandle, wbuff, 4);if (ret ! HDF_SUCCESS) {HDF_LOGE(SpiTestSample: spi write fail, ret:%d!\n, ret);goto err;}/* 从SPI设备读取指定长度的数据 */ret SpiRead(spiHandle, rbuff, 4);if (ret ! HDF_SUCCESS) {HDF_LOGE(SpiTestSample: spi read fail, ret:%d!\n, ret);goto err;}msg.wbuf wbuff2; // 写入的数据msg.rbuf rbuff; // 读取的数据msg.len 4; // 读取写入数据的长度为4msg.keepCs 0; // 当前传输完成后是否保持CS活动1表述保持0表示关闭CSmsg.delayUs 0; // 进行下一次传输前不进行延时msg.speed 115200; // 本次传输的速度// 进行一次自定义传输传输的msg个数为1ret SpiTransfer(spiHandle, msg, 1);if (ret ! HDF_SUCCESS) {HDF_LOGE(SpiTestSample: spi transfer fail, ret:%d!\n, ret);goto err;}HDF_LOGD(SpiTestSample: function tests end!);
err:// 销毁SPI设备句柄SpiClose(spiHandle);
}
最后
有很多小伙伴不知道学习哪些鸿蒙开发技术不知道需要重点掌握哪些鸿蒙应用开发知识点而且学习时频繁踩坑最终浪费大量时间。所以有一份实用的鸿蒙HarmonyOS NEXT资料用来跟着学习是非常有必要的。
这份鸿蒙HarmonyOS NEXT资料包含了鸿蒙开发必掌握的核心知识要点内容包含了ArkTS、ArkUI开发组件、Stage模型、多端部署、分布式应用开发、音频、视频、WebGL、OpenHarmony多媒体技术、Napi组件、OpenHarmony内核、Harmony南向开发、鸿蒙项目实战等等鸿蒙HarmonyOS NEXT技术知识点。
希望这一份鸿蒙学习资料能够给大家带来帮助有需要的小伙伴自行领取限时开源先到先得~无套路领取
获取这份完整版高清学习路线请点击→纯血版全套鸿蒙HarmonyOS学习资料
鸿蒙HarmonyOS NEXT最新学习路线 HarmonOS基础技能 HarmonOS就业必备技能 HarmonOS多媒体技术 鸿蒙NaPi组件进阶 HarmonOS高级技能 初识HarmonOS内核 实战就业级设备开发 有了路线图怎么能没有学习资料呢小编也准备了一份联合鸿蒙官方发布笔记整理收纳的一套系统性的鸿蒙OpenHarmony 学习手册共计1236页与鸿蒙OpenHarmony 开发入门教学视频内容包含ArkTS、ArkUI、Web开发、应用模型、资源分类…等知识点。
获取以上完整版高清学习路线请点击→纯血版全套鸿蒙HarmonyOS学习资料
《鸿蒙 (OpenHarmony)开发入门教学视频》 《鸿蒙生态应用开发V2.0白皮书》 《鸿蒙 (OpenHarmony)开发基础到实战手册》
OpenHarmony北向、南向开发环境搭建 《鸿蒙开发基础》
ArkTS语言安装DevEco Studio运用你的第一个ArkTS应用ArkUI声明式UI开发.…… 《鸿蒙开发进阶》
Stage模型入门网络管理数据管理电话服务分布式应用开发通知与窗口管理多媒体技术安全技能任务管理WebGL国际化开发应用测试DFX面向未来设计鸿蒙系统移植和裁剪定制…… 《鸿蒙进阶实战》
ArkTS实践UIAbility应用网络案例…… 获取以上完整鸿蒙HarmonyOS学习资料请点击→纯血版全套鸿蒙HarmonyOS学习资料
总结
总的来说华为鸿蒙不再兼容安卓对中年程序员来说是一个挑战也是一个机会。只有积极应对变化不断学习和提升自己他们才能在这个变革的时代中立于不败之地。