当前位置: 首页 > article >正文

音视频——I2S 协议详解

I2S 协议详解


I2S (Inter-IC Sound) 协议是一种串行总线协议,专门用于在数字音频设备之间传输数字音频数据。它由飞利浦(Philips)公司开发,以其简单、高效和广泛的兼容性而闻名。

1. 信号线

I2S 协议通常使用三根或四根信号线:

  • SCK (Serial Clock / Bit Clock): 串行时钟,也称位时钟。它决定了数据传输的速率,每个时钟周期传输一个数据位。
  • WS (Word Select / Left/Right Clock / Frame Sync): 字选择信号,也称左右声道时钟或帧同步信号。它指示当前传输的是左声道数据还是右声道数据,并标志一个音频帧的开始。
  • SD (Serial Data / Data Line): 串行数据线。音频数据通过这根线传输。
  • MCLK (Master Clock / System Clock - Optional): 主时钟,也称系统时钟。这根线是可选的,用于提供系统级的时钟,通常是SCK的整数倍。如果存在,它可以用于生成SCK和WS。

图1: I2S 信号线连接示意图

              -----------------------|       Master        || (e.g., Audio Source)|-----------------------|   |   |   ||   |   |   | (Optional)SCK WS  SD  MCLK|   |   |   ||   |   |   |-----------------------|       Slave         || (e.g., Audio DAC)   |-----------------------

2. 时序

I2S 协议的时序是理解其工作方式的关键。

图2: I2S 数据传输时序图 (标准 I2S 模式)

             _______________   _______________   _______________
SCK: _______|               |_|               |_|               |___ ..._________________                 _________________
WS: _________|                 |_______________|                 |___ ..._________________ _______ _______ _________________
SD: _________| D0_L | D1_L |...| Dn_L | D0_R | D1_R |...| Dn_R |___ ...<----- Left Channel ------> <----- Right Channel ------><-------------------- Audio Frame -------------------->

时序解释:

  • SCK (位时钟): 在 SCK 的每个上升沿或下降沿(取决于实现)会传输一个数据位。通常在 SCK 的下降沿采样数据,在 SCK 的上升沿输出数据。
  • WS (字选择):
    • 当 WS 为低电平(通常为 0)时,表示传输的是左声道数据。
    • 当 WS 为高电平(通常为 1)时,表示传输的是右声道数据。
    • WS 信号在每个音频帧开始时翻转,并且在整个声道数据传输过程中保持稳定。
    • WS 信号的变化发生在 SCK 信号的第一个位之前一个 SCK 周期。
  • SD (串行数据):
    • 数据通常是 MSB (Most Significant Bit) 在前,LSB (Least Significant Bit) 在后。
    • 每个声道的字长可以是 16 位、24 位、32 位等,具体取决于设备支持的精度。
    • 数据的有效位通常从 WS 变化后第二个 SCK 周期开始。这意味着在 WS 变化后的第一个 SCK 周期,数据线上是无用的。这种偏移是 I2S 标准的一个特点。

图3: I2S 数据位对齐方式 (举例: 16位数据)

             _______________   _______________   _______________
SCK: _______|               |_|               |_|               |___ ..._________________                 _________________
WS: _________|                 |_______________|                 |___ ..._________________ _________________________________
SD: _________|  Dummy Bit(s)   |  D15 | D14 | ... | D1 | D0     |___ ...<----------------> <----------- 16-bit Data ----------->^WS change^First SCK after WS change^Actual data starts here

数据位对齐方式的特点:

  • I2S 协议规定,在 WS 信号切换后,SD 线上的第一个有效数据位(MSB)在第二个 SCK 的上升沿或下降沿开始。这意味着在 WS 切换后的第一个 SCK 周期,SD 线上的数据是无效的,或者说是一个“虚拟位”。这种对齐方式被称为“左对齐,数据延迟一位”。
  • 数据字长可以小于或等于 SCK 周期数减去一个虚拟位的数量。例如,如果一个声道传输 16 位数据,并且 SCK 周期数为 32 (对应一个 32 位字),那么 I2S 会在传输完 16 位数据后,在 SD 线上输出 16 个无效位。

3. I2S 的几种模式

除了标准的 I2S 模式,还有一些其他的模式,但标准 I2S 是最常见的。

  • 标准 I2S 模式 (Standard I2S): 如上所述,数据在 WS 变化后延迟一个 SCK 周期。
  • 左对齐模式 (Left-Justified / MSB-Justified): 数据没有延迟,MSB 在 WS 变化后的第一个 SCK 周期就出现。
  • 右对齐模式 (Right-Justified / LSB-Justified): 数据被填充到字的右侧,LSB 在字的最后一个 SCK 周期出现。
  • PCM 模式 (Pulse Code Modulation / DSP Mode): 用于传输 TDM (Time Division Multiplexed) 数据,通常用于多通道音频。

I2S 协议的应用流程

I2S 协议的应用通常涉及以下步骤:

  1. 硬件连接:
    • 连接音频源(如微控制器、DSP)和音频接收器(如 DAC、ADC)的 I2S 引脚。
    • 确保 SCK、WS、SD 甚至 MCLK(如果使用)正确连接。
  2. 配置时钟:
    • 确定 I2S 的主设备和从设备。通常音频源是主设备(提供 SCK 和 WS),音频接收器是从设备。
    • 配置主设备生成正确的 SCK 频率和 WS 频率。SCK 频率通常是采样率的整数倍(例如,32 * 采样率),WS 频率等于采样率。
    • 如果使用 MCLK,确保其频率满足设备要求。
  3. 配置数据格式:
    • 确定数据字长(例如 16 位、24 位、32 位)。
    • 确定是立体声还是单声道传输。
    • 配置数据对齐方式(标准 I2S 模式是最常见的)。
  4. 数据传输:
    • 发送端 (Master): 根据 I2S 时序,将音频数据逐位地写入 SD 线,并同步 SCK 和 WS 信号。通常使用 DMA (Direct Memory Access) 来高效地传输数据,以减轻 CPU 负担。
    • 接收端 (Slave): 根据 I2S 时序,在 SCK 触发时从 SD 线读取数据,并根据 WS 信号区分左右声道。接收到的数据通常存储在缓冲区中,然后由 DAC 转换为模拟信号输出。
  5. 错误处理 (可选):
    • 可以实现一些错误检测机制,例如校验和,以确保数据完整性。
    • 处理同步丢失等问题。

I2S 协议代码示例 (基于 STM32 微控制器)

由于 I2S 协议通常在嵌入式系统中实现,我将提供一个基于 STM32 微控制器的代码示例。STM32 微控制器集成了专门的 I2S 外设,这使得实现变得相对简单。

这个示例将演示如何使用 STM32 的 I2S 外设作为主设备(Master)输出音频数据。假设我们有一个 STM32F4 系列的微控制器,并连接到一个 I2S DAC(例如 PCM5102A)。

重要提示:

  • 这只是一个概念性的示例,实际应用需要根据你的具体硬件(DAC型号、引脚连接、时钟源)进行调整。
  • 你需要配置 STM32CubeMX 或手动配置寄存器来初始化 I2S 外设和相关的 GPIO。
  • 音频数据(audio_buffer)需要由你的应用生成,例如从 ADC 采集、从文件读取或生成测试音。

1. STM32CubeMX 配置 (概念性描述)

在 STM32CubeMX 中,你需要:

  • 启用 I2S 外设: 选择一个支持 I2S 的 SPI 外设 (例如 SPI2)。
  • 配置模式: 设置为 Master Transmit。
  • 时钟配置: 根据你的系统时钟和所需的采样率,配置 I2S 的时钟源和分频器,以生成正确的 SCK 频率。
  • DMA 配置: 为 I2S TX 配置 DMA 通道,以实现高效数据传输。
  • GPIO 配置: 配置 I2S 相关的引脚(SCK, WS, SD)为复用功能。

2. 核心代码示例

#include "main.h" // 包含 CubeMX 生成的头文件
#include "stm32f4xx_hal.h" // HAL 库头文件// 假设 I2S 外设句柄已在 main.c 中定义并初始化
extern I2S_HandleTypeDef hi2s2; // 假设使用 SPI2 作为 I2S 外设// 定义音频数据缓冲区
#define AUDIO_BUFFER_SIZE  4096 // 缓冲区大小,可以根据需要调整
#define SAMPLE_RATE        44100 // 采样率 (Hz)
#define CHANNELS           2     // 声道数 (立体声)
#define BITS_PER_SAMPLE    16    // 每样本位数// 16位立体声音频数据缓冲区 (左声道L,右声道R交替)
// 假设数据格式为 S16_LE (Signed 16-bit, Little Endian)
int16_t audio_buffer[AUDIO_BUFFER_SIZE];// DMA 回调函数 - 缓冲区传输完成
void HAL_I2S_TxCpltCallback(I2S_HandleTypeDef *hi2s)
{if (hi2s->Instance == hi2s2.Instance){// 缓冲区已传输完成,可以重新填充缓冲区// 在这里可以处理音频数据的读取、生成或切换到下一个缓冲区// 例如,从SD卡读取下一块音频数据// 为了简单,我们这里只是重新启动传输,实际应用中会加载新数据HAL_I2S_Transmit_DMA(&hi2s2, (uint16_t*)audio_buffer, AUDIO_BUFFER_SIZE);}
}// DMA 回调函数 - 半缓冲区传输完成
void HAL_I2S_TxHalfCpltCallback(I2S_HandleTypeDef *hi2s)
{if (hi2s->Instance == hi2s2.Instance){// 缓冲区的前半部分已传输完成// 在这里可以填充缓冲区的后半部分,实现“双缓冲”机制// 从而确保连续不间断的音频输出}
}// 初始化音频缓冲区 (用于演示,实际应由音频源填充)
void init_audio_buffer(void)
{for (int i = 0; i < AUDIO_BUFFER_SIZE / 2; i++){// 生成一个简单的正弦波作为测试音// 左声道audio_buffer[2 * i] = (int16_t)(30000.0 * sin(2.0 * M_PI * 440.0 * i / SAMPLE_RATE));// 右声道 (这里和左声道相同,可以根据需要修改)audio_buffer[2 * i + 1] = (int16_t)(30000.0 * sin(2.0 * M_PI * 440.0 * i / SAMPLE_RATE));}
}int main(void)
{/* MCU Configuration--------------------------------------------------------*/HAL_Init(); // 初始化 HAL 库SystemClock_Config(); // 配置系统时钟 (由 CubeMX 生成)/* Initialize all configured peripherals */MX_GPIO_Init(); // 初始化 GPIO (由 CubeMX 生成)MX_DMA_Init();  // 初始化 DMA (由 CubeMX 生成)MX_SPI2_I2S_Init(); // 初始化 I2S (由 CubeMX 生成)// 初始化音频缓冲区init_audio_buffer();// 启动 I2S DMA 传输// hi2s2: I2S 句柄// (uint16_t*)audio_buffer: 待传输的数据 (I2S DMA 通常按16位传输)// AUDIO_BUFFER_SIZE: 传输的样本数量 (对于16位立体声,这里是总的16位样本数,即声道数 * 单声道样本数)HAL_I2S_Transmit_DMA(&hi2s2, (uint16_t*)audio_buffer, AUDIO_BUFFER_SIZE);while (1){// 主循环,可以执行其他任务// 音频数据传输由 DMA 自动完成}
}// 确保在你的 main.c 文件中,hi2s2 句柄已正确初始化,例如:
/*
I2S_HandleTypeDef hi2s2;void MX_SPI2_I2S_Init(void)
{hi2s2.Instance = SPI2;hi2s2.Init.Mode = I2S_MODE_MASTER_TX;hi2s2.Init.Standard = I2S_STANDARD_PHILIPS; // 标准 I2S 模式hi2s2.Init.DataFormat = I2S_DATAFORMAT_16B_EXTENDEDSA; // 16位数据,32位帧hi2s2.Init.MCLKOutput = I2S_MCLKOUTPUT_ENABLE; // 如果需要输出 MCLKhi2s2.Init.AudioFreq = I2S_AUDIOFREQ_44K; // 44.1kHz 采样率hi2s2.Init.CPOL = I2S_CPOL_LOW; // 时钟极性hi2s2.Init.ClockSource = I2S_CLOCK_PLLR; // I2S 时钟源 (例如 PLLR)hi2s2.Init.FullDuplexMode = I2S_FULLDUPLEXMODE_DISABLE; // 单工模式 (发送)if (HAL_I2S_Init(&hi2s2) != HAL_OK){Error_Handler();}
}
*/

代码解释:

  • audio_buffer: 这是一个 int16_t 类型的数组,用于存储音频数据。由于是立体声,数据通常是左声道和右声道交替存储。AUDIO_BUFFER_SIZE 定义了缓冲区中 int16_t 元素的数量。

  • HAL_I2S_TxCpltCallbackHAL_I2S_TxHalfCpltCallback:

    这是 HAL 库提供的 DMA 传输完成和半传输完成的回调函数。

    • 当 DMA 传输完整个 audio_buffer 时,会调用 HAL_I2S_TxCpltCallback。你可以在这里加载下一批音频数据。
    • 当 DMA 传输完 audio_buffer 的前半部分时,会调用 HAL_I2S_TxHalfCpltCallback。这允许你在上半部分数据传输的同时填充下半部分数据,从而实现连续的、无间断的音频播放(双缓冲机制)。
  • HAL_I2S_Transmit_DMA(): 这是 HAL 库函数,用于启动 I2S 通过 DMA 进行数据传输。它将 audio_buffer 中的数据发送到 I2S 外设。

  • init_audio_buffer(): 一个简单的函数,用于填充音频缓冲区。在实际应用中,这里的数据可能来自麦克风、SD 卡、蓝牙模块或其他数字音频源。

  • MX_SPI2_I2S_Init() (在 main.c 或其他文件中): 这个函数(通常由 CubeMX 生成)初始化 I2S 外设,包括设置工作模式(主发送)、标准(飞利浦 I2S)、数据格式、时钟源和频率等。

运行流程:

  1. 初始化: 微控制器启动,HAL 库和 I2S 外设被初始化。
  2. 数据填充: audio_buffer 被填充初始音频数据。
  3. 启动 DMA 传输: HAL_I2S_Transmit_DMA() 被调用,I2S 外设开始从 audio_buffer 中通过 DMA 自动读取数据,并按照 I2S 协议时序将其发送到 SD 线。
  4. 连续播放: 当 DMA 传输到 audio_buffer 的一半或全部完成时,会触发相应的回调函数。在这些回调函数中,你可以填充或加载新的音频数据到 audio_buffer,从而实现连续的音频播放。这种双缓冲或多缓冲机制对于不间断音频流至关重要。
  5. DAC 接收: 连接到 STM32 的 I2S DAC 会接收 SCK、WS 和 SD 信号,并根据这些信号将数字音频数据转换为模拟音频信号输出到扬声器或耳机。

相关文章:

音视频——I2S 协议详解

I2S 协议详解 I2S (Inter-IC Sound) 协议是一种串行总线协议&#xff0c;专门用于在数字音频设备之间传输数字音频数据。它由飞利浦&#xff08;Philips&#xff09;公司开发&#xff0c;以其简单、高效和广泛的兼容性而闻名。 1. 信号线 I2S 协议通常使用三根或四根信号线&a…...

七、数据库的完整性

七、数据库的完整性 主要内容 7.1 数据库的完整性概述 7.2 实体完整性 7.3 参照完整性 7.4 用户定义的完整性 7.5 触发器 7.6 SQL Server中数据库完整性的实现 7.7 小结 7.1 数据库的完整性概述 数据库完整性的含义 正确性 指数据的合法性 有效性 指数据是否属于所定…...

人工智能(大型语言模型 LLMs)对不同学科的影响以及由此产生的新学习方式

今天是关于AI如何在教学中增强学生的学习体验&#xff0c;我把重要信息标红了。人文学科的价值被低估了 ⬇️ 转型与必要性 人工智能正在深刻地改变教育&#xff0c;这并非炒作&#xff0c;而是已经发生的巨大变革。教育机构和教育者不能忽视它&#xff0c;试图简单地禁止学生使…...

安全突围:重塑内生安全体系:齐向东在2025年BCS大会的演讲

文章目录 前言第一部分&#xff1a;体系力量是突围之钥第一重困境是体系思想落地不畅。第二重困境是大小体系融合瓶颈。第三重困境是“小体系”运营梗阻。 第二部分&#xff1a;体系矛盾是突围之障一是数据孤岛的障碍。二是投入不足的障碍。三是新旧兼容难的障碍。 第三部分&am…...

处理vxe-table 表尾数据是单独一个接口,表格tableData数据更新后,需要点击两下,表尾才是正确的

修改bug思路&#xff1a; 分别把 tabledata 和 表尾相关数据 console.log() 发现 更新数据先后顺序不对 settimeout延迟查询表格接口 ——测试可行 升级↑&#xff1a;async await 等接口返回后再开始下一个接口查询 ________________________________________________________…...

排序算法总结(C++)

目录 一、稳定性二、排序算法选择、冒泡、插入排序归并排序随机快速排序堆排序基数排序计数排序 三、总结 一、稳定性 排序算法的稳定性是指&#xff1a;同样大小的样本 **&#xff08;同样大小的数据&#xff09;**在排序之后不会改变原始的相对次序。 稳定性对基础类型对象…...

GruntJS-前端自动化任务运行器从入门到实战

Grunt 完全指南&#xff1a;从入门到实战 一、Grunt 是什么&#xff1f; Grunt是一个基于 Node.js 的前端自动化任务运行器&#xff0c;主要用于自动化执行项目开发中重复性高的任务&#xff0c;例如文件压缩、代码编译、语法检查、单元测试、文件合并等。通过配置简洁的任务…...

LangChain知识库管理后端接口:数据库操作详解—— 构建本地知识库系统的基础《二》

这段 Python 代码是一个完整的 知识库数据库操作模块&#xff0c;用于对本地知识库系统中的知识库进行增删改查&#xff08;CRUD&#xff09;操作。它基于 SQLAlchemy ORM 框架 和一个自定义的装饰器 with_session 实现数据库会话管理。 &#x1f4d8; 一、整体功能概述 该模块…...

20个超级好用的 CSS 动画库

分享 20 个最佳 CSS 动画库。 它们中的大多数将生成纯 CSS 代码&#xff0c;而不需要任何外部库。 1.Animate.css 一个开箱即用型的跨浏览器动画库&#xff0c;可供你在项目中使用。 2.Magic Animations CSS3 一组简单的动画&#xff0c;可以包含在你的网页或应用项目中。 3.An…...

【电力电子】基于STM32F103C8T6单片机双极性SPWM逆变(硬件篇)

本项目是基于 STM32F103C8T6 微控制器的 SPWM(正弦脉宽调制)电源模块,能够生成可调频率和幅值的正弦波交流电源输出。该项目适用于逆变器、UPS电源、变频器等应用场景。 供电电源 输入电压采集 上图为本设计的电源电路,图中 D1 为二极管, 其目的是防止正负极电源反接, …...

动态 Web 开发技术入门篇

一、HTTP 协议核心 1.1 HTTP 基础 协议全称 &#xff1a;HyperText Transfer Protocol&#xff08;超文本传输协议&#xff09; 默认端口 &#xff1a;HTTP 使用 80 端口&#xff0c;HTTPS 使用 443 端口。 请求方法 &#xff1a; GET &#xff1a;用于获取资源&#xff0c;…...

Python Ovito统计金刚石结构数量

大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...

招商蛇口 | 执笔CID,启幕低密生活新境

作为中国城市生长的力量&#xff0c;招商蛇口以“美好生活承载者”为使命&#xff0c;深耕全球111座城市&#xff0c;以央企担当匠造时代理想人居。从深圳湾的开拓基因到西安高新CID的战略落子&#xff0c;招商蛇口始终与城市发展同频共振&#xff0c;以建筑诠释对土地与生活的…...

基于SpringBoot在线拍卖系统的设计和实现

摘 要 随着社会的发展&#xff0c;社会的各行各业都在利用信息化时代的优势。计算机的优势和普及使得各种信息系统的开发成为必需。 在线拍卖系统&#xff0c;主要的模块包括管理员&#xff1b;首页、个人中心、用户管理、商品类型管理、拍卖商品管理、历史竞拍管理、竞拍订单…...

【笔记】WSL 中 Rust 安装与测试完整记录

#工作记录 WSL 中 Rust 安装与测试完整记录 1. 运行环境 系统&#xff1a;Ubuntu 24.04 LTS (WSL2)架构&#xff1a;x86_64 (GNU/Linux)Rust 版本&#xff1a;rustc 1.87.0 (2025-05-09)Cargo 版本&#xff1a;cargo 1.87.0 (2025-05-06) 2. 安装 Rust 2.1 使用 Rust 官方安…...

JavaScript基础-API 和 Web API

在学习JavaScript的过程中&#xff0c;理解API&#xff08;应用程序接口&#xff09;和Web API的概念及其应用是非常重要的。这些工具极大地扩展了JavaScript的功能&#xff0c;使得开发者能够创建出功能丰富、交互性强的Web应用程序。本文将深入探讨JavaScript中的API与Web AP…...

Netty从入门到进阶(二)

二、Netty入门 1. 概述 1.1 Netty是什么 Netty is an asynchronous event-driven network application framework for rapid development of maintainable high performance protocol servers & clients. Netty是一个异步的、基于事件驱动的网络应用框架&#xff0c;用于…...

深入浅出深度学习基础:从感知机到全连接神经网络的核心原理与应用

文章目录 前言一、感知机 (Perceptron)1.1 基础介绍1.1.1 感知机是什么&#xff1f;1.1.2 感知机的工作原理 1.2 感知机的简单应用&#xff1a;基本逻辑门1.2.1 逻辑与 (Logic AND)1.2.2 逻辑或 (Logic OR)1.2.3 逻辑与非 (Logic NAND) 1.3 感知机的实现1.3.1 简单实现 (基于阈…...

SQL慢可能是触发了ring buffer

简介 最近在进行 postgresql 性能排查的时候,发现 PG 在某一个时间并行执行的 SQL 变得特别慢。最后通过监控监观察到并行发起得时间 buffers_alloc 就急速上升,且低水位伴随在整个慢 SQL,一直是 buferIO 的等待事件,此时也没有其他会话的争抢。SQL 虽然不是高效 SQL ,但…...

C#中的CLR属性、依赖属性与附加属性

CLR属性的主要特征 封装性&#xff1a; 隐藏字段的实现细节 提供对字段的受控访问 访问控制&#xff1a; 可单独设置get/set访问器的可见性 可创建只读或只写属性 计算属性&#xff1a; 可以在getter中执行计算逻辑 不需要直接对应一个字段 验证逻辑&#xff1a; 可以…...

使用LangGraph和LangSmith构建多智能体人工智能系统

现在&#xff0c;通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战&#xff0c;比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...

MySQL 知识小结(一)

一、my.cnf配置详解 我们知道安装MySQL有两种方式来安装咱们的MySQL数据库&#xff0c;分别是二进制安装编译数据库或者使用三方yum来进行安装,第三方yum的安装相对于二进制压缩包的安装更快捷&#xff0c;但是文件存放起来数据比较冗余&#xff0c;用二进制能够更好管理咱们M…...

无人机侦测与反制技术的进展与应用

国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机&#xff08;无人驾驶飞行器&#xff0c;UAV&#xff09;技术的快速发展&#xff0c;其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统&#xff0c;无人机的“黑飞”&…...

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要&#xff1a; 近期&#xff0c;在使用较新版本的OpenSSH客户端连接老旧SSH服务器时&#xff0c;会遇到 "no matching key exchange method found"​, "n…...

【无标题】路径问题的革命性重构:基于二维拓扑收缩色动力学模型的零点隧穿理论

路径问题的革命性重构&#xff1a;基于二维拓扑收缩色动力学模型的零点隧穿理论 一、传统路径模型的根本缺陷 在经典正方形路径问题中&#xff08;图1&#xff09;&#xff1a; mermaid graph LR A((A)) --- B((B)) B --- C((C)) C --- D((D)) D --- A A -.- C[无直接路径] B -…...

Go 并发编程基础:通道(Channel)的使用

在 Go 中&#xff0c;Channel 是 Goroutine 之间通信的核心机制。它提供了一个线程安全的通信方式&#xff0c;用于在多个 Goroutine 之间传递数据&#xff0c;从而实现高效的并发编程。 本章将介绍 Channel 的基本概念、用法、缓冲、关闭机制以及 select 的使用。 一、Channel…...

免费PDF转图片工具

免费PDF转图片工具 一款简单易用的PDF转图片工具&#xff0c;可以将PDF文件快速转换为高质量PNG图片。无需安装复杂的软件&#xff0c;也不需要在线上传文件&#xff0c;保护您的隐私。 工具截图 主要特点 &#x1f680; 快速转换&#xff1a;本地转换&#xff0c;无需等待上…...

Kafka入门-生产者

生产者 生产者发送流程&#xff1a; 延迟时间为0ms时&#xff0c;也就意味着每当有数据就会直接发送 异步发送API 异步发送和同步发送的不同在于&#xff1a;异步发送不需要等待结果&#xff0c;同步发送必须等待结果才能进行下一步发送。 普通异步发送 首先导入所需的k…...

深度学习水论文:mamba+图像增强

&#x1f9c0;当前视觉领域对高效长序列建模需求激增&#xff0c;对Mamba图像增强这方向的研究自然也逐渐火热。原因在于其高效长程建模&#xff0c;以及动态计算优势&#xff0c;在图像质量提升和细节恢复方面有难以替代的作用。 &#x1f9c0;因此短时间内&#xff0c;就有不…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机

这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机&#xff0c;因为在使用过程中发现 Airsim 对外部监控相机的描述模糊&#xff0c;而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置&#xff0c;最后在源码示例中找到了&#xff0c;所以感…...