嵌入式驱动开发详解14(SPI驱动架构实现)
文章目录
- 前言
- SPI简介
- SPI介绍
- SPI工作模式
- SPI特点
- 驱动开发
- 驱动架构
- SPI控制器驱动
- SPI设备驱动
- SPI 设备和驱动匹配过程
- SPI其他相关API函数
- 参考文献
前言
SPI 是很常用的串行通信协议,可以通过 SPI 来连接众多的传感器,相比 I2C 接 口,SPI 接口的通信速度很快,I2C 最多 400KHz,但是 SPI 可以到达几十 MHz。本文章主要讲解SPI串行通信协议相关的基本内容和在Linux操作系统下如何进行SPI外设的开发。
SPI简介
SPI介绍
SPI 全称是 Serial Perripheral Interface,也就是串行外围设备接口。SPI 是 Motorola 公司推出的一种同步串行接口 技术,是一种高速、全双工的同步通信总线,SPI 时钟频率相比 I2C 要高很多,最高可以工作 在上百 MHz。
SPI 以主从方式工作,通常是有一个主设备和一个或多个从设备,一般 SPI 需要 4 根线,但是也可以使用三根线(单向传输),这四根线如下:
①、CS/SS,Slave Select/Chip Select,这个是片选信号线,用于选择需要进行通信的从设备。 I2C 主机是通过发送从机设备地址来选择需要进行通信的从机设备的,SPI 主机不需要发送从机 设备,直接将相应的从机设备片选信号拉低即可。
②、SCK,Serial Clock,串行时钟,和 I2C 的 SCL 一样,为 SPI 通信提供时钟。
③、MOSI/SDO,Master Out Slave In/Serial Data Output,简称主出从入信号线,这根数据线 只能用于主机向从机发送数据,也就是主机输出,从机输入。
④、MISO/SDI,Master In Slave Out/Serial Data Input,简称主入从出信号线,这根数据线只 能用户从机向主机发送数据,也就是主机输入,从机输出。
SPI 通信都是由主机发起的,主机需要提供通信的时钟信号,如下图所示:
SPI 的传输方式:
全双工通信:在任何时刻,主机与从机之间都可以同时进行数据的发送和接收。
单工通信:在同一时刻,只有一个传输的方向,发送或者是接收。
半双工通信:在同一时刻,只能为一个方向传输数据。
单工和双工的区别在于是否能同时发送或者接收,全或者半的区别在于是双向的还是单向的。
SPI工作模式
SPI 有四种工作模式
- CPOL,详称Clock Polarity,就是时钟极性,当主从机没有数据传输的时候 SCL 线的电平状态(即空闲状态)。假如空闲状态是高电平, CPOL = 1;若空闲状态时低电平,那么 CPOL = 0。
- CPHA,详称Clock Phase,就是时钟相位。在这里先科普一下数据传输的常识: 同步通信时,数据的变化和采样都是在时钟边沿上进行的,每一个时钟周期都会有上升沿和下降沿两个边沿,那么数据的变化和采样就分别安排在两个不同的边沿,由于数据在产生和到它稳定是需要一定的时间,那么假如我们在第 1 个边沿信号把数据输出了,从机只能从第 2 个边沿信号去采样这个数据。
通过串行时钟极性(CPOL)和相位(CPHA)的搭配来得到四种工作模式:
-
CPOL = 0&&CPHA = 0时序:由于配置了 CPOL = 0,可以看到当数据未发送或者发送完毕,SCL 的状态是低电平,再者 CPHA = 0 即是奇数边沿采集。所以传输的数据会在奇数边沿上升沿被采集,MOSI 和 MISO 数据的有效信号需要在 SCK 奇数边沿保持稳定且被采样,在非采样时刻, MOSI和 MISO 的有效信号才发生变化。
-
CPOL = 0&CPHA = 1 时序:由于 CPOL = 0,所以 SCL 的空闲状态依然是低电平,CPHA = 1 数据就从偶数边沿采样,至于是上升沿还是下降沿,从上图就可以知道,是下降沿。这里有一个误区,空闲状态是低电平的情况下,不是应该上升沿吗,为什么这里是下降沿?首先我们先明确这里是偶数边沿采样,那么看图就很清晰,SCL 低电平空闲状态下,上升沿是在奇数边沿上,下降沿是在偶数边沿上。
-
CPOL = 1&CPHA = 0 时序:只是这里是 CPOL = 1,即 SCL 空闲状态为高电平,在 CPHA = 0,奇数边沿采样的情况下,数据在奇数边沿下降沿要保持稳定并等待采样。
-
CPOL = 1&&CPHA = 1:可以看到未发送数据和发送数据完毕,SCL的状态是高电平,奇数边沿的边沿极性是上升沿,偶数边沿的边沿极性是下降沿。因为 CPHA= 1,所以数据在偶数边沿上升沿被采样。在奇数边沿的时候 MOSI 和 MISO 会发生变化,在偶数边沿时候是稳定的。
SPI特点
- SPI的优点:
- 全双工串行通信;
- 高速数据传输速率。
- 简单的软件配置;
- 极其灵活的数据传输,不限于8位,它可以是任意大小的字;
- 非常简单的硬件结构。从站不需要唯一地址(与I2C不同)。从机使用主机时钟,不需要精密时钟振荡器/晶振(与UART不同)。不需要收发器(与CAN不同)。
- SPI的缺点:
- 没有硬件从机应答信号(主机可能在不知情的情况下无处发送);
- 通常仅支持一个主设备;
- 需要更多的引脚(与I2C不同);
- 没有定义硬件级别的错误检查协议;
- 与RS-232和CAN总线相比,只能支持非常短的距离;
驱动开发
驱动架构
SPI控制器驱动
SPI 主机驱动就是 SOC 的 SPI 控制器驱动,Linux 内核使用 spi_master 表示 SPI 主机驱动,spi_master 是个结构体,定义在 include/linux/spi/spi.h 文件中。
struct spi_master {struct device dev;int (*transfer)(struct spi_device *spi,struct spi_message *mesg);int (*transfer_one_message)(struct spi_master *master,struct spi_message *mesg);
};
transfer 函数,和i2c_algorithm 中的 master_xfer 函数一样,控制器数据传输函数。transfer_one_message 函数,也用于 SPI 数据发送,用于发送一个 spi_message, SPI 的数据会打包成 spi_message,然后以队列方式发送出去。 也就是 SPI 主机端最终会通过 transfer 函数与 SPI 设备进行通信,
因此对于 SPI 主机控制器的驱动编写者而言 transfer 函数是需要实现的,因为不同的 SOC 其 SPI 控制器不同,寄存器都不一 样。和 I2C 适配器驱动一样,SPI 主机驱动一般都是 SOC 厂商去编写的,所以我们作为 SOC 的 使用者,这一部分的驱动就不用操心了,除非你是在 SOC 原厂工作,内容就是写 SPI 主机驱动。
SPI 主机驱动的核心就是申请 spi_master,然后初始化 spi_master,最后向 Linux 内核注册 spi_master。
- spi_master 申请与释放
spi_alloc_master 函数用于申请 spi_master,函数原型如下:
struct spi_master *spi_alloc_master(struct device *dev, unsigned size)
spi_master 的释放通过 spi_master_put 函数来完成,当我们删除一个 SPI 主机驱动的时候就 需要释放掉前面申请的 spi_master,spi_master_put 函数原型如下:
void spi_master_put(struct spi_master *master)
- spi_master 的注册与注销
当 spi_master 初始化完成以后就需要将其注册到 Linux 内核,spi_master 注册函数为 spi_register_master,函数原型如下:
int spi_register_master(struct spi_master *master)
如果要注销 spi_master 的话可以使用 spi_unregister_master 函数,此函数原型为:
void spi_unregister_master(struct spi_master *master)
SPI 主机驱动一般都由 SOC 厂商编写好了,在设备树中可以看到以下内容:
ecspi3: ecspi@02010000 {address-cells = <1>;#size-cells = <0>;compatible = "fsl,imx6ul-ecspi", "fsl,imx51-ecspi";reg = <0x02010000 0x4000>;interrupts = <GIC_SPI 33 IRQ_TYPE_LEVEL_HIGH>;clocks = <&clks IMX6UL_CLK_ECSPI3>,<&clks IMX6UL_CLK_ECSPI3>;clock-names = "ipg", "per";dmas = <&sdma 7 7 1>, <&sdma 8 7 2>;status = "disabled";
};
在 Linux 内核源码中搜素这两个属性值即可找到 I.MX6U 对应的 ECSPI(SPI) 主机驱动,I.MX6U 的 ECSPI 主机驱动文件为 drivers/spi/spi-imx.c,这个地方文件的命名与不同的芯片对应的名牌名称有关。对应的主机驱动(控制器驱动)也是通过platform架构实现的。
static struct platform_driver spi_imx_driver = {.driver = {.name = DRIVER_NAME,.of_match_table = spi_imx_dt_ids,.pm = IMX_SPI_PM,},.id_table = spi_imx_devtype,.probe = spi_imx_probe,.remove = spi_imx_remove,
};
spi_imx_probe 函数会从设备树中读取相应的节点属性值,申请并初始化 spi_master,最后 调用 spi_bitbang_start 函数(spi_bitbang_start 会调用 spi_register_master 函数)向 Linux 内核注册 spi_master。
spi_imx_probe->设置spi_imx->bitbang.setup_transfer = spi_imx_setupxfer;//设置发送或者接收字节数量->设置spi_imx->bitbang.txrx_bufs = spi_imx_transfer->spi_imx_pio_transfer()->spi_imx_push()->spi_imx->tx(spi_imx);//发送函数配置->spi_bitbang_start->注册spi_register_master;->设置master->transfer_one_message = spi_bitbang_transfer_one;
spi_imx 是个 spi_imx_data 类型的机构指针变量,其中 tx 和 rx 这两个成员变量分别为 SPI 数据发送和接收函数,最终会将spi_bitbang_transfer_one函数配置为第二行的发生配置函数。
SPI设备驱动
spi 设备驱动和 i2c 设备驱动也很类似,Linux 内核使用 spi_driver 结构体来表示 spi 设备驱 动,我们在编写 SPI 设备驱动的时候需要实现 spi_driver 。 spi_driver 结构体定义在 include/linux/spi/spi.h 文件中,结构体内容如下:
struct spi_driver {const struct spi_device_id *id_table;int (*probe)(struct spi_device *spi);int (*remove)(struct spi_device *spi);void (*shutdown)(struct spi_device *spi);struct device_driver driver;
};
spi_driver 注册函数为 spi_register_driver,函数原型如下:
int spi_register_driver(struct spi_driver *sdrv)
注销 SPI 设备驱动以后也需要注销掉前面注册的 spi_driver,使用 spi_unregister_driver 函 数完成 spi_driver 的注销,函数原型如下:
void spi_unregister_driver(struct spi_driver *sdrv)
SPI 设备和驱动匹配过程
SPI 设备和驱动的匹配过程是由 SPI 总线来完成的,这点和 platform、I2C 等驱动一样,SPI 总线为 spi_bus_type,定义在 drivers/spi/spi.c 文件中,驱动的匹配函数为 spi_match_device。
struct bus_type spi_bus_type = {.name = "spi",.dev_groups = spi_dev_groups,.match = spi_match_device,.uevent = spi_uevent,
};
SPI其他相关API函数
spi_transfer 结构体用于描述 SPI 传输信息
struct spi_transfer {/* it's ok if tx_buf == rx_buf (right?)* for MicroWire, one buffer must be null* buffers must work with dma_*map_single() calls, unless* spi_message.is_dma_mapped reports a pre-existing mapping*/const void *tx_buf; //tx_buf 保存着要发送的数据。void *rx_buf; //rx_buf 用于保存接收到的数据。unsigned len;dma_addr_t tx_dma;dma_addr_t rx_dma;struct sg_table tx_sg;struct sg_table rx_sg;unsigned cs_change:1;unsigned tx_nbits:3;unsigned rx_nbits:3;
#define SPI_NBITS_SINGLE 0x01 /* 1bit transfer */
#define SPI_NBITS_DUAL 0x02 /* 2bits transfer */
#define SPI_NBITS_QUAD 0x04 /* 4bits transfer */u8 bits_per_word;u16 delay_usecs;u32 speed_hz;struct list_head transfer_list;
};
spi_transfer 需要组织成 spi_message,spi_message 也是一个结构体
在使用 spi_message 之前需要对其进行初始化,spi_message 初始化函数为 spi_message_init, 函数原型如下:
void spi_message_init(struct spi_message *m)
spi_message 初始化完成以后需要将 spi_transfer 添加到 spi_message 队列中,这里我们要用 到 spi_message_add_tail 函数,此函数原型如下:
void spi_message_add_tail(struct spi_transfer *t, struct spi_message *m)
spi_message 准备好以后就可以进行数据传输了,数据传输分为同步传输和异步传输,同步 传输会阻塞的等待 SPI 数据传输完成,同步传输函数为 spi_sync,函数原型如下:
int spi_sync(struct spi_device *spi, struct spi_message *message)
异步传输不会阻塞的等到 SPI 数据传输完成,异步传输需要设置 spi_message 中的 complete 成员变量,complete 是一个回调函数,当 SPI 异步传输完成以后此函数就会被调用。SPI 异步传 输函数为 spi_async,函数原型如下:
int spi_async(struct spi_device *spi, struct spi_message *message)
参考文献
- 个人专栏系列文章
- 正点原子嵌入式驱动开发指南
- 对代码有兴趣的同学可以查看链接https://github.com/NUAATRY/imx6ull_dev
相关文章:
嵌入式驱动开发详解14(SPI驱动架构实现)
文章目录 前言SPI简介SPI介绍SPI工作模式SPI特点 驱动开发驱动架构SPI控制器驱动SPI设备驱动SPI 设备和驱动匹配过程SPI其他相关API函数 参考文献 前言 SPI 是很常用的串行通信协议,可以通过 SPI 来连接众多的传感器,相比 I2C 接 口,SPI 接口…...
【保姆级系列:思科模拟器安装下载汉化教程大全】
文章目录 概述Packet Tracer下载Packet Tracer安装Packet Tracer使用EVE-NG下载:EVE-NG安装:EVE-NG使用: 概述 思科在网络界的地位是众所周知的。如果说在中美科技战中,华为代表CHN,那么思科就代表US,依然…...
2024 一带一路暨金砖国家技能发展与技术创新大赛【网络安全防护治理实战技能赛项】样题(中职组)
2024 一带一路暨金砖国家技能发展与技术创新大赛【网络安全防护治理实战技能赛项】样题(中职组) 1.基础设置和安全强化(xxx 分)1.3. 任务内容: 2.安全监测和预警(xxx 分)2.1. 任务一:建立目录安…...
QT 中基于 TCP 的网络通信
基础 基于 TCP 的套接字通信需要用到两个类: 1)QTcpServer:服务器类,用于监听客户端连接以及和客户端建立连接。 2)QTcpSocket:通信的套接字类,客户端、服务器端都需要使用。 这两个套接字通信类…...
React Native 速度提升 550%
React Native 爱好者们!🌟 您准备好听一些激动人心的消息了吗?React Native 刚刚发布了其最大的更新之一:一种全新的架构,彻底改变了我们构建移动应用程序的方式。如果您想知道这对您的项目和开发体验意味着什么,请继续关注!我们正在深入探讨这个改变游戏规则的事物;您…...
火语言RPA流程组件介绍--键盘按键
🚩【组件功能】:模拟键盘按键 配置预览 配置说明 按键 点击后,在弹出的软键盘上选择需要的按键 执行后等待时间(ms) 默认值300,执行该组件后等待300毫秒后执行下一个组件. 输入输出 输入类型 万能对象类型(System.Object)输出类型 万能对象类型…...
数值分析—数值积分
研究背景 积分的数学解法为牛顿莱布尼兹公式,数学表示为 ∫ a b f ( x ) d x F ( b ) − F ( a ) \int_{a}^{b} f(x)dxF(b)-F(a) ∫abf(x)dxF(b)−F(a),但应用该方法有如下困难: 1, f ( x ) f(x) f(x)的原函数有时不能用初等函…...
Next.js优化教程:优化字体加载
更多有关Next.js教程,请查阅: 【目录】Next.js 独立开发系列教程-CSDN博客 目录 更多有关Next.js教程,请查阅: 前言 1. 字体加载的常见问题 1.1 什么是 FOIT 和 FOUT? 1.2 字体优化的核心目标 2. Next.js 字体优…...
功能篇:springboot中全局异常
在Java应用程序中实现全局异常处理是确保应用健壮性和用户体验良好性的重要一步。通过全局异常处理,你可以集中管理所有未捕获的异常,并以统一的方式响应它们。对于Web应用程序(如使用Spring框架的应用),通常会创建一个…...
【go 】 select case 的用法
文章目录 1. 基本使用:监听多个通道,会阻塞2.带默认分支:非阻塞操作3. 永远监听多个通道4. 超时机制5. 关闭通道的处理6. context的关闭判断 相关文章: 【go】select 语句case的随机性 【go】 select case 超时机制(time.After)示…...
出海服务器可以用国内云防护吗
随着企业国际化进程的加速,越来越多的企业选择将业务部署到海外服务器上,以便更贴近国际市场。然而,海外服务器也面临着来自全球各地的安全威胁和网络攻击。当出海服务器遭受攻击时,是否可以借助国内的云服务器来进行有效的防护呢…...
前端权限控制
前端权限控制 一、路由权限(控制页面访问) vue // router.js const routes [{path: /dashboard,name: Dashboard,component: () > import(/views/Dashboard.vue),meta: { requiresAuth: true, roles: [admin, manager] }},{path: /user,name: Use…...
计算机组成原理(二):指令跳转
指令跳转(Instruction Jump)是计算机程序控制流的重要组成部分,通过改变程序的执行顺序实现循环、条件分支和函数调用等功能。 基本概念 跳转指令主要用来修改**程序计数器(Program Counter, PC)**的值,使…...
LoViT: 用于手术阶段识别的长视频Transformer|文献速递-生成式模型与transformer在医学影像中的应用
Title 题目 LoViT: Long Video Transformer for surgical phase recognition LoViT: 用于手术阶段识别的长视频Transformer 01 文献速递介绍 快速发展的手术数据科学(SDS)领域旨在通过先进利用手术室(OR)内医疗设备采集的数据…...
【传感器技术】第4章 力敏传感器,弹性敏感元件的基本特性,应变式压力传感器,电阻应变片的温度补偿,压阻式压力传感器,压电式压力传感器
关注作者了解更多 我的其他CSDN专栏 过程控制系统 工程测试技术 虚拟仪器技术 可编程控制器 工业现场总线 数字图像处理 智能控制 传感器技术 嵌入式系统 复变函数与积分变换 单片机原理 线性代数 大学物理 热工与工程流体力学 数字信号处理 光电融合集成电路…...
linux之vim
一、模式转换命令 vim主要有三种模式:命令模式(Normal Mode)、输入模式(Insert Mode)和底线命令模式(Command-Line Mode)。 从命令模式切换到输入模式:i:在当前光标所在…...
【LeetCode】每日一题 2024_12_9 判断国际象棋棋盘中一个格子的颜色(找规律)
前言 每天和你一起刷 LeetCode 每日一题~ LeetCode 启动! 题目:判断国际象棋棋盘中一个格子的颜色 最近力扣一直在出棋盘类的题目,这个月已经出了 9 天了,我倒要看看他是不是真能出一个月 代码与解题思路 先读题:题…...
HCL虚拟环境搭建并且支持ssh远程访问
1.连接设备 新建设备和host主机,连线,host主机选择本地网卡(不选host-only网卡) 2.启动设备,打开终端,按ctrlc 3.执行命令 <H3C>system-view [H3C]int g0/0 [H3C-GigabitEthernet0/0]ip address …...
批量验证指定漏洞思路和流程
免责申明 本文仅是用于学习研究POC的地址收集与漏洞验证原理,请勿用在非法途径上,若将其用于非法目的,所造成的一切后果由您自行承担,产生的一切风险和后果与笔者无关;本文开始前请认真详细学习《中华人民共和国网络安全法》【学法时习之丨网络安全在身边一图了解网络安…...
首次打开韦东山提供的Ubuntu-18.04镜像后,该做哪些事?
目录 01-测试有无网络02-配置最基本的嵌入式开发环境(安装tftp-nfs等)03-缩短关机强制结束进行时间04-关闭软件的自动更新05-未完待续... 01-测试有无网络 ping www.baidu.com 02-配置最基本的嵌入式开发环境(安装tftp-nfs等) 需要安装 tftp,nfs,vim …...
怎么才能让图片不能转发截图保存
发私密图片给好友又担心被截图保存甚至转发给第三人?有没有办法让发出去的图片不能转发、截图、保存?当然有!今天教你一招,并且对方打开不需要下载任何软件,发出去对方点开就能看。 操作步骤 如何发送这样限制截图的图…...
设计模式-装饰器模式(结构型)与责任链模式(行为型)对比,以及链式设计
提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档 文章目录 前言1.装饰器模式1.1概念1.2作用1.3应用场景1.4特点1.5类与对象关系1.6实现 2责任链模式2.1概念2.2作用2.3应用场景2.4特点2.5类与对象关系2.6实现 3.对比总结 前言…...
outlook软件配置邮箱提示“到邮件服务器的加密连接不可用”
outlook软件配置邮箱提示“到邮件服务器的加密连接不可用” 问题描述: outlook软件里邮箱提示“已断开”或配置邮箱时提示“到邮件服务器的加密连接不可用”。 解决方案: 一、更改注册表(可先导出备份) winr,输入re…...
通过QT实现进度条随着读取文件增加
mythread循环给主线程发送信号实现主线程循环的功能 widget.h #ifndef WIDGET_H #define WIDGET_H#include <QWidget> #include <QFile> #include <QFileDialog> #include <QTextStream> #include <QByteArray> #include "mythread.h"…...
构建高效可靠的分布式推理系统:深入解析控制器与模型服务的协同工作
在现代互联网应用中,随着用户需求的增长和技术的进步,单一服务器已经难以满足大规模并发请求的需求。为了提升系统的性能和可靠性,开发者们越来越多地采用分布式架构。本文将结合具体的代码示例,深入浅出地探讨如何构建一个高效的分布式推理系统,并详细解析其中的关键组件…...
洛谷B2082
数字统计 - 洛谷 数字统计 题目描述 请统计某个给定范围 [L,R] 的所有整数中,数字 2 出现的次数。 比如给定范围 [2,22],数字2 在数 2 中出现了 1 次,在数 12 中出现 1 次,在数 20中出现 1次,在数 21 中出现 1 次&…...
HTML5系列(14)-- 链接与资源关系指南
前端技术探索系列:HTML5 链接与资源关系指南 🔗 致读者:探索资源加载的艺术 👋 前端开发者们, 今天我们将深入探讨 HTML5 的链接与资源关系管理,学习如何优化网站的资源加载策略,提升用户体验…...
ubuntu系统每天凌晨定时上传redis 备份数据到阿里云OSS上
1.压缩备份脚本 1.1 代码如下#!/bin/bash# redis_backup_compress.sh # 设置变量 BACKUP_DIR"/data/redis/backup" REDIS_DIR"/var/lib/redis" DATE$(date %Y%m%d_%H%M%S) BACKUP_FILE"redis_backup_${DATE}.rdb" COMPRESSED_FILE"redis_b…...
uniapp结合movable-area与movable-view实现拖拽功能
前言 因为公司业务开发需要拖拽功能。 ps:该功能只能针对高度一致的,如果高度不一致需要另外二开 演示 开始 <template><view style"height: 100%;"><movable-area :style"{width: 100%, height: allHeight px}"…...
JavaScript 单例模式的创建与应用
JavaScript 单例模式的创建与应用 单例模式(Singleton Pattern)是一种设计模式,旨在确保一个类只有一个实例,并提供全局访问点。在 JavaScript 中,单例模式可以帮助我们避免多次创建同一个对象,节省资源&a…...
【HarmonyOS】 鸿蒙保存图片或视频到相册
【HarmonyOS】 鸿蒙保存图片或视频到相册 前言 鸿蒙中保存图片或者视频,或者其他媒体文件到设备的媒体库,可以是相册,也可以是文件管理等。共有两种方式: 需要应用申请受限权限,获取文件读写的权限(调用…...
windows下nacos启动报错:java.lang.unsatisfiedLinkError: C:\USers\乱码AppData\xxx.dll
问题 看了许多别的帖子,大家都是因为缺少dll包,下载安装 Microsoft Visual C 2015 Redistributable 就可以。但我试过了不行。思来想去,之前正常的时候用的JDK版本是17,后面别的项目用1.8给切换回来了。然后尝试配置环境变量将JD…...
梳理你的思路(从OOP到架构设计)_基本OOP知识01
目录 1、“-Oriented” 的涵意 2、 ” -Oriented”、” -Based”、” -Driven”、” -Centered” 它们之间区别 3、 从对象(Object) 谈起 4、类的用途: 叙述软件对象 Android从程序员到架构师之路:梳理你的思路(从OOP到架构设计) 1、“-Oriented” …...
【C++图论 BFS算法】2467. 树上最大得分和路径|2053
本文涉及知识点 C图论 CBFS算法 LeetCode2467. 树上最大得分和路径 一个 n 个节点的无向树,节点编号为 0 到 n - 1 ,树的根结点是 0 号节点。给你一个长度为 n - 1 的二维整数数组 edges ,其中 edges[i] [ai, bi] ,表示节点 a…...
Java的Mvc整合Swagger的knife4框架
Swagger的介绍 Swagger 是一个规范和完整的框架,用于生成、描述、调用和可视化 RESTful 风格的 Web 服务。使用Swagger,就是把相关的信息存储在它定义的描述文件里面(yml或json格式),再通过维护这个描述 文件可以去更…...
AI项目二十六:YOLOV11简单部署测试
若该文为原创文章,转载请注明原文出处。 一、YOLOv11介绍 继YOLOv 8、YOLOv 9和YOLOv10之后,发布的YOLOV11引入了几个突破性的增强功能,为目标检测和计算机视觉设定了新的基准。 增强的特征提取:YOLOv11使用改进的主干和颈部架构…...
19. Three.js案例-创建一个带有纹理映射的旋转平面
19. Three.js案例-创建一个带有纹理映射的旋转平面 实现效果 知识点 WebGLRenderer (WebGL渲染器) WebGLRenderer 是 Three.js 中用于渲染场景的主要类。它利用 WebGL 技术在浏览器中绘制 3D 图形。 构造器 new THREE.WebGLRenderer(parameters)参数类型描述parametersobj…...
【Makefile】编译日志之输出重定向符号 >
用法1 make all >& compilelog.txt make all > compilelog.txt这两个编译命令在功能上有一些细微的区别,主要在于标准输出和标准错误的处理方式。 make all >& compilelog.txt 这个命令会将标准输出(stdout)和标准错误&a…...
TDengine 新功能 复合主键
1. 简介 从 TDengine 3.3.0.0 版本之后,新增了复合主键的功能。 TDengine 原来的时间列是不允许有重复时间戳的,有了复合主键功能后,时间列即允许有重复,重复后的时间戳按紧跟其后第二列主键列的值来确定唯一性。 此功能的常用…...
【OpenHarmony】初识设备间互联互通的统一基础:分布式软总线
分布式软总线 前言软总线软总线代码目录软总线传输模块概述传输模块主要对外接口和使用方式 前言 很久没有写出一篇能够分享出来的学习心得了,零零散散地写了好多,总是不太满意。今年8月份开始正式投入精力去学习open harmony,记得第一次接触…...
yocto加软件包install 动态链接库报错
加入bb文件,编译通过 在install时报错 报错 ERROR: demo-1.0-r0 do_package_qa: QA Issue: -dev package agent-dev contains non-symlink .so ‘/usr/lib64/libdemo.so’ 解决 在bb文件install前加2行 SOLIBS ".so" FILES_SOLIBSDEV ""do_install …...
《数据结构》(408代码题)
2009 单链表(双指针) 分析:首先呢,给我们的数据结构是一个带有表头结点的单链表,也不允许我们改变链表的结构。链表的长度不是直接给出的啊,所以这个倒数也很棘手。那我们该如何解决这个“k”呢,…...
哈希表的完善及unordered_map/unordered_set封装
1.哈希表的完善 1.1 优化:哈希函数 在实际使用中,往往需要以字符串作为存储依据(键值),比如姓名与快递信息、商品名称与价格、中文单词与英文释义等。 而在上一篇文章中,我们实现的哈希表只考虑了整型的存储情况,即直…...
“物联·数据·产融·场景”聚力垂直数智场景下的新质生产力破局
人工智能、物联网(简称AIOT)正在深刻改变世界的经济格局,对各行各业产生深厚的影响。12月6日,由深圳市物联网协会、华夏银行深圳分行、深圳市区块链技术应用协会、深圳市康复辅助器具智能技术应用协会联合主办的第五届AIOT生态大会…...
API接口的性能测试与优化策略
在现代软件开发中,API(应用程序编程接口)扮演着至关重要的角色,它们作为不同服务之间的桥梁,确保数据的顺畅流通与交互。然而,随着用户需求的不断增长和系统复杂性的提升,API接口的性能问题日益…...
【Vue】Part4 接口调用
接口调用方式 原生ajax基于jQuery的ajaxfetchaxios 异步 JavaScript的执行环境是「单线程」所谓单线程,是指JS引擎中负责解释和执行JavaScript代码的线程只有一个,也就是一次只能完成一项任务,这个任务执行完后才能执行下一个,…...
管理系统前端框架开发案例学习
一、 需求分析 本案例的主要目标是开发一个智能学习辅助系统的前端界面,涵盖以下功能模块: 首页:显示系统的总体概览和关键功能介绍。 班级学员管理:实现班级管理和学员管理。 系统信息管理:管理部门和员工信息。 …...
协程设计原理与实现
协程设计原理与汇编实现 同步与异步 对于任何一个事情,都可以划分为不同的步骤。所谓同步,就先做第一个事情,按照这件事的步骤完成这件事之后,再去做第二件事。再去做第三件事,以此类推。 异步就是,可以…...
c++广播通讯的实现
概念大家都很清楚,不赘述。 广播必然用UDP这套东西。 setsockopt() 函数及其在广播中的应用: 在 C 网络编程中,setsockopt() 函数用于设置套接字选项,这些选项可以控制套接字的各种行为。对于广播通信,我们特别关心…...
Leetcode 3377. Digit Operations to Make Two Integers Equal
Leetcode 3377. Digit Operations to Make Two Integers Equal 1. 解题思路2. 代码实现 题目链接:3377. Digit Operations to Make Two Integers Equal 1. 解题思路 这一题的核心思路属于路径遍历问题,我们使用一个堆排来控制最优路径的选择。 我们首…...