RK3568DAYU开发板-平台驱动开发:I2C驱动(原理、源码、案例分析)

1、程序介绍

本程序是基于OpenHarmony标准系统编写的平台驱动案例:I2C

系统版本:openharmony5.0.0

开发板:dayu200

编译环境:ubuntu22

部署路径: //sample/04_platform_i2c

2、基础知识

2.1、I2C简介

I2C(Inter Integrated Circuit)总线是由Philips公司开发的一种简单、双向二线制同步串行总线。由于其硬件连接简单、成本低廉,因此被广泛应用于各种短距离通信的场景

I2C以主从方式工作,通常有一个主设备和一个或者多个从设备,主从设备通过SDA(SerialData)串行数据线以及SCL(SerialClock)串行时钟线两根线相连(如下图)。

I2C数据的传输必须以一个起始信号作为开始条件,以一个结束信号作为传输的停止条件。数据传输以字节为单位,高位在前,逐个bit进行传输。

I2C总线上的每一个设备都可以作为主设备或者从设备,而且每一个设备都会对应一个唯一的地址,当主设备需要和某一个从设备通信时,通过广播的方式,将从设备地址写到总线上,如果某个从设备符合此地址,将会发出应答信号,建立传输。

I2C接口定义了完成I2C传输的通用方法集合,包括:

  • I2C控制器管理:打开或关闭I2C控制器

  • I2C消息传输:通过消息传输结构体数组进行自定义传输

I2C物理连线示意图

在这里插入图片描述

2.2、I2C驱动开发

I2C模块各分层的作用为:

  • 接口层:提供打开设备,数据传输以及关闭设备的能力。
  • 核心层:主要负责服务绑定、初始化以及释放管理器,并提供添加、删除以及获取控制器的能力。
  • 适配层:由驱动适配者实现与硬件相关的具体功能,如控制器的初始化等。

在这里插入图片描述

2.2.1、I2C驱动开发接口

为了保证上层在调用I2C接口时能够正确的操作硬件,核心层在//drivers/hdf_core/framework/support/platform/include/i2c/i2c_core.h中定义了以下钩子函数。驱动适配者需要在适配层实现这些函数的具体功能,并与这些钩子函数挂接,从而完成接口层与核心层的交互。

I2cMethod和I2cLockMethod定义:

struct I2cMethod {int32_t (*transfer)(struct I2cCntlr *cntlr, struct I2cMsg *msgs, int16_t count);
};struct I2cLockMethod { // 锁机制操作结构体int32_t (*lock)(struct I2cCntlr *cntlr);void (*unlock)(struct I2cCntlr *cntlr);
};

在适配层中,I2cMethod必须被实现,I2cLockMethod可根据实际情况考虑是否实现。核心层提供了默认的I2cLockMethod,其中使用mutex作为保护临界区的锁:

static int32_t I2cCntlrLockDefault(struct I2cCntlr *cntlr)
{if (cntlr == NULL) {return HDF_ERR_INVALID_OBJECT;}return OsalMutexLock(&cntlr->lock);
}static void I2cCntlrUnlockDefault(struct I2cCntlr *cntlr)
{if (cntlr == NULL) {return;}(void)OsalMutexUnlock(&cntlr->lock);
}static const struct I2cLockMethod g_i2cLockOpsDefault = {.lock = I2cCntlrLockDefault,.unlock = I2cCntlrUnlockDefault,
};

若实际情况不允许使用mutex(例如使用者可能在中断上下文调用I2C接口,mutex可能导致休眠,而中断上下文不允许休眠)时,驱动适配者可以考虑使用其他类型的锁来实现一个自定义的I2cLockMethod。一旦实现了自定义的I2cLockMethod,默认的I2cLockMethod将被覆盖。

I2cMethod结构体成员函数功能说明:

函数成员入参出参返回值功能
transfercntlr:结构体指针,核心层I2C控制器。 msgs:结构体指针,用户消息。 count:uint16_t,消息数量。HDF_STATUS相关状态传递用户消息

I2cLockMethod结构体成员函数功能说明:

函数成员入参出参返回值功能
lockcntlr:结构体指针,核心层I2C控制器。HDF_STATUS相关状态获取临界区锁
unlockcntlr:结构体指针,核心层I2C控制器。HDF_STATUS相关状态释放临界区锁
2.2.2、I2C驱动开发步骤

I2C模块适配HDF框架包含以下四个步骤:

  • 实例化驱动入口。
  • 配置属性文件。
  • 实例化I2C控制器对象。
  • 驱动调试。

2.3、I2C应用开发

2.3.1、接口说明

I2C模块提供的主要接口如表1所示,具体API详见//drivers/hdf_core/framework/include/platform/i2c_if.h。

I2C驱动API接口功能介绍如下所示:

接口名接口描述
DevHandle I2cOpen(int16_t number)打开I2C控制器
void I2cClose(DevHandle handle)关闭I2C控制器
int32_t I2cTransfer(DevHandle handle, struct I2cMsg *msgs, int16_t count)自定义传输

(1)I2cOpen

在进行I2C通信前,首先要调用I2cOpen打开I2C控制器。

DevHandle I2cOpen(int16_t number);

I2cOpen参数定义如下:

参数参数描述
numberI2C控制器号

I2cOpen返回值定义如下:

返回值返回值描述
NULL打开I2C控制器失败
设备句柄打开的I2C控制器设备句柄

假设系统中存在8个I2C控制器,编号从0到7,以下代码示例为获取3号控制器:

DevHandle i2cHandle = NULL;  /* I2C控制器句柄 //* 打开I2C控制器 */
i2cHandle = I2cOpen(3);
if (i2cHandle == NULL) {HDF_LOGE("I2cOpen: failed\n");return;
}

(2)I2cClose

I2C通信完成之后,需要关闭I2C控制器。

void I2cClose(DevHandle handle); 

I2cClose参数定义如下:

参数参数描述
handleI2C控制器设备句柄

(3)I2cTransfer

i2c消息传输。

int32_t I2cTransfer(DevHandle handle, struct I2cMsg \*msgs, int16_t count);

I2cTransfer参数定义如下:

参数参数描述
handleI2C控制器设备句柄
msgs待传输数据的消息结构体数组
count消息数组长度

I2cTransfer返回值定义如下:

返回值返回值描述
正整数成功传输的消息结构体数目
负数执行失败

I2C传输消息类型为I2cMsg,每个传输消息结构体表示一次读或写,通过一个消息数组,可以执行若干次的读写组合操作。组合读写示例:

int32_t ret;
uint8_t wbuff[2] = { 0x12, 0x13 };
uint8_t rbuff[2] = { 0 };
struct I2cMsg msgs[2]; /* 自定义传输的消息结构体数组 */
msgs[0].buf = wbuff;    /* 写入的数据 */
msgs[0].len = 2;        /* 写入数据长度为2 */
msgs[0].addr = 0x5A;    /* 写入设备地址为0x5A */
msgs[0].flags = 0;      /* 传输标记为0,默认为写 */
msgs[1].buf = rbuff;    /* 要读取的数据 */
msgs[1].len = 2;        /* 读取数据长度为2 */
msgs[1].addr = 0x5A;    /* 读取设备地址为0x5A */
msgs[1].flags = I2C_FLAG_READ /* I2C_FLAG_READ置位 */
/* 进行一次自定义传输,传输的消息个数为2 */
ret = I2cTransfer(i2cHandle, msgs, 2);
if (ret != 2) {HDF_LOGE("I2cTransfer: failed, ret %d\n", ret);return;
}
2.2.2、开发流程

使用I2C设备的一般流程如下图所示:

在这里插入图片描述

3、程序解析

3.1、源码目录

在这里插入图片描述

3.2、接口流程梳理

  • I2cOpen执行流程
//drivers\hdf_core\framework\support\platform\src\i2c\i2c_if.c
DevHandle I2cOpen(int16_t number)
|-->return (DevHandle)I2cCntlrGet(number);|-->return I2cManagerFindCntlr(number);|-->struct I2cCntlr *cntlr = g_i2cManager->cntlrs[number];|-->return cntlr
  • I2cTransfer执行流程
//drivers\hdf_core\framework\support\platform\src\i2c\i2c_if.c
int32_t I2cTransfer(DevHandle handle, struct I2cMsg *msgs, int16_t count)
|-->return I2cCntlrTransfer((struct I2cCntlr *)handle, msgs, count);|-->return cntlr->ops->transfer(cntlr, msgs, count);

由上可见设备节点由全局变量g_i2cManager提供,此变量由下文中平台驱动linux_i2c_adapter(drivers\hdf_core\adapter\khdf\linux\platform\i2c\i2c_adapter.c)进行设置。

3.3、平台驱动说明

  • 驱动实例化驱动入口

I2C控制器会出现很多个设备挂接的情况,因而在HDF框架中首先会为此类型的设备创建一个管理器对象,并同时对外发布一个管理器服务来统一处理外部访问。这样,用户需要打开某个设备时,会先获取到管理器服务,然后管理器服务根据用户指定参数查找到指定设备

I2C管理器服务的驱动由核心层实现,驱动适配者不需要关注这部分内容的实现,但在实现Init函数的时候需要调用核心层的I2cCntlrAdd函数,它会实现相应功能。

I2C驱动入口开发参考:

struct HdfDriverEntry g_i2cLinuxDriverEntry = {.moduleVersion = 1,.Bind = LinuxI2cBind,.Init = LinuxI2cInit,.Release = LinuxI2cRelease,.moduleName = "linux_i2c_adapter",		// 【必要且与device_info.hcs文件里面匹配】
};
HDF_INIT(g_i2cLinuxDriverEntry);			// 调用HDF_INIT将驱动入口注册到HDF框架中/* 核心层i2c_core.c管理器服务的驱动入口 */
struct HdfDriverEntry g_i2cManagerEntry = {.moduleVersion = 1,.Bind = I2cManagerBind,.Init = I2cManagerInit,.Release = I2cManagerRelease,.moduleName = "HDF_PLATFORM_I2C_MANAGER", // 这与device_info.hcs文件中device0对应
};
HDF_INIT(g_i2cManagerEntry);
  • 配置属性文件

deviceNode信息与驱动入口注册相关,器件属性值对于驱动适配者的驱动实现以及核心层I2cCntlr相关成员的默认值或限制范围有密切关系。

统一服务模式的特点是device_info.hcs文件中第一个设备节点必须为I2C管理器,其各项参数如下所示:

成员名
moduleName固定为HDF_PLATFORM_I2C_MANAGER
serviceName固定为HDF_PLATFORM_I2C_MANAGER
policy具体配置为1或2取决于是否对用户态可见
deviceMatchAttr没有使用,可忽略

从第二个节点开始配置具体I2C控制器信息,此节点并不表示某一路I2C控制器,而是代表一个资源性质设备,用于描述一类I2C控制器的信息。多个控制器之间相互区分的参数是busId和reg_pbase,这在i2c_config.hcs文件中有所体现。如下:

//vendor/hihope/rk3568/hdf_config/khdf/device_info/device_info.hcs已定义好,具体如下:

在这里插入图片描述

注意:

  • device1是rk3568原有的配置,也是我们需要的,作为OpenHarmony的i2c配置。
  • moduleName定义为linux_i2c_adapter,表示该节点对应于//drivers/hdf_core/adapter/khdf/linux/platform/i2c/i2c_adapter.c,该驱动是对接Linux i2c子系统。

在//vendor/hihope/rk3568/hdf_config/khdf/platform/i2c_config.hcs,具体内容如下:

在这里插入图片描述

注意:

  • controller_0x120b2000是为i2c2准备的。
  • bus用于确定Linux i2c控制器序号。

具体执行流程如下:

//drivers\hdf_core\adapter\khdf\linux\platform\i2c\i2c_adapter.c
// 定义I2cMethod结构体变量g_method,实现i2c相应接口
static struct I2cMethod g_method = {.transfer = LinuxI2cTransfer,
};
static int32_t LinuxI2cInit(struct HdfDeviceObject *device)
|-->struct I2cCntlr *cntlr = (struct I2cCntlr *)OsalMemCalloc(sizeof(*cntlr));//为I2cCntlr对象分配内存
|-->cntlr->ops = &g_method;//分配i2c相应接口
|-->ret = I2cCntlrAdd(cntlr);//添加新创建的I2cCntlr对象到全局变量g_i2cManager中|-->ret = I2cManagerAddCntlr(cntlr);|-->manager->cntlrs[cntlr->busId] = cntlr;

由HDF驱动框架通过init和bind调用此驱动入口,注册之后,下一步就是以核心层I2cCntlr对象的初始化为核心,包括驱动适配者自定义结构体(传递参数和数据),实例化I2cCntlr成员I2cMethod(让用户可以通过接口来调用驱动底层函数),实现HdfDriverEntry成员函数(Bind,Init,Release)。

3.4、应用程序

3.4.1、i2c_test.c

i2c相关头文件如下所示:

#include "i2c_if.h"                 // i2c标准接口头文件

主函数负责i2c读写操作。

其中,读操作源代码具体如下:

int main(int argc, char* argv[])
{DevHandle handle = NULL;int32_t ret = 0;struct I2cMsg msgs[2];      // 消息结构体数组int16_t msgs_count = 0;uint8_t wbuff[STRING_MAXSIZE] = { 0 };uint8_t rbuff[STRING_MAXSIZE] = { 0 };// 解析参数......// 打开i2c控制器handle = I2cOpen(m_i2c_number);if (handle == NULL) {PRINT_ERROR("I2cOpen failed\n");return -1;}if (m_i2c_flags_read == 1) {// 读操作// 设置msgs数组有效数目msgs_count = 2;// 初始化msgs[0],该部分为主设备发送从设备的i2c内容msgs[0].addr = m_i2c_slave_address;msgs[0].flags = toI2cFlags(0, m_i2c_flags_addr_10bit, m_i2c_flags_read_no_ack, m_i2c_flags_ignore_no_ack, m_i2c_flags_no_start, m_i2c_flags_stop);msgs[0].len = 1;wbuff[0] = m_i2c_reg_address;           // 本案例的i2c从设备是第1字节是寄存器地址msgs[0].buf = wbuff;// 初始化msgs[1],该部分为主设备读取从设备发送的i2c内容msgs[1].addr = m_i2c_slave_address;msgs[1].flags = toI2cFlags(1, m_i2c_flags_addr_10bit, m_i2c_flags_read_no_ack, m_i2c_flags_ignore_no_ack, m_i2c_flags_no_start, m_i2c_flags_stop);msgs[1].len = m_i2c_read_data_length;msgs[1].buf = rbuff;// i2c数据传输,传输次数为2次ret = I2cTransfer(handle, msgs, msgs_count);if (ret != msgs_count) {PRINT_ERROR("I2cTransfer(read) failed and ret = %d\n", ret);goto out;}printf("I2cTransfer success and read data length = %d\n", strlen((char *)rbuff));for (uint32_t i = 0; i < strlen((char *)rbuff); i++) {printf("rbuff[%d] = 0x%x\n", i, rbuff[i]);}} else {......}out:// 关闭i2c控制器I2cClose(handle);return ret;
}

写操作源代码如下所示:

int main(int argc, char* argv[])
{DevHandle handle = NULL;int32_t ret = 0;struct I2cMsg msgs[2];      // 消息结构体数组int16_t msgs_count = 0;uint8_t wbuff[STRING_MAXSIZE] = { 0 };uint8_t rbuff[STRING_MAXSIZE] = { 0 };// 解析参数......// 打开i2c控制器handle = I2cOpen(m_i2c_number);if (handle == NULL) {PRINT_ERROR("I2cOpen failed\n");return -1;}if (m_i2c_flags_read == 1) {......} else {// 写操作// 设置msgs数组有效数目msgs_count = 1;// 初始化msgs[0],该部分为主设备发送从设备的i2c内容msgs[0].addr = m_i2c_slave_address;msgs[0].flags = toI2cFlags(0, m_i2c_flags_addr_10bit, m_i2c_flags_read_no_ack, m_i2c_flags_ignore_no_ack, m_i2c_flags_no_start, m_i2c_flags_stop);msgs[0].len = 2;wbuff[0] = m_i2c_reg_address;       // 本案例的i2c从设备是第1字节是寄存器地址wbuff[1] = m_i2c_reg_value;         // 本案例的i2c从设备是第2字节是寄存器数值msgs[0].buf = wbuff;// i2c数据传输,传输次数为2次ret = I2cTransfer(handle, msgs, msgs_count);if (ret != msgs_count) {PRINT_ERROR("I2cTransfer(write) failed and ret = %d\n", ret);goto out;}printf("I2cTransfer success and write reg(%d), data(%d)\n", m_i2c_reg_address, m_i2c_reg_value);}out:// 关闭i2c控制器I2cClose(handle);return ret;
}
3.4.2、BUILD.gn

编写应用程序的BUILD.gn,具体内容如下:

import("//build/ohos.gni")
import("//drivers/hdf_core/adapter/uhdf2/uhdf.gni")print("samples: compile rk3568_i2c_test")
ohos_executable("rk3568_i2c_test") {sources = [ "i2c_test.c" ]include_dirs = ["$hdf_framework_path/include","$hdf_framework_path/include/core","$hdf_framework_path/include/osal","$hdf_framework_path/include/platform","$hdf_framework_path/include/utils","$hdf_uhdf_path/osal/include","$hdf_uhdf_path/ipc/include","//base/hiviewdfx/hilog/interfaces/native/kits/include","//third_party/bounds_checking_function/include",]deps = ["$hdf_uhdf_path/platform:libhdf_platform","$hdf_uhdf_path/utils:libhdf_utils","//base/hiviewdfx/hilog/interfaces/native/innerkits:libhilog",]cflags = ["-Wall","-Wextra","-Werror","-Wno-format","-Wno-format-extra-args",]part_name = "rk3568_i2c_test"install_enable = true
}
3.4.3、bundle.json

编写应用程序的bundle.json,具体内容如下:

{"name": "@ohos/i2c_test","description": "rk3568_i2c_test example.","version": "3.1","license": "Apache License 2.0","publishAs": "code-segment","segment": {"destPath": "sample/04_platform_i2c"},"dirs": {},"scripts": {},"component": {"name": "rk3568_i2c_test","subsystem": "sample","syscap": [],"features": [],"adapted_system_type": ["mini","small","standard"],"rom": "10KB","ram": "10KB","deps": {"components": ["hdf_core","hilog"],"third_party": []},"build": {"sub_component": ["//sample/04_platform_i2c:rk3568_i2c_test"],"inner_kits": [],"test": []}}
}

4、程序编译

sudo ./build.sh --product-name rk3568 --build-target rk3568_i2c_test

5、运行结果

通过i2cdetect命令查看发现I2C 5中包含地址为0x15的设备,所以直接通过此设备进行测试了。

在i2c调试过程中,OpenHarmony还提供Linux i2c-tools工具,具体使用方法可以参考这篇。
在这里插入图片描述

运行如下:

在这里插入图片描述

上述命令为:查看i2c 5控制器,从设备地址21(即0x15,该地址为开发板外接i2c芯片),读取寄存器地址0,数据长度为3。

6.参考资料

  • I2C平台驱动开发
  • I2C应用程序开发
  • OpenHarmony平台驱动案例–I2C

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.pswp.cn/news/907310.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

在UniApp中开发微信小程序实现图片、音频和视频下载功能

随着微信小程序的迅猛发展&#xff0c;越来越多的开发者选择通过UniApp框架来进行跨平台应用开发。UniApp能够让开发者在一个代码库中同时发布iOS、Android和小程序等多平台应用。而在实际开发过程中&#xff0c;很多应用都需要实现一些常见的下载功能&#xff0c;例如图片、音…

鸿蒙5.0项目开发——接入有道大模型翻译

鸿蒙5.0项目开发——接入有道大模型翻译 【高心星出品】 项目效果图 项目功能 文本翻译功能 支持文本输入和翻译结果显示 使用有道翻译API进行翻译 支持自动检测语言&#xff08;auto&#xff09; 支持双向翻译&#xff08;源语言和目标语言可互换&#xff09; 文本操作…

Vim 中设置插入模式下输入中文

在 Vim 中设置插入模式下输入中文需要配置输入法切换和 Vim 的相关设置。以下是详细步骤&#xff1a; 1. 确保系统已安装中文输入法 在 Linux 系统中&#xff0c;常用的中文输入法有&#xff1a; IBus&#xff08;推荐&#xff09;&#xff1a;支持拼音、五笔等Fcitx&#xf…

湖北理元理律师事务所:债务优化中的“生活锚点”设计

在债务重组领域&#xff0c;一个常被忽视的核心矛盾是&#xff1a;还款能力与生存需求的冲突。过度压缩生活支出还债&#xff0c;可能导致收入中断&#xff1b;放任债务膨胀&#xff0c;又加剧精神压力。湖北理元理律师事务所通过“三步平衡法”&#xff0c;尝试在法理框架内破…

Prometheus + Grafana 监控常用服务

一、引言 Prometheus监控常见服务的原理主要包括服务暴露指标和Prometheus抓取指标。一方面&#xff0c;被监控服务通过自身提供的监控接口或借助Exporter将服务的性能指标等数据以HTTP协议的方式暴露出来&#xff1b;另一方面&#xff0c;Prometheus根据配置好的采集任务&…

基于YOLOv8 的分类道路目标系统-PyTorch实现

本文源码: https://download.csdn.net/download/shangjg03/90873939 1. 引言 在智能交通和自动驾驶领域,道路目标分类是一项关键技术。通过对摄像头捕获的图像或视频中的目标进行分类识别,可以帮助车辆或系统理解周围环境,做出更安全的决策。本教程将介绍如何使用 PyTorch …

知识图谱:AI时代语义认知的底层重构逻辑

在生成式人工智能&#xff08;GEO&#xff09;的技术架构中&#xff0c;知识图谱已从辅助性工具演变为驱动机器认知的核心神经中枢。它通过结构化语义网络的重构&#xff0c;正在突破传统数据处理的线性逻辑&#xff0c;建立机器对复杂业务场景的深度理解能力。 一、语义解构&a…

如何使用 Python 的胶水语言特性

Python 作为“胶水语言”最核心的特性在于&#xff1a;跨语言集成能力强、支持丰富的 C/C 扩展模块、嵌入式调用简便、适配多种数据交换格式、拥有强大的封装能力。其中&#xff0c;Python 对 C/C 模块的快速封装能力&#xff0c;使其能够将底层高性能库暴露为易用接口&#xf…

[网页五子棋][匹配模块]服务器开发、用户管理器(创建匹配请求/响应对象、处理连接成功、处理下线)

文章目录 MatchAPI 类用户管理器创建匹配请求/响应对象处理连接成功—afterConnectionEstablished处理下线——handleTransportError/afterConnectionClosed MatchAPI 类 创建 api.MatchAPI&#xff0c;继承自 TextWebSocketHandler 作为处理 WebSocket 请求的入口类 准备好一…

软件测试的潜力与挑战:从“质量守门员”到“工程效能催化剂”的进化

1. 潜力&#xff1a;为什么软件测试的未来比想象中更广阔&#xff1f; ✅ 行业趋势驱动需求爆发 DevOps/持续交付&#xff1a;测试成为流水线的核心环节&#xff0c;自动化能力直接影响发布频率&#xff08;案例&#xff1a;某头部互联网企业日均发布100次&#xff0c;依赖自动…

indel_snp_ssr_primer

好的&#xff0c;我们可以逐步分析这个 Perl 脚本的每个部分。脚本的主要功能是基于给定的 VCF 文件和参考基因组文件&#xff0c;设计引物并进行电子 PCR&#xff08;e-PCR&#xff09;分析。我们将从脚本的头部和初始化部分开始讲解。 第一部分&#xff1a;脚本头部和初始化…

2.4GHz 射频前端芯片AT2401C

射频前端芯片作为无线通信系统的核心组件&#xff0c;涵盖功率放大器&#xff08;PA&#xff09;、滤波器、开关、低噪声放大器&#xff08;LNA&#xff09;等关键器件&#xff0c;其性能直接影响通信质量、功耗及信号稳定性。 AT2401C是一款面向 Zigbee&#xff0c;无线传感网…

Batch Normalization[[

error surface如果很崎岖,那么就代表比较难train,我们有没有办法去改变这个landscape呢 可以用batch normalization. 如果 ( x_1 ) 的取值范围很小&#xff08;如 1, 2&#xff09;&#xff0c;而 ( x_2 ) 的取值范围很大&#xff08;如 100, 200&#xff09;&#xff0c;那么…

c++结构化绑定

author: hjjdebug date: 2025年 05月 28日 星期三 15:57:58 CST descrip: c结构化绑定: 结构化绑定: 名称辨析: 名称叫绑定好还是叫解绑好&#xff1f; 解绑意思是原来是一个整体,现在被分成了若干个部分,所以叫解. 绑定强调的意思是. 被分解的某个变量,绑定到了整体的某个变量…

大数据治理:理论、实践与未来展望(一)

文章目录 一、大数据治理的定义与重要性&#xff08;一&#xff09;定义&#xff08;二&#xff09;重要性 二、大数据治理的应用场景&#xff08;一&#xff09;金融行业&#xff08;二&#xff09;医疗行业&#xff08;三&#xff09;制造业&#xff08;四&#xff09;零售行…

AI系统化学习月计划6月计划

以下是为技术总监设计的 AI系统化学习月计划&#xff08;每天投入2小时&#xff0c;共30天&#xff09;&#xff0c;结合战略思维、技术基础、实战应用和行业趋势&#xff0c;帮助您快速掌握AI的核心知识&#xff0c;并转化为业务决策能力。 第一周&#xff1a;AI基础与战略思维…

详解MySQL调优

目录 1. SQL 语句优 1.1 避免低效查询 1.2 索引优化 1.3 分析执行计划 2. 数据库配置优化 2.1 核心参数调整 2.2 表结构与存储引擎 2.3 存储引擎选择 3. 事务与锁优化 3.1 事务控制 3.2 锁机制优化 3.3 批量操作优化 4. 其他优化手段 4.1 监控与分析工具 4.2 读写…

VScode单双引号、分号格式

1、settings.json中添加&#xff1a; 1 2 3 "prettier.semi": false, // 取消自动加分号 "prettier.singleQuote": true, // 保持单引号&#xff0c;不自动变双引号 "prettier.trailingComma": "none" // 去掉结尾的逗号 2、如上一步…

自动驾驶规划控制教程——不确定环境下的决策规划

引言:驾驭未知——不确定性下的自动驾驶决策挑战 自动驾驶汽车 (Autonomous Vehicles, AVs) 的愿景是彻底改变交通运输的面貌,提高道路安全、提升交通效率、改善驾乘体验。然而,要将这一愿景安全可靠地付诸实践,自动驾驶系统必须能够在复杂、动态且充满不确定性的真实世界…

电缆中性点概念

电缆中性点概念 电缆中性点(也称“中性点”或“中性线”)是电力系统和电气设备中一个非常重要的概念,尤其在三相电系统中。下面是对中性点概念的系统性解释。 1. 基本定义 中性点:三相电缆(A/B/C相)的电压矢量交汇点,理想情况下三相平衡时该点电压为零。对于星形(Y形…