This commit is contained in:
PhatenIoT-yan
2026-05-16 17:24:34 +08:00
parent fd63e5e4ec
commit 70e26b1827
18 changed files with 1880 additions and 2102 deletions

View File

@@ -277,6 +277,329 @@ keywords: A316固件开发, XU316通信问题, USB设备供电, 固件开发FAQ,
</div>
## 音频输出问题
### Q1: I2S/DSD 数据引脚连接后没有声音输出
<div class="grid" markdown>
=== "排查步骤"
1. **确认引脚定义**
- 不同模式USB-I2S、SPDIF-IN、ADAT等的 DATA0/1/2、BCLK、LRCLK 引脚位置可能不同
- 对照网站固件介绍确认引脚连接
2. **检查 I2S 格式**
- 确认是 I2S 格式、左对齐还是右对齐
- 与 DAC 芯片要求是否匹配
3. **确认 MCLK 连接**
- 某些 DAC 需要 MCLK 才能正常工作
- 检查是否已连接 MCLK 信号线
4. **测量信号波形**
- 用示波器检查 BCLK、LRCLK、DATA 线上是否有信号输出
</div>
### Q2: SPDIF 输入(光纤/同轴)没有声音或断断续续
<div class="grid" markdown>
=== "排查步骤"
1. **时钟限制**
- SPDIF-IN 模式只能使用内部时钟
- 不要发送 0x26 切换外部时钟命令
2. **检查接收电路**
- 光纤接收头或同轴接收电路是否正常
- 信号质量是否良好
3. **确认模式匹配**
- 发送的 0x23 命令中的模式必须与固件支持的 SPDIF 模式一致
4. **检查信号质量**
- SPDIF 信号质量差会导致解码失败
- 尝试更换线材或检查接口接触
</div>
### Q3: 切换模式时有爆音POP Noise
<div class="grid" markdown>
=== "解决方案"
1. **使用 MUTE 引脚控制**
- 切换模式前将 MUTE 引脚拉低
- 切换完成并确认成功后再拉高
2. **配置上电静音时间**
- 通过 0x02 命令配置合适的静音时间0-65535ms
- 给 DAC 足够的稳定时间
3. **DAC 侧配合静音**
- MCU 同时控制 DAC 的静音引脚
- 实现双重静音保护
4. **检查电源时序**
- 确保 DAC 电源稳定后再取消静音
</div>
### Q4: 外部时钟MCLK如何正确接入和切换
<div class="grid" markdown>
=== "操作要点"
1. **确认时钟频率**
- 22.5792MHz 对应 44.1kHz 系列
- 24.576MHz 对应 48kHz 系列
2. **切换时机**
- 在音频流传输前完成时钟切换
- 使用 0x26 命令进行切换
3. **SPDIF-IN 限制**
- SPDIF 输入模式只能使用内部时钟
- 不能切换外部时钟
4. **时钟质量**
- 外部时钟的抖动Jitter会直接影响音质
- 需使用低抖动晶振
</div>
### Q5: 不同采样率切换时有卡顿或爆音
<div class="grid" markdown>
=== "解决方案"
1. **使用 ASRC 功能**
- 特定固件支持 ASRC异步采样率转换
- 可平滑切换不同采样率
2. **时钟锁定时间**
- 采样率切换后 PLL 需要锁定时间
- 期间 XU316 会自动静音,属正常现象
3. **DAC 复位**
- 某些 DAC 在采样率变化时需要复位
- 可在切换后重新初始化 DAC
4. **缓存设置**
- 适当增加音频缓冲可减少卡顿
- 但会增加延迟
</div>
### Q6: 音频输出有杂音、底噪,如何排查 EMC/EMI 问题
<div class="grid" markdown>
=== "排查要点"
1. **电源隔离**
- 数字电源和模拟电源分开
- 使用 LDO 给音频电路供电
2. **地线设计**
- 采用单点接地,避免地环路
- 数字地和模拟地在一点连接
3. **I2S 走线**
- I2S 信号线等长走线
- 远离高速数字信号USB、SPI
- 必要时包地处理
4. **屏蔽处理**
- 对敏感模拟信号进行屏蔽
- 光纤接收头做好屏蔽罩接地
5. **晶振布局**
- MCLK 晶振靠近 XU316 和 DAC 布局
- 减少时钟线长度
</div>
## 音频格式支持
### Q1: MQA 音频播放需要注意什么
<div class="grid" markdown>
=== "注意事项"
1. **选择正确固件**
- 需要 MQA 支持必须下载带 Q 的固件(如 XXX_Q.bin
- 不带 Q 的固件不支持 MQA 解码
2. **MQA 渲染器**
- XU316 作为 MQA Renderer
- 需配合 MQA Core Decoder如 Tidal 软件解码)使用
3. **软件支持**
- 播放端软件需支持 MQATidal、Audirvana 等)
4. **授权问题**
- MQA 固件涉及授权,请确保使用正版固件
- 未授权会自动重启
</div>
### Q2: DSD 音频播放没有声音或变成噪音
<div class="grid" markdown>
=== "排查步骤"
1. **确认固件支持**
- 查看固件名称是否带 DSD 标识
2. **DSD 格式设置**
- 确认是 Native DSD 还是 DoPDSD over PCM
- 两种格式数据传输方式不同
3. **I2S 数据线连接**
- DSD 通常使用 DATA0 或 DATA1 传输
- 与 PCM 模式可能使用不同引脚
4. **DAC 支持**
- 确认 DAC 芯片支持 DSD 解码
- 已正确配置为 DSD 模式
</div>
## 协议命令详解
### Q1: 0x22 报告音频流格式命令的数据如何解析和使用
<div class="grid" markdown>
=== "使用说明"
1. **触发时机**
- XU316 启动成功后 1 秒自动发送
- 切换输入/输出模式后 1 秒也会自动发送
2. **数据解析**
- 根据固件规格书解析采样率、位深、音频格式PCM/DSD/DoP
3. **显示用途**
- 用于显示屏显示当前音频格式,如 "PCM 96kHz/24bit" 或 "DSD64"
4. **配合命令**
- 获取音频格式后,可用 0x28 命令设置音频延迟时间
</div>
### Q2: 0x24 音量命令的数值范围及 DAC 映射
<div class="grid" markdown>
=== "使用说明"
1. **音量范围**
- 通常为 0-100 或 0-255
- 具体范围参考固件规格书
2. **对数映射**
- 人耳对音量感知是对数的
- 建议将线性值映射为对数曲线后控制 DAC
3. **左右声道处理**
- 注意处理左右声道音量是否一致
- 部分 DAC 需分别设置左右声道音量
4. **与 0x21 的区别**
- 0x21MCU → XU316 → PC发送方向
- 0x24PC → XU316 → MCU接收方向
</div>
### Q3: 0x29 USB 连接状态检测有什么用途
<div class="grid" markdown>
=== "用途说明"
- 用于在显示屏上显示 USB 是否连接
- 提升用户体验
</div>
### Q4: 录音功能Microphone如何配置和使用
<div class="grid" markdown>
=== "配置说明"
- 不是所有固件都支持录音功能
- 需查看固件说明确认是否支持
</div>
## 驱动问题
### Q1: 使用不同配置固件后,设备无法正确识别
<div class="grid" markdown>
=== "问题现象"
- 开发或调试中使用不同配置、不同声道的固件后
- 设备无法正确识别当前配置
=== "原因"
- 改了录音声道数后Windows 缓存与实际不一致
=== "解决方法"
1. 进入设备管理器
2. 删除音频设备下识别的音频设备,右键卸载
3. 同时删除驱动,然后重新安装驱动
4. 重新插上设备并成功识别
</div>
## 二次开发高频问题
以下内容整理自 XMOS 常见问题,从二次开发/硬件集成开发者视角出发。
### 接口与模式类
#### Q1: I²S 输入只能是 Slave、输出只能是 Master 吗?能不能反向?
<div class="grid" markdown>
=== "回答"
- **不能反向**
- 输入I²S Slave
- 输出I²S Master
- 模式 6 也是I²S(slave) in → I²S(master) out
- 二次开发时必须按此时钟关系设计,否则无音频
</div>
#### Q2: S/PDIF 1 和 2 两个输入怎么切换?
<div class="grid" markdown>
=== "回答"
- 由模式编号区分:
- 模式 3 = SPDIF1 输入
- 模式 4 = SPDIF2 输入
- 切换靠 UART 配置或上位机工具,不是自动识别
</div>
### 时钟与采样率转换
#### Q1: 支持 768kHz / DSD512macOS/Windows 能直接跑吗?
<div class="grid" markdown>
=== "回答"
- **Windows**:需官方 USB 驱动 + UAC2.0
- **macOS**:原生免驱 UAC2.0,可直接到 768kHz
- **DSD512**:需播放器支持 DoP 或原生 DSD
- 限制不在模块,而在系统与播放器
</div>
#### Q2: 多通道能输出到几通道?
<div class="grid" markdown>
=== "回答"
- 属于标准多通道 USB Audio 2.0 架构
- 实际为 28 通道区间(需看模组手册)
- 二次开发按 UAC2.0 通道映射即可
</div>
### 硬件集成
#### Q1: 模块尺寸 19.5×26×0.8mm,是贴片还是插针?
<div class="grid" markdown>
=== "回答"
- 属于超薄模组
- 板对板或焊盘式集成,不是插针模块
- 二次开发需做 PCB 封装匹配
</div>
#### Q2: 供电 3.03.6V,典型 3.3V,能不能 5V 直接供电?
<div class="grid" markdown>
=== "回答"
- **不能**
- 必须 3.3V,且要低噪声 LDO
- 否则影响 THD+N
</div>
## 咨询反馈
<details>
<summary>点击展开咨询反馈表单</summary>
@@ -306,4 +629,3 @@ keywords: A316固件开发, XU316通信问题, USB设备供电, 固件开发FAQ,
}]
}
</script>

View File

@@ -26,7 +26,7 @@ search:
## 一、协议基础规范 :material-connection:
### 1.1 底层通信协议
**基于UART (Universal Asynchronous Receiver/Transmitter) 协议**
| 参数 | 值 |
@@ -170,7 +170,7 @@ sequenceDiagram
**执行条件**: 启动选项包含0x01更新基础产品信息
**步骤**:
1. XU316发送0x01命令请求读取基础产品信息
2. MCU返回新基础产品信息给XU316
3. XU316更新并保存配置到内部存储
@@ -187,7 +187,7 @@ sequenceDiagram
=== "应用固件加载阶段"
**步骤**:
1. XU316发送0x03命令获取当前输入输出模式
2. MCU返回当前模式信息给XU316
3. XU316根据返回模式加载对应输入输出模式
@@ -225,7 +225,9 @@ sequenceDiagram
| 0x24 | xu316发送播放音量 | XU316→MCU |
| 0x25 | 发送录音音量 | XU316→MCU |
| 0x26 | 切换MCLK | MCU→XU316 |
| 0x29 | 报告USB连接状态 | XU316→MCU |
| 0x27 | 设置 unmute | MCU→XU316 |
| 0x28 | 发送音频格式的时间延迟 | MCU→XU316 |
| 0x29 | 报告USB连接状态 | XU316→MCU |
=== "HID-MCU互相透传命令(0xEE-0xEF)"
| 命令字 | 命令描述 | 发送方向 |
@@ -237,6 +239,7 @@ sequenceDiagram
| 命令字 | 命令描述 | 发送方向 |
|:--------:|:---------------------------------------------|:----------:|
| 0xF0 | DAC配置选择命令 | MCU→XU316 |
| 0xF1 | 获取固件版本命令 | MCU→XU316 |
!!! note "命令使用说明"
1. 所有命令必须遵循基本帧格式规范
@@ -307,6 +310,24 @@ sequenceDiagram
* 重启原因字段可用于MCU识别XU316重启的具体原因以便进行不同处理
* 当需要更新多项信息时MCU可将多个选项通过位操作组合在一起
=== "MCU返回示例"
**命令示例**
```
55 AA 03 00 01 03 06
```
**逐段解析**
| 字节段 | 长度 | 示例值 | 说明 |
|:-------|:-----|:-------|:-----|
| 帧头 | 2字节 | `55 AA` | 固定帧头,表示一帧协议数据开始 |
| 版本 | 1字节 | `03` | 表示这是 MCU 返回给 XU316 的数据 |
| 命令字 | 1字节 | `00` | 表示当前命令是“开始启动” |
| 数据长度 | 1字节 | `01` | 表示后面紧跟着 1 字节的数据区 |
| 启动选项 | 1字节 | `03` | 表示 `0x01` 和 `0x02` 同时生效,也就是既要更新产品基础信息,也要更新上电配置信息 |
| 校验和 | 1字节 | `06` | 从 `55` 开始到 `03` 结束,所有字节相加后对 256 取余的结果 |
#### 3.2.2 读取产品信息0x01
=== "命令格式"
@@ -348,6 +369,31 @@ sequenceDiagram
CRC: 4字节 (32位CRC校验)
```
=== "MCU返回示例"
**命令示例**
```
55 AA 03 01 3C 20 B1 00 17 20 B1 00 16 50 48 41 54 45 4E 00 00 00 00 00 00 00 00 00 00 58 55 33 31 36 20 44 41 43 00 00 00 00 00 00 00 53 4E 32 34 30 30 30 31 00 00 00 00 00 00 00 00 12 34 56 78 D9
```
**逐段解析**
| 字节段 | 长度 | 示例值 | 说明 |
|:-------|:-----|:-------|:-----|
| 帧头 | 2字节 | `55 AA` | 固定帧头,表示一帧协议数据开始 |
| 版本 | 1字节 | `03` | 表示这是 MCU 返回给 XU316 的数据 |
| 命令字 | 1字节 | `01` | 表示当前命令是“读取产品信息” |
| 数据长度 | 1字节 | `3C` | 表示后面紧跟着 60 字节的数据区 |
| VID1 | 2字节 | `20 B1` | UAC1.0 的 USB VID |
| PID1 | 2字节 | `00 17` | UAC1.0 的 USB PID |
| VID2 | 2字节 | `20 B1` | UAC2.0 的 USB VID |
| PID2 | 2字节 | `00 16` | UAC2.0 的 USB PID |
| ManufactureName | 16字节 | `50 48 41 54 45 4E 00 00 00 00 00 00 00 00 00 00` | ASCII 字符串 `PHATEN`,后面不足 16 字节的部分用 `00` 补齐 |
| ProductName | 16字节 | `58 55 33 31 36 20 44 41 43 00 00 00 00 00 00 00` | ASCII 字符串 `XU316 DAC`,后面用 `00` 补齐到 16 字节 |
| SerialNumber | 16字节 | `53 4E 32 34 30 30 30 31 00 00 00 00 00 00 00 00` | ASCII 字符串 `SN240001`,后面用 `00` 补齐到 16 字节 |
| CRC | 4字节 | `12 34 56 78` | 产品基础信息的 32 位 CRC 校验值,这里仅作为示例演示 |
| 校验和 | 1字节 | `D9` | 从 `55` 开始到 `78` 结束,所有字节相加后对 256 取余的结果 |
#### 3.2.3 读取上电配置信息0x02
=== "命令格式"
@@ -387,6 +433,29 @@ sequenceDiagram
CRC: 4字节 (32位CRC校验)
```
=== "MCU返回示例"
**命令示例**
```
55 AA 03 02 0E 01 00 00 00 00 01 2C 20 30 30 11 22 33 44 6A
```
**逐段解析**
| 字节段 | 长度 | 示例值 | 说明 |
|:-------|:-----|:-------|:-----|
| 帧头 | 2字节 | `55 AA` | 固定帧头,表示一帧协议数据开始 |
| 版本 | 1字节 | `03` | 表示这是 MCU 返回给 XU316 的数据 |
| 命令字 | 1字节 | `02` | 表示当前命令是“读取上电配置信息” |
| 数据长度 | 1字节 | `0E` | 表示后面紧跟着 14 字节的数据区 |
| 默认输入输出模式 | 5字节 | `01 00 00 00 00` | 示例模式数据,具体每个字节的含义由产品规格书定义 |
| 静音时间 | 2字节 | `01 2C` | 按大端模式表示 `300ms` |
| 麦克风默认音量 | 1字节 | `20` | 示例默认麦克风音量 |
| DAC左声道默认音量 | 1字节 | `30` | 示例默认左声道音量 |
| DAC右声道默认音量 | 1字节 | `30` | 示例默认右声道音量 |
| CRC | 4字节 | `11 22 33 44` | 上电配置的 32 位 CRC 校验值,这里仅作为示例演示 |
| 校验和 | 1字节 | `6A` | 从 `55` 开始到 `44` 结束,所有字节相加后对 256 取余的结果 |
#### 3.2.4 获取当前输入输出模式0x03
=== "命令格式"
@@ -415,6 +484,24 @@ sequenceDiagram
- XU316会根据返回的模式加载相应的应用固件
- 此命令用于设备启动过程中的模式匹配与确认
=== "MCU返回示例"
**命令示例**
```
55 AA 03 03 05 01 00 00 00 00 0B
```
**逐段解析**
| 字节段 | 长度 | 示例值 | 说明 |
|:-------|:-----|:-------|:-----|
| 帧头 | 2字节 | `55 AA` | 固定帧头,表示一帧协议数据开始 |
| 版本 | 1字节 | `03` | 表示这是 MCU 返回给 XU316 的数据 |
| 命令字 | 1字节 | `03` | 表示当前命令是“获取当前输入输出模式” |
| 数据长度 | 1字节 | `05` | 表示后面紧跟着 5 字节的模式数据 |
| 输入输出模式 | 5字节 | `01 00 00 00 00` | 示例模式数据,具体每个字节的定义由产品规格书决定 |
| 校验和 | 1字节 | `0B` | 从 `55` 开始到最后一个模式字节结束,所有字节相加后对 256 取余的结果 |
#### 3.2.5 获取当前用户配置0x04
=== "命令格式"
@@ -443,6 +530,29 @@ sequenceDiagram
- 在应用固件加载后、应用启动前执行
- 应用会根据返回的信息初始化相应参数
=== "MCU返回示例"
**命令示例**
```
55 AA 03 04 0E 02 00 00 00 00 00 C8 18 28 28 55 66 77 88 00
```
**逐段解析**
| 字节段 | 长度 | 示例值 | 说明 |
|:-------|:-----|:-------|:-----|
| 帧头 | 2字节 | `55 AA` | 固定帧头,表示一帧协议数据开始 |
| 版本 | 1字节 | `03` | 表示这是 MCU 返回给 XU316 的数据 |
| 命令字 | 1字节 | `04` | 表示当前命令是“获取当前用户配置” |
| 数据长度 | 1字节 | `0E` | 表示后面紧跟着 14 字节的数据区 |
| 输入输出模式 | 5字节 | `02 00 00 00 00` | 示例用户当前选择的模式数据,具体每个字节的定义由产品规格书决定 |
| 静音时间 | 2字节 | `00 C8` | 按大端模式表示 `200ms` |
| 麦克风音量 | 1字节 | `18` | 示例当前麦克风音量 |
| DAC左声道音量 | 1字节 | `28` | 示例当前左声道音量 |
| DAC右声道音量 | 1字节 | `28` | 示例当前右声道音量 |
| CRC | 4字节 | `55 66 77 88` | 用户配置的 32 位 CRC 校验值,这里仅作为示例演示 |
| 校验和 | 1字节 | `00` | 从 `55` 开始到 `88` 结束,所有字节相加后对 256 取余的结果 |
#### 3.2.6 启动完成命令0x05
=== "命令格式"
@@ -473,6 +583,23 @@ sequenceDiagram
- 包含启动状态信息告知MCU启动是否成功或遇到问题
- 所有后续业务命令只能在此命令发送成功后使用
=== "MCU返回示例"
**命令示例**
```
55 AA 03 05 00 07
```
**逐段解析**
| 字节段 | 长度 | 示例值 | 说明 |
|:-------|:-----|:-------|:-----|
| 帧头 | 2字节 | `55 AA` | 固定帧头,表示一帧协议数据开始 |
| 版本 | 1字节 | `03` | 表示这是 MCU 返回给 XU316 的确认数据 |
| 命令字 | 1字节 | `05` | 表示当前确认的是“启动完成命令” |
| 数据长度 | 1字节 | `00` | 表示这是一条纯确认帧,不携带额外数据 |
| 校验和 | 1字节 | `07` | 从 `55` 开始到 `00` 结束,所有字节相加后对 256 取余的结果 |
### 3.3 业务控制命令详解
!!! warning "使用前提"
@@ -506,6 +633,23 @@ sequenceDiagram
- 通常在状态发生变化时发送,例如音量变化、模式切换等
- MCU可根据此信息更新UI显示或调整相关功能
=== "MCU返回示例"
**命令示例**
```
55 AA 03 20 00 22
```
**逐段解析**
| 字节段 | 长度 | 示例值 | 说明 |
|:-------|:-----|:-------|:-----|
| 帧头 | 2字节 | `55 AA` | 固定帧头,表示一帧协议数据开始 |
| 版本 | 1字节 | `03` | 表示这是 MCU 返回给 XU316 的确认数据 |
| 命令字 | 1字节 | `20` | 表示当前确认的是“报告应用状态”命令 |
| 数据长度 | 1字节 | `00` | 表示这是一条纯确认帧,不携带额外数据 |
| 校验和 | 1字节 | `22` | 从 `55` 开始到 `00` 结束,所有字节相加后对 256 取余的结果 |
#### 3.3.2 媒体控制0x21
=== "命令格式"
@@ -554,6 +698,23 @@ sequenceDiagram
| 0x06 | 快退 | 在当前曲目中快退 |
| 0x07 | 静音 | 切换系统静音状态 |
=== "MCU发送示例"
```
55 AA 03 21 01 02 26
```
**逐段解析**
| 字节段 | 长度 | 示例值 | 说明 |
|:-------|:-----|:-------|:-----|
| 帧头 | 2字节 | `55 AA` | 固定帧头,表示一帧协议数据开始 |
| 版本 | 1字节 | `03` | 表示这是 MCU 发送给 XU316 的命令 |
| 命令字 | 1字节 | `21` | 表示当前命令是“媒体控制” |
| 数据长度 | 1字节 | `01` | 表示后面紧跟着 1 字节的控制码 |
| 控制码 | 1字节 | `02` | 表示“播放/暂停”命令 |
| 校验和 | 1字节 | `26` | 从 `55` 开始到控制码结束,所有字节相加后对 256 取余的结果 |
#### 3.3.3 报告播放音频流格式和类型0x22
=== "命令格式"
@@ -582,6 +743,23 @@ sequenceDiagram
- 通常在播放开始或格式变化时发送
- MCU可根据此信息更新显示如显示PCM/DSD/MQA/DOP等状态
=== "MCU返回示例"
**命令示例**
```
55 AA 03 22 00 24
```
**逐段解析**
| 字节段 | 长度 | 示例值 | 说明 |
|:-------|:-----|:-------|:-----|
| 帧头 | 2字节 | `55 AA` | 固定帧头,表示一帧协议数据开始 |
| 版本 | 1字节 | `03` | 表示这是 MCU 返回给 XU316 的确认数据 |
| 命令字 | 1字节 | `22` | 表示当前确认的是“报告播放音频流格式和类型”命令 |
| 数据长度 | 1字节 | `00` | 表示这是一条纯确认帧,不携带额外数据 |
| 校验和 | 1字节 | `24` | 从 `55` 开始到 `00` 结束,所有字节相加后对 256 取余的结果 |
#### 3.3.4 设置输入输出模式0x23
=== "命令格式"
@@ -610,13 +788,30 @@ sequenceDiagram
- 通常由用户操作触发,如按下模式选择按钮
- XU316可能需要重启以加载新模式的固件
=== "MCU发送示例"
```
55 AA 03 23 05 02 00 00 00 00 2C
```
**逐段解析**
| 字节段 | 长度 | 示例值 | 说明 |
|:-------|:-----|:-------|:-----|
| 帧头 | 2字节 | `55 AA` | 固定帧头,表示一帧协议数据开始 |
| 版本 | 1字节 | `03` | 表示这是 MCU 发送给 XU316 的命令 |
| 命令字 | 1字节 | `23` | 表示当前命令是“设置输入输出模式” |
| 数据长度 | 1字节 | `05` | 表示后面紧跟着 5 字节的模式数据 |
| 输入输出模式 | 5字节 | `02 00 00 00 00` | 示例目标模式数据,具体每个字节的定义由产品规格书决定 |
| 校验和 | 1字节 | `2C` | 从 `55` 开始到最后一个模式字节结束,所有字节相加后对 256 取余的结果 |
#### 3.3.5 发送播放音量0x24
=== "命令格式"
**XU316返回**
**XU316发送**
```
帧头: 2字节 - 0x55aa
版本: 1字节 - 0x03
版本: 1字节 - 0x00
命令字: 1字节 - 0x24
数据长度: 1字节 - 0x02 (即2字节)
数据: 2字节
@@ -625,10 +820,10 @@ sequenceDiagram
校验和: 1字节 - 从帧头开始按字节求和结果对256求余
```
**MCU发送**
**MCU返回**
```
帧头: 2字节 - 0x55aa
版本: 1字节 - 0x00
版本: 1字节 - 0x03
命令字: 1字节 - 0x24
数据长度: 1字节 - 0x00
数据: 0字节
@@ -638,24 +833,41 @@ sequenceDiagram
=== "功能说明"
- 该命令用于XU316向MCU报告当前播放音量
=== "MCU返回示例"
**命令示例**
```
55 AA 03 24 00 26
```
**逐段解析**
| 字节段 | 长度 | 示例值 | 说明 |
|:-------|:-----|:-------|:-----|
| 帧头 | 2字节 | `55 AA` | 固定帧头,表示一帧协议数据开始 |
| 版本 | 1字节 | `03` | 表示这是 MCU 返回给 XU316 的确认数据 |
| 命令字 | 1字节 | `24` | 表示当前确认的是“发送播放音量”命令 |
| 数据长度 | 1字节 | `00` | 表示这是一条纯确认帧,不携带额外数据 |
| 校验和 | 1字节 | `26` | 从 `55` 开始到 `00` 结束,所有字节相加后对 256 取余的结果 |
#### 3.3.6 发送录音音量0x25
=== "命令格式"
**MCU发送**
**XU316发送**
```
帧头: 2字节 - 0x55aa
版本: 1字节 - 0x03
版本: 1字节 - 0x00
命令字: 1字节 - 0x25
数据长度: 1字节 - 0x01 (即1字节)
数据: 1字节 - 0xFF Mute0-0dB -127-127dB
校验和: 1字节 - 从帧头开始按字节求和结果对256求余
```
**XU316返回**
**MCU返回**
```
帧头: 2字节 - 0x55aa
版本: 1字节 - 0x00
版本: 1字节 - 0x03
命令字: 1字节 - 0x25
数据长度: 1字节 - 0x00
数据: 0字节
@@ -666,6 +878,23 @@ sequenceDiagram
- 该命令用于XU316向MCU报告当前麦克风录音音量
- 是预留命令,当前未使用
=== "MCU返回示例"
**命令示例**
```
55 AA 03 25 00 27
```
**逐段解析**
| 字节段 | 长度 | 示例值 | 说明 |
|:-------|:-----|:-------|:-----|
| 帧头 | 2字节 | `55 AA` | 固定帧头,表示一帧协议数据开始 |
| 版本 | 1字节 | `03` | 表示这是 MCU 返回给 XU316 的确认数据 |
| 命令字 | 1字节 | `25` | 表示当前确认的是“发送录音音量”命令 |
| 数据长度 | 1字节 | `00` | 表示这是一条纯确认帧,不携带额外数据 |
| 校验和 | 1字节 | `27` | 从 `55` 开始到 `00` 结束,所有字节相加后对 256 取余的结果 |
#### 3.3.7 切换MCLK0x26
=== "命令格式"
@@ -694,6 +923,23 @@ sequenceDiagram
- 可切换使用内部时钟或外部时钟
- 对于某些需要精确同步的音频应用场景很重要
=== "MCU发送示例"
```
55 AA 03 26 01 01 2A
```
**逐段解析**
| 字节段 | 长度 | 示例值 | 说明 |
|:-------|:-----|:-------|:-----|
| 帧头 | 2字节 | `55 AA` | 固定帧头,表示一帧协议数据开始 |
| 版本 | 1字节 | `03` | 表示这是 MCU 发送给 XU316 的命令 |
| 命令字 | 1字节 | `26` | 表示当前命令是“切换MCLK” |
| 数据长度 | 1字节 | `01` | 表示后面紧跟着 1 字节的数据区 |
| 数据 | 1字节 | `01` | 表示切换到外部 MCLK如果是 `00`,则表示切换到内部 MCLK |
| 校验和 | 1字节 | `2A` | 从 `55` 开始到最后一个数据字节结束,所有字节相加后对 256 取余的结果 |
#### 3.3.8 设置 unmute0x27
=== "命令格式"
@@ -776,6 +1022,23 @@ sequenceDiagram
- 当USB连接状态发生变化时连接或断开XU316主动发送此命令
- MCU可根据此信息更新UI显示或调整相关功能
=== "MCU返回示例"
**命令示例**
```
55 AA 03 29 00 2B
```
**逐段解析**
| 字节段 | 长度 | 示例值 | 说明 |
|:-------|:-----|:-------|:-----|
| 帧头 | 2字节 | `55 AA` | 固定帧头,表示一帧协议数据开始 |
| 版本 | 1字节 | `03` | 表示这是 MCU 返回给 XU316 的确认数据 |
| 命令字 | 1字节 | `29` | 表示当前确认的是“报告USB连接状态”命令 |
| 数据长度 | 1字节 | `00` | 表示这是一条纯确认帧,不携带额外数据 |
| 校验和 | 1字节 | `2B` | 从 `55` 开始到 `00` 结束,所有字节相加后对 256 取余的结果 |
#### 3.3.11 获取固件版本命令0xF1
=== "命令格式"
@@ -802,6 +1065,23 @@ sequenceDiagram
=== "功能说明"
- 获取固件版本
=== "MCU发送示例"
```
55 AA 03 F1 02 00 00 F5
```
**逐段解析**
| 字节段 | 长度 | 示例值 | 说明 |
|:-------|:-----|:-------|:-----|
| 帧头 | 2字节 | `55 AA` | 固定帧头,表示一帧协议数据开始 |
| 版本 | 1字节 | `03` | 表示这是 MCU 发送给 XU316 的命令 |
| 命令字 | 1字节 | `F1` | 表示当前命令是“获取固件版本命令” |
| 数据长度 | 1字节 | `02` | 表示后面紧跟着 2 字节的数据区 |
| 数据 | 2字节 | `00 00` | 示例中的两个字节保留为 `00`,用于占位 |
| 校验和 | 1字节 | `F5` | 从 `55` 开始到最后一个数据字节结束,所有字节相加后对 256 取余的结果 |
### 3.4 DAC配置选择0xF0
@@ -818,7 +1098,7 @@ sequenceDiagram
Byte 1 - 3: reserved
校验和: 1字节 - 从帧头开始按字节求和结果对256求余
```
**XU316返回**
```
帧头: 2字节 - 0x55aa
@@ -833,6 +1113,24 @@ sequenceDiagram
- 测试命令用于MCU想XU316设置DAC配置选择。让XU316通过DAC I2C配置DAC还是MCU自己配置DAC
- 此命令为产品特定命令,不是所有产品都支持。具体支持情况请参考产品规格书说明。
=== "MCU发送示例"
```
55 AA 03 F0 04 00 00 00 00 F6
```
**逐段解析**
| 字节段 | 长度 | 示例值 | 说明 |
|:-------|:-----|:-------|:-----|
| 帧头 | 2字节 | `55 AA` | 固定帧头,表示一帧协议数据开始 |
| 版本 | 1字节 | `03` | 表示这是 MCU 发送给 XU316 的命令 |
| 命令字 | 1字节 | `F0` | 表示当前命令是“DAC配置选择命令” |
| 数据长度 | 1字节 | `04` | 表示后面紧跟着 4 字节的数据区 |
| Byte 0 | 1字节 | `00` | 表示使能 XU316 通过 I2C 配置 DAC |
| Byte 1-3 | 3字节 | `00 00 00` | 预留字节,示例中全部填 `00` |
| 校验和 | 1字节 | `F6` | 从 `55` 开始到最后一个数据字节结束,所有字节相加后对 256 取余的结果 |
### 3.5 HID和MCU通过XU316数据透传命令
#### 3.5.1 HID通过XU316透传数据给MCU(0xEE)
@@ -848,7 +1146,7 @@ sequenceDiagram
数据: 57字节 - 由于HID协议限制必须是57字节透传数据
校验和: 1字节 - 从帧头开始按字节求和结果对256求余
```
**MCU返回(可以返回多帧)**
```
帧头: 2字节 - 0x55aa
@@ -946,7 +1244,7 @@ sequenceDiagram
|-------|----------------------------------------|
| 0xFF | 静音(Mute) |
| 0x00-0xFE | 音量值,具体映射由应用定义 |
**DAC音量**
| 值 | 说明 |

View File

@@ -0,0 +1,492 @@
---
title: XU316 MCU开发示例
description: XU316与MCU之间的通信协议详细说明包括数据结构、命令格式和处理流程
keywords: XU316, MCU, 通信协议, 命令参考
---
# XU316 MCU开发示例
--8<-- "common/phaten_xmos_support_img.md"
本示例基于 GD32 平台,其他平台请自行适配。
## 最小使用示例
这段代码展示了如何初始化协议层并在主循环中处理数据。用户需要实现自己的 UART 发送函数,并在串口接收中断中调用 `ring_buffer_write` 将数据写入环形缓冲区。
```c
#include "xu316_protocol.h"
// 发送回调将数据通过UART发送给XU316
// 用户需要根据自己的硬件实现uart_send函数
void my_send(const uint8_t *data, uint16_t len) {
uart_send(data, len);
}
// 日志回调:输出调试信息(可选)
void my_log(const char *tag, const char *msg) {
printf("[%s] %s\n", tag, msg);
}
// 初始化
void init(void) {
xu316_port_t port = {
.send = my_send,
.log = my_log
};
xu316_register_port(&port);
xu316_init();
}
// 串口接收中断中调用,将接收到的数据写入环形缓冲区
void uart_rx_isr(uint8_t *data, uint16_t len) {
ring_buffer_write(data, len);
}
// 主循环中周期性调用,处理接收到的命令
void main_loop(void) {
uart_data_process();
}
```
## 协议层函数
### 校验和计算
计算从帧头到数据区所有字节的累加和,结果对 256 取余。该校验和用于验证数据帧的完整性。
```c
uint8_t xu316_calc_checksum(uint8_t *data, uint8_t len) {
uint8_t sum = 0;
for (uint8_t i = 0; i < len; i++) {
sum += data[i];
}
return sum;
}
```
### 帧封装函数
将命令字和数据封装成符合协议格式的数据帧,并通过注册的 `send` 回调发送出去。
帧格式:`帧头(0x55AA) + 版本(0x03) + 命令字 + 数据长度 + 数据区 + 校验和`
```c
int xu316_pack_frame(uint8_t cmd, uint8_t *data, uint8_t len) {
memset(g_tx_buffer, 0, sizeof(g_tx_buffer));
g_tx_buffer[0] = FRAME_HEADER_H; // 0x55
g_tx_buffer[1] = FRAME_HEADER_L; // 0xAA
g_tx_buffer[2] = PROTOCOL_VERSION_RX; // 0x03 (MCU版本)
g_tx_buffer[3] = cmd; // 命令字
g_tx_buffer[4] = len; // 数据长度
if (data && len > 0) {
memcpy(g_tx_buffer + 5, data, len);
}
// 计算校验和(帧头+版本+命令字+数据长度+数据区)
g_tx_buffer[len + 5] = xu316_calc_checksum(g_tx_buffer, len + 5);
// 通过注册的回调发送
if (g_xu316_port.send) {
g_xu316_port.send(g_tx_buffer, len + 6);
}
return len + 6;
}
```
### 数据帧提取
从环形缓冲区中预读数据,检查帧头是否有效。如果帧头有效,返回完整帧的长度;如果无效,返回 `-1` 表示需要丢弃字节。
```c
static int check_frame_length(uint8_t *buf, uint16_t len) {
// 检查帧头是否为0x55AA
if (buf[0] != FRAME_HEADER_H || buf[1] != FRAME_HEADER_L) {
return -1; // 帧头错误
}
// 返回完整帧长度 = 数据长度 + 6帧头2+版本1+命令1+长度1+校验1
return buf[4] + 6;
}
```
### 数据处理主函数
在主循环中周期性调用。从环形缓冲区中提取完整的数据帧,检查帧头有效性,确认数据长度足够后,将完整帧复制到接收缓冲区,然后调用 `uart_data_parse` 进行命令解析。如果帧头无效,会逐字节丢弃直到找到有效帧头。
```c
void uart_data_process(void) {
uint8_t peek_buffer[8]; // 预读缓冲区
uint8_t process_buffer[256]; // 帧数据缓冲区
int frame_length;
// 至少需要6字节才能开始检查帧头
while (uart_ring_buffer.count >= 6) {
// 预读6字节检查帧头
ring_buffer_peek(peek_buffer, 6);
// 检查帧长度
frame_length = check_frame_length(peek_buffer, 6);
if (frame_length < 0) {
// 帧头无效丢弃1字节继续查找
uint8_t dummy;
ring_buffer_read(&dummy, 1);
continue;
}
// 检查环形缓冲区中是否有足够的数据组成完整帧
if (uart_ring_buffer.count < (uint16_t)frame_length) {
break; // 数据不足,等待更多数据
}
// 读取完整帧到处理缓冲区
if (ring_buffer_read(process_buffer, (uint16_t)frame_length)) {
// 将完整帧复制到全局接收缓冲区
memcpy(g_rx_buffer, process_buffer, frame_length);
g_rx_count = frame_length;
g_rx_data = g_rx_buffer;
// 调用解析函数处理命令
uart_data_parse();
}
}
}
```
## 命令解析
### 解析入口
协议处理的核心函数。对接收到的数据帧进行校验,提取命令字和数据区,然后根据命令字分发到对应的处理逻辑。
```c
int uart_data_parse(void) {
int ret = 0;
uint8_t cmd = 0;
uint16_t data_len = 0;
uint16_t rx_len = (uint16_t)g_rx_count;
static uint8_t buffer[256] = {0};
// 帧校验:检查帧格式和校验和
ret = uart_frame_check((uint8_t *)g_rx_data, (uint8_t)rx_len);
if (ret == 0) {
return -1; // 帧校验失败
}
// 计算数据区长度:总长度 - 6帧头2+版本1+命令1+长度1+校验1
data_len = rx_len - 6;
// 提取命令字第4个字节索引3
cmd = g_rx_data[3];
// 复制数据区到缓冲区从第6个字节开始索引5
memcpy(buffer, g_rx_data + 5, data_len);
// 根据命令字分发处理
switch (cmd) {
case 0x00: /* 启动命令处理 */ break;
case 0x01: /* 读取产品信息 */ break;
case 0x02: /* 读取上电配置 */ break;
case 0x03: /* 获取音频模式 */ break;
case 0x04: /* 获取用户配置 */ break;
case 0x05: /* 启动完成 */ break;
case 0x20: /* 状态报告 */ break;
case 0x22: /* 音频格式设置 */ break;
case 0x24: /* 播放音量 */ break;
case 0x25: /* 录音音量 */ break;
case 0x27: /* 静音解除响应 */ break;
case 0x28: /* 音频格式延迟响应 */ break;
case 0xEE: /* HID透传 */ break;
default: /* 未知命令处理 */ break;
}
return ret;
}
```
### 命令参考
#### 启动命令 (0x00)
XU316 上电或重启后首先发送此命令。XU316 发送 17 字节数据,包含 VID/PID 和 CRC 校验值。MCU 需要比较 CRC 判断是否需要更新配置,然后回复 1 字节的启动选项。
```c
case 0x00: {
// XU316发送数据格式
// 重启原因(1B) + VID1(2B) + PID1(2B) + VID2(2B) + PID2(2B) + CRC1(4B) + CRC2(4B) = 17字节
// MCU回复启动选项(1B)
// 解析XU316发送的数据
uint8_t reboot_reason = buffer[0]; // 0x00=上电重启, 0x01=切换模式, 0xFF=其他
uint8_t *vid_uac1 = buffer + 1; // UAC1.0 VID
uint8_t *pid_uac1 = buffer + 3; // UAC1.0 PID
uint8_t *vid_uac2 = buffer + 5; // UAC2.0 VID
uint8_t *pid_uac2 = buffer + 7; // UAC2.0 PID
uint8_t *basic_crc = buffer + 9; // 基础信息CRC
uint8_t *power_crc = buffer + 13; // 上电配置CRC
// 判断是否需要更新配置比较XU316发送的CRC与本地存储的CRC
mcu_data.boot_option = 0;
if (memcmp(basic_crc, mcu_data.basic_info_crc, 4) != 0) {
mcu_data.boot_option |= BOOT_OPTION_UPDATE_BASIC_INFO; // 需要更新基础信息
}
if (memcmp(power_crc, mcu_data.power_cfg_crc, 4) != 0) {
mcu_data.boot_option |= BOOT_OPTION_UPDATE_POWER_CFG; // 需要更新上电配置
}
// 发送回复:启动选项
ret = xu316_pack_frame(cmd, &mcu_data.boot_option, CMD00_MCU_DATA_LEN);
break;
}
```
#### 读取产品信息 (0x01)
XU316 请求获取产品基础信息。MCU 需要回复 60 字节数据,包含 VID、PID、制造商名称、产品名称、序列号和 CRC 校验值。
```c
case 0x01: {
// XU316发送无数据
// MCU回复60字节产品信息
// VID1(2B) + PID1(2B) + VID2(2B) + PID2(2B) +
// 制造商(16B) + 产品名(16B) + 序列号(16B) + CRC(4B)
// 重新计算基础信息的CRC32校验值前56字节
crc = calculate_crc32(mcu_data.vid_uac1, 56);
// 将CRC存储为大端序
mcu_data.basic_info_crc[0] = (uint8_t)((crc >> 24) & 0xFF);
mcu_data.basic_info_crc[1] = (uint8_t)((crc >> 16) & 0xFF);
mcu_data.basic_info_crc[2] = (uint8_t)((crc >> 8) & 0xFF);
mcu_data.basic_info_crc[3] = (uint8_t)(crc & 0xFF);
// 发送产品信息从vid_uac1开始的60字节
ret = xu316_pack_frame(cmd, mcu_data.vid_uac1, CMD01_MCU_DATA_LEN);
break;
}
```
#### 读取上电配置 (0x02)
XU316 请求获取上电配置参数。MCU 回复 14 字节数据,包含启动状态、音频模式、静音时间、音量设置和 CRC 校验值。
```c
case 0x02: {
// XU316发送无数据
// MCU回复14字节配置信息
// 启动状态(1B) + 音频模式(5B) + 静音时间(2B) +
// 麦克风音量(1B) + 左音量(1B) + 右音量(1B) + CRC(4B)
// 重新计算上电配置的CRC32校验值audio_mode开始的10字节
crc = calculate_crc32((uint8_t *)&mcu_data.audio_mode, 0x0a);
// 存储为大端序
mcu_data.power_cfg_crc[0] = (uint8_t)((crc >> 24) & 0xFF);
mcu_data.power_cfg_crc[1] = (uint8_t)((crc >> 16) & 0xFF);
mcu_data.power_cfg_crc[2] = (uint8_t)((crc >> 8) & 0xFF);
mcu_data.power_cfg_crc[3] = (uint8_t)(crc & 0xFF);
// 发送上电配置从audio_mode开始的14字节
ret = xu316_pack_frame(cmd, (uint8_t *)&mcu_data.audio_mode, CMD02_MCU_DATA_LEN);
break;
}
```
#### 获取音频模式 (0x03)
XU316 请求获取当前输入输出模式。MCU 回复 5 字节的音频模式配置。
```c
case 0x03: {
// XU316发送无数据
// MCU回复5字节音频模式
ret = xu316_pack_frame(cmd, (uint8_t *)&mcu_data.audio_mode, CMD03_MCU_DATA_LEN);
break;
}
```
#### 获取用户配置 (0x04)
XU316 请求获取用户配置参数。MCU 回复 14 字节,格式与 0x02 命令相同。会设置当前选中的音频模式并重新计算 CRC。
```c
case 0x04: {
// XU316发送无数据
// MCU回复14字节用户配置格式同0x02
// 设置当前选中的音频模式
memcpy((uint8_t *)&mcu_data.audio_mode, audio_modes[g_current_mode], 5);
// 计算CRC
crc = calculate_crc32((uint8_t *)&mcu_data.audio_mode, 10);
mcu_data.power_cfg_crc[0] = (uint8_t)((crc >> 24) & 0xFF);
mcu_data.power_cfg_crc[1] = (uint8_t)((crc >> 16) & 0xFF);
mcu_data.power_cfg_crc[2] = (uint8_t)((crc >> 8) & 0xFF);
mcu_data.power_cfg_crc[3] = (uint8_t)(crc & 0xFF);
ret = xu316_pack_frame(cmd, (uint8_t *)&mcu_data.audio_mode, CMD04_MCU_DATA_LEN);
break;
}
```
#### 启动完成 (0x05)
XU316 通知 MCU 启动完成并发送当前状态数据。MCU 只需回复确认(无数据)。
```c
case 0x05: {
// XU316发送21字节状态数据
// MCU回复无数据
// 保存XU316发送的状态到mcu_data结构体
memcpy(&mcu_data.startup_status, buffer, 15);
// 回复确认
ret = xu316_pack_frame(cmd, NULL, CMD05_MCU_DATA_LEN);
break;
}
```
#### 状态报告 (0x20)
XU316 在状态变化时主动上报。MCU 保存状态数据并回复确认。
```c
case 0x20: {
// XU316发送20字节状态数据
// 音频模式(5B) + 静音时间(2B) + 麦克风音量(1B) + 左音量(1B) + 右音量(1B) + CRC(4B)
// MCU回复无数据
// 保存状态数据
memcpy(&mcu_data.audio_mode, buffer, 14);
// 回复确认
ret = xu316_pack_frame(cmd, NULL, CMD20_MCU_DATA_LEN);
break;
}
```
#### 音频格式设置 (0x22)
XU316 通知当前播放的音频格式和类型。MCU 保存这些信息并回复确认。
```c
case 0x22: {
// XU316发送2字节音频格式 + 音频类型)
// MCU回复无数据
// 保存音频格式和类型
memcpy(&mcu_data.audio_format, buffer, 2);
// 回复确认
ret = xu316_pack_frame(cmd, NULL, CMD22_MCU_DATA_LEN);
break;
}
```
#### 播放音量 (0x24)
XU316 发送当前播放音量。MCU 保存左右声道音量值并回复确认。
```c
case 0x24: {
// XU316发送2字节左音量 + 右音量)
// MCU回复无数据
// 保存音量值
memcpy(&mcu_data.dac_l_volume, buffer, 2);
// 回复确认
ret = xu316_pack_frame(cmd, NULL, CMD24_MCU_DATA_LEN);
break;
}
```
#### HID 透传 (0xEE)
HID 数据透传或 OTA 升级数据。XU316 发送 57 字节数据MCU 需要回复 57 字节Echo 模式)。
```c
case 0xEE: {
// XU316发送57字节HID/OTA数据
// MCU回复57字节Echo模式
// 检查版本号和数据长度
if (g_rx_data[2] == 0x00 && g_rx_data[4] == CMD_HID_TRANSPARENT_DATA_LEN) {
// 简单Echo回复将接收到的数据原样返回
ret = xu316_pack_frame(0xEE, buffer, CMD_HID_TRANSPARENT_MCU_DATA_LEN);
}
break;
}
```
## MCU 主动发送命令
以下命令由 MCU 主动发送给 XU316。
### 静音解除命令
命令字 `0x27`,数据为 2 字节 `0x00`
```c
void send_unmute_cmd(void) {
uint8_t data[2] = {0x00, 0x00};
xu316_pack_frame(0x27, data, 2);
}
```
### 音频格式延迟命令
命令字 `0x28`,数据为 2 字节 `0x00`
```c
void send_audio_format_delay_cmd(void) {
uint8_t data[2] = {0x00, 0x00};
xu316_pack_frame(0x28, data, 2);
}
```
### 媒体控制命令
命令字 `0x21`,数据为 1 字节的媒体控制码。
```c
void send_media_control(media_control_t cmd) {
uint8_t data = (uint8_t)cmd;
xu316_pack_frame(0x21, &data, 1);
}
// 使用示例
send_media_control(MEDIA_KEY_PLAY_PAUSE); // 播放/暂停
send_media_control(MEDIA_KEY_VOLUME_UP); // 音量增加
send_media_control(MEDIA_KEY_VOLUME_DOWN); // 音量减小
```
### 设置音频模式
命令字 `0x23`,数据为 5 字节音频模式配置。
```c
void set_audio_mode(uint8_t mode_index) {
// audio_modes是预定义的8种模式数组
xu316_pack_frame(0x23, (uint8_t *)audio_modes[mode_index], 5);
}
// 8种预定义音频模式
static const uint8_t audio_modes[][5] = {
{0x00, 0x80, 0xa9, 0x00, 0x01}, // UAC2.0->I2S
{0x00, 0x80, 0x01, 0x00, 0x02}, // UAC1.0-I2S
{0x10, 0x80, 0x65, 0x10, 0x03}, // S/PDIF1 IN-I2S OUT (COAX)
{0x00, 0x80, 0x65, 0x10, 0x04}, // S/PDIF2 IN-I2S OUT (OPT)
{0x00, 0x80, 0xc5, 0x08, 0x05}, // UAC2.0-SPDIF OUT
{0x00, 0x82, 0xd5, 0x81, 0x06}, // I2S IN-I2S OUT
{0x20, 0x80, 0x65, 0x10, 0x07}, // S/PDIF3 IN-I2S OUT (HDMI)
{0x30, 0x80, 0x65, 0x10, 0x08} // S/PDIF4 IN-I2S OUT
};
```
---
## 咨询反馈
<details>
<summary>点击展开咨询反馈表单</summary>
--8<-- "common/customer_form.md"
</details>

View File

@@ -1,7 +1,7 @@
---
title: A316免开发固件MCU开发指南
description: 本文档提供了XU316与MCU通信开发的完整指导包括开发步骤、参考文档和常见问题解答帮助开发者快速实现XU316与MCU的通信功能
keywords: XU316开发, MCU通信开发, 音频接口控制, 通信协议, 开发指导, 常见问题解答
description: XU316与MCU通信开发入门指导,帮助开发者按步骤理解协议、实现通信、运行示例代码
keywords: XU316开发, MCU通信开发, 通信协议, 开发指导, 代码示例
---
--8<-- "common/phaten_xmos_support_img.md"
@@ -10,58 +10,34 @@ keywords: XU316开发, MCU通信开发, 音频接口控制, 通信协议, 开发
## 开发概述
本文档提供了XU316与MCU通信开发的完整指导帮助开发者按正确顺序实现XU316与MCU的通信功能。开发过程分为以下几个主要步骤,每个步骤都有对应的参考文档和详细说明
本文档帮助开发者按正确顺序实现 XU316 与 MCU 的串口通信功能。开发过程分为以下步骤,每都有对应的参考文档。
## 开发步骤
<div class="grid" markdown>
=== "第一步:了解基础概念和协议结构"
**目标**理解XU316MCU通信的基本概念和协议结构
**参考文档**[:material-file-document-outline: XU316与MCU通信协议命令宏定义](./Command_Macros.md)
=== "第一步:了解协议结构"
**目标**:理解 XU316MCU 通信的帧格式与命令定义
**参考文档**[:material-file-document-outline: XU316与MCU通信协议](../../protocols/xu316_zerocode_protocol.md)
**学习要点**
- 掌握帧格式的基本结构(帧头、命令、数据长度、校验和、帧尾
- 理解各命令的数据长度定义
- 掌握帧格式(帧头 `0x55AA`、版本、命令、数据长度、校验和)
- 理解各命令的数据长度定义
- 熟悉音频格式枚举和类型定义
- 了解命令数据结构体的组成
=== "第二步:实现基础通信功能"
**目标**实现XU316与MCU的基础通信功能
**参考文档**[:material-file-document-outline: XU316与MCU通信协议参考](./Command_Reference.md)
**开发任务**
=== "第二步:运行示例代码"
**目标**基于 GD32 平台运行完整的协议通信示例
- 实现环形缓冲区初始化和管理
- 实现数据帧的封装和发送
- 实现数据帧的接收和解析
- 实现CRC32和简单校验和计算
- 实现基本的通信协议处理流程
**参考文档**[:material-file-document-outline: XU316 MCU开发示例](./Development_Guide.md)
=== "第三步:配置音频接口和参数"
**目标**配置XU316的音频接口和相关参数
**参考文档**[:material-file-document-outline: XU316音频接口控制代码示例](./Product_Content.md)
**开发任务**
- 配置I2S主从模式
- 设置音频采样率和位深度
- 配置音频通道数量
- 设置音量控制参数
- 配置各种音频接口SPDIF、ADAT、DSD等
**示例内容**
<!-- === "第四步:集成和测试"
**目标**:将各个模块集成并进行功能测试
**开发任务**
- 集成所有通信功能模块
- 实现完整的命令处理流程
- 进行功能测试和调试
- 优化性能和稳定性 -->
- 最小使用示例(初始化、中断接收、主循环处理)
- 协议层函数(校验和计算、帧封装、帧提取、数据处理)
- 全部命令的解析代码0x00 ~ 0xEE
- MCU 主动发送命令(静音解除、媒体控制、音频模式设置等)
</div>