Harmony鸿蒙南向驱动开发-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。
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连接主设备的CS0,Device B的片选CS1连接主设备的CS1。
图 2 SPI主从设备连接示意图
-
SPI通信通常由主设备发起,通过以下步骤完成一次通信:
-
通过CS选中要通信的从设备,在任意时刻,一个主设备上最多只能有一个从设备被选中。
-
通过SCLK给选中的从设备提供时钟信号。
-
基于SCLK时钟信号,主设备数据通过MOSI发送给从设备,同时通过MISO接收从设备发送的数据,完成通信。
-
-
根据SCLK时钟信号的CPOL(Clock Polarity,时钟极性)和CPHA(Clock Phase,时钟相位)的不同组合,SPI有以下四种工作模式:
-
CPOL=0,CPHA=0 时钟信号idle状态为低电平,第一个时钟边沿采样数据。
-
CPOL=0,CPHA=1 时钟信号idle状态为低电平,第二个时钟边沿采样数据。
-
CPOL=1,CPHA=0 时钟信号idle状态为高电平,第一个时钟边沿采样数据。
-
CPOL=1,CPHA=1 时钟信号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参数和返回值描述
参数 | 参数描述 |
---|---|
handle | DevHandle类型,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参数和返回值描述
参数 | 参数描述 |
---|---|
handle | DevHandle类型,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参数和返回值描述
参数 参数描述 handle DevHandle类型,SPI设备句柄 buf uint8_t类型指针,待写入数据 len uint32_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参数和返回值描述
参数 参数描述 handle DevHandle类型,SPI设备句柄 buf uint8_t类型指针,待读取数据 len uint32_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参数和返回值描述
参数 参数描述 handle DevHandle类型,SPI设备句柄 msgs 结构体指针,待传输数据的数组 count uint32_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参数描述
参数 | 参数描述 |
---|---|
handle | DevHandle类型,SPI设备句柄 |
SpiClose(spiHandle); // 销毁SPI设备句柄
使用实例
本例拟对Hi3516DV300开发板上SPI设备进行操作。
SPI设备完整的使用示例如下所示,首先获取SPI设备句柄,然后配置SPI设备属性,接着调用读写接口进行数据传输,最后销毁SPI设备句柄。
#include "hdf_log.h"
#include "spi_if.h"void 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学习资料
总结
总的来说,华为鸿蒙不再兼容安卓,对中年程序员来说是一个挑战,也是一个机会。只有积极应对变化,不断学习和提升自己,他们才能在这个变革的时代中立于不败之地。
相关文章:

Harmony鸿蒙南向驱动开发-SPI接口使用
功能简介 SPI指串行外设接口(Serial Peripheral Interface),是一种高速的,全双工,同步的通信总线。SPI是由Motorola公司开发,用于在主设备和从设备之间进行通信。 SPI接口定义了操作SPI设备的通用方法集合…...
芒果YOLOv7改进96:检测头篇DynamicHead动态检测头:即插即用|DynamicHead检测头,尺度感知、空间感知、任务感知
该专栏完整目录链接: 芒果YOLOv7深度改进教程 该创新点:在原始的Dynamic Head的基础上,对核心部位进行了二次的改进,在 原论文 《尺度感知、空间感知、任务感知》 的基础上,在 通道感知 的层级上进行了增强,关注每个像素点的比重。 在自己的数据集上改进,有效涨点就可以…...

独一无二:探索单例模式在现代编程中的奥秘与实践
设计模式在软件开发中扮演着至关重要的角色,它们是解决特定问题的经典方法。在众多设计模式中,单例模式因其独特的应用场景和简洁的实现而广受欢迎。本文将从多个角度详细介绍单例模式,帮助你理解它的定义、实现、应用以及潜在的限制。 1. 什…...
centos7 安装 rabbitmq3.8.5
1.首先安装 erlang 环境: curl -s https://packagecloud.io/install/repositories/rabbitmq/erlang/script.rpm.sh | sudo bash sudo yum install erlang-21.3.8.14-1.el7.x86_64 yum install socat -y 2.安装 rabbitmq https://github.com/rabbitmq/rabbitmq-s…...
利用SOCKS5代理和代理IP提升网络安全与匿名性
一、引言 随着网络技术的迅猛发展,数据安全和隐私保护已成为业界关注的热点。企业和个人用户越来越依赖于各种网络技术来保护敏感信息免受未授权访问。本文将探讨SOCKS5代理、代理IP以及HTTP协议在提升网络安全和匿名性方面的作用和实践应用。 二、基础技术概述 2.…...

C++list模拟实现
Clist模拟实现 list接口总结结点类的模拟实现迭代器的模拟实现迭代器模板参数迭代器类中的构造函数迭代器类中的运算符重载operator和operator - -operator! 和operatoroperator*operator->总览 list 类构造函数拷贝构造函数赋值运算符重载operatorclear…...

设计模式(22):解释器模式
解释器 是一种不常用的设计模式用于描述如何构成一个简单的语言解释器,主要用于使用面向对象语言开发的解释器和解释器设计当我们需要开发一种新的语言时,可以考虑使用解释器模式尽量不要使用解释器模式,后期维护会有很大麻烦。在项目中&…...
kubernetes docker版本安装测试
文章目录 测试环境kubernetes安装环境配置安装程序下载镜像初始化reset环境init构建kubernetes配置授权信息配置网络插件查看状态 简单实例测试 测试环境 [rootlocalhost ~]# cat /etc/redhat-release CentOS Linux release 7.9.2009 (Core)kubernetes安装 参考kuberneter文档…...

策略模式:灵活调整算法的设计精髓
在软件开发中,策略模式是一种行为型设计模式,它允许在运行时选择算法的行为。通过定义一系列算法,并将每个算法封装起来,策略模式使得算法可以互换使用,这使得算法可以独立于使用它们的客户。本文将详细介绍策略模式的…...

[INS-30014]无法检查指定的位置是否位于 CFS 上
文章目录 一、具体错误二、通用解决方案1、可能的问题原因2、解决方案3、常见原因之hosts文件配置问题hosts配置方法hosts文件不可编辑解决办法 一、具体错误 在安装ORACLE19c的时候,出现无法检查指定的位置是否位于CFS上 二、通用解决方案 1、可能的问题原因 遇…...

机器学习和深度学习 -- 李宏毅(笔记与个人理解)Day 13
Day13 Error surface is rugged…… Tips for training :Adaptive Learning Rate critical point is not the difficult Root mean Square --used in Adagrad 这里为啥是前面的g的和而不是直接只除以当前呢? 这种方法的目的是防止学习率在训练过程中快速衰减。如果只用当前的…...

[Python图像识别] 五十二.水书图像识别 (2)基于机器学习的濒危水书古文字识别研究
该系列文章是讲解Python OpenCV图像处理知识,前期主要讲解图像入门、OpenCV基础用法,中期讲解图像处理的各种算法,包括图像锐化算子、图像增强技术、图像分割等,后期结合深度学习研究图像识别、图像分类应用。目前我进入第二阶段Python图像识别,该部分主要以目标检测、图像…...

Jmeter针对多种响应断言的判断
有时候response返回的结果并非一种,有多种,需要对这几种进行判断的时候需要使用Bean Shell。 (1)首先获取响应数据 String response prev.getResponseDataAsString(); ResponseCode 响应状态码 responseHeaders 响应头信息 res…...

Harmony鸿蒙南向驱动开发-Regulator接口使用
功能简介 Regulator模块用于控制系统中某些设备的电压/电流供应。在嵌入式系统(尤其是手机)中,控制耗电量很重要,直接影响到电池的续航时间。所以,如果系统中某一个模块暂时不需要使用,就可以通过Regulato…...

【opencv】示例-grabcut.cpp 使用OpenCV库的GrabCut算法进行图像分割
left mouse button - set rectangle SHIFTleft mouse button - set GC_FGD pixels CTRLleft mouse button - set GC_BGD pixels 这段代码是一个使用OpenCV库的GrabCut算法进行图像分割的C程序。它允许用户通过交互式方式选择图像中的一个区域,并利用GrabCut算法尝试…...

GEE数据集——巴基斯坦国家级土壤侵蚀数据集(2005 年和 2015 年)
简介 巴基斯坦国家级土壤侵蚀数据集(2005 年和 2015 年) 该数据集采用修订的通用土壤流失方程 (RUSLE),并考虑了六个关键影响因素:降雨侵蚀率 (R)、土壤可侵蚀性 (K)、坡长 (L)、坡陡 (S)、覆盖管理 (C) 和保护措施 (P)ÿ…...

服务器代理
服务器代理 配置:64G内存1 3090(24g)1P4000(8g) SSH连接 工作路径:/home/ubuntu/workspace/python Anaconda路径:/home/Ubuntu 1.在工作路径下创建自己的文件夹作为workspace 2.以用户ubunbtu登…...

【SGDR】《SGDR:Stochastic Gradient Descent with Warm Restarts》
arXiv-2016 code: https://github.com/loshchil/SGDR/blob/master/SGDR_WRNs.py 文章目录 1 Background and Motivation2 Related Work3 Advantages / Contributions4 Method5 Experiments5.1 Datasets and Metric5.2 Single-Model Results5.3 Ensemble Results5.4 Experiment…...
如何将arping以及所有依赖打包安装到另外一台离线ubuntu机器
ubuntu系统下可以使用arping命令检测局域网内一些ip是否冲突,使用方式为: arping xx.xx.xx.xx 在线情况下,可以使用下面命令下载arping,然后使用即可 apt install arping 但是有些情况下机器可能不能上网,这时就需要将…...

mac上如何安装python3
mac上如何安装python3? 安装homebrew 在终端执行命令 /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 执行完成后,homebrew和pip等工具就自动安装好了。 接下来安装python3.在终端…...
应用升级/灾备测试时使用guarantee 闪回点迅速回退
1.场景 应用要升级,当升级失败时,数据库回退到升级前. 要测试系统,测试完成后,数据库要回退到测试前。 相对于RMAN恢复需要很长时间, 数据库闪回只需要几分钟。 2.技术实现 数据库设置 2个db_recovery参数 创建guarantee闪回点,不需要开启数据库闪回。…...
【Java学习笔记】Arrays类
Arrays 类 1. 导入包:import java.util.Arrays 2. 常用方法一览表 方法描述Arrays.toString()返回数组的字符串形式Arrays.sort()排序(自然排序和定制排序)Arrays.binarySearch()通过二分搜索法进行查找(前提:数组是…...
C++中string流知识详解和示例
一、概览与类体系 C 提供三种基于内存字符串的流,定义在 <sstream> 中: std::istringstream:输入流,从已有字符串中读取并解析。std::ostringstream:输出流,向内部缓冲区写入内容,最终取…...

ArcGIS Pro制作水平横向图例+多级标注
今天介绍下载ArcGIS Pro中如何设置水平横向图例。 之前我们介绍了ArcGIS的横向图例制作:ArcGIS横向、多列图例、顺序重排、符号居中、批量更改图例符号等等(ArcGIS出图图例8大技巧),那这次我们看看ArcGIS Pro如何更加快捷的操作。…...
前端中slice和splic的区别
1. slice slice 用于从数组中提取一部分元素,返回一个新的数组。 特点: 不修改原数组:slice 不会改变原数组,而是返回一个新的数组。提取数组的部分:slice 会根据指定的开始索引和结束索引提取数组的一部分。不包含…...
vue3 daterange正则踩坑
<el-form-item label"空置时间" prop"vacantTime"> <el-date-picker v-model"form.vacantTime" type"daterange" start-placeholder"开始日期" end-placeholder"结束日期" clearable :editable"fal…...

在 Visual Studio Code 中使用驭码 CodeRider 提升开发效率:以冒泡排序为例
目录 前言1 插件安装与配置1.1 安装驭码 CodeRider1.2 初始配置建议 2 示例代码:冒泡排序3 驭码 CodeRider 功能详解3.1 功能概览3.2 代码解释功能3.3 自动注释生成3.4 逻辑修改功能3.5 单元测试自动生成3.6 代码优化建议 4 驭码的实际应用建议5 常见问题与解决建议…...

QT开发技术【ffmpeg + QAudioOutput】音乐播放器
一、 介绍 使用ffmpeg 4.2.2 在数字化浪潮席卷全球的当下,音视频内容犹如璀璨繁星,点亮了人们的生活与工作。从短视频平台上令人捧腹的搞笑视频,到在线课堂中知识渊博的专家授课,再到影视平台上扣人心弦的高清大片,音…...

解析“道作为序位生成器”的核心原理
解析“道作为序位生成器”的核心原理 以下完整展开道函数的零点调控机制,重点解析"道作为序位生成器"的核心原理与实现框架: 一、道函数的零点调控机制 1. 道作为序位生成器 道在认知坐标系$(x_{\text{物}}, y_{\text{意}}, z_{\text{文}}…...

C++--string的模拟实现
一,引言 string的模拟实现是只对string对象中给的主要功能经行模拟实现,其目的是加强对string的底层了解,以便于在以后的学习或者工作中更加熟练的使用string。本文中的代码仅供参考并不唯一。 二,默认成员函数 string主要有三个成员变量,…...