1. DMA (Direct Memory Access) - 直接内存访问
是什么:
DMA是一种硬件机制 ,允许外部设备直接与系统内存交换数据 ,而无需CPU的持续干预。
核心原理与工作流程:
-
CPU初始化阶段:
-
CPU配置DMA控制器:设置源地址(从哪里读)、目的地址(往哪里写)、传输数据量(多少个字节/字)
-
设置传输模式(单次、块传输、循环等)
-
启动DMA传输
-
-
DMA自主传输阶段:
-
DMA控制器接管系统总线(通过总线仲裁器获得控制权)
-
直接在内存和外设寄存器之间搬运数据
-
CPU在此期间可以执行其他任务,实现真正的并行
-
-
传输完成阶段:
-
DMA控制器完成指定数据量传输后,向CPU发送中断信号
-
CPU在中断服务程序中处理后续工作(如准备下一个缓冲区)
-
关键特点与优势:
-
减少CPU开销:避免CPU陷入每个字节搬运的"搬运工"角色
-
提高系统效率:CPU与外设操作并行
-
保证实时性:适合数据流式传输(如音频、视频、网络)
-
降低功耗:CPU可以进入低功耗模式等待DMA完成
实际应用(以音频为例):
c
// 传统CPU搬运(低效)
while(audio_buffer_not_empty) {
byte = read_from_i2s_register(); // CPU读I2S
write_to_memory(byte); // CPU写内存
}
// DMA方式(高效)
setup_dma(source=I2S_DATA_REG, dest=audio_buffer, count=1024);
start_dma();
// 此时CPU可以处理音频解码、网络协议等其他任务
2. I2S (Inter-IC Sound) - 集成电路内置音频总线
是什么:
I2S是一种同步串行通信协议 ,专门设计用于在数字音频设备之间传输高质量音频数据。
标准I2S信号线(3线制):
| 信号 | 全称 | 作用 | 特点 |
|---|---|---|---|
| SCK | 串行时钟 | 位时钟,每个脉冲传输一位数据 | 频率 = 采样率 × 位深 × 声道数 |
| WS | 字选择 | 声道选择(左/右) | 频率 = 采样率,高电平=左声道,低电平=右声道 |
| SD | 串行数据 | 实际音频数据(补码格式) | MSB先行,在WS变化后1个SCK周期开始传输 |
时序图示例(16位,单声道/立体声):
text
WS: ┌─────左声道────┐ ┌─────右声道────┐
│ │ │ │
SCK: ▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁▁
│← 16个SCK →│ │← 16个SCK →│
SD: ▔▔▔MSB▔▔▔▔▔▔▔▔▔▔▔LSB▔▔▔▔▔▔MSB▔▔▔▔▔▔LSB▔
3. Single-Channel I2S vs Multi-Channel I2S
Single-Channel I2S(标准立体声)
-
通道数:2个(左 + 右)
-
帧结构:一个WS周期内包含2个时隙(Time Slot)
-
WS=1:传输左声道数据(16/24/32位)
-
WS=0:传输右声道数据(16/24/32位)
-
-
应用场景:立体声音频、耳机输出、普通扬声器
-
数据率计算:
text
数据率 = 采样率 × 位深 × 声道数 例:44.1kHz × 16位 × 2 = 1.4112 Mbps
Multi-Channel I2S(多通道/TDM模式)
-
通道数:2个以上(通常4、6、8通道)
-
帧结构:一个WS周期内包含多个时隙
-
通过TDM(时分复用) 将多个声道数据打包在一帧内
-
WS信号通常作为帧同步(Frame Sync)
-
-
常见格式:
-
I2S TDM:扩展的标准I2S格式
-
PCM/TDM:更通用的多通道格式
-
左对齐/右对齐:数据在时隙中的对齐方式
-
8通道TDM示例(32位/通道):
text
WS (Frame Sync): ┌───────────────────── 1帧 ─────────────────────┐
│ │
时隙分配: 槽0 槽1 槽2 槽3 槽4 槽5 槽6 槽7
│左前 │右前 │中置 │低音炮│左后 │右后 │左环绕│右环绕│
│32位 │32位 │32位 │32位 │32位 │32位 │32位 │32位 │
SCK计数: 0-31 32-63 64-95 96-127 128-159 ... 总共256个SCK
-
总位宽 = 32位 × 8通道 = 256位/帧
-
SCK频率 = 采样率 × 256(比立体声高4倍)
4. 三者协同工作:音频系统的完整示例
场景:多声道家庭影院音频系统
-
需求:8通道(7.1环绕声)音频播放,48kHz采样率,24位精度
-
系统组成:
-
主处理器:运行音频解码软件
-
DMA控制器:负责音频数据搬运
-
I2S外设:配置为多通道TDM模式
-
音频编解码器:接收I2S数据并转换为模拟信号
-
工作流程:
c
// 1. 内存中准备音频数据(8通道交错存储)
int32_t audio_buffer[BUFFER_SIZE][8]; // [样本索引][通道]
// 2. 配置DMA(关键!)
dma_config_t config = {
.src_addr = audio_buffer,
.dst_addr = &I2S_DATA_REG,
.transfer_size = BUFFER_SIZE * 8 * 4, // 样本数×通道数×4字节
.mode = CIRCULAR, // 循环模式,持续播放
.src_inc = TRUE, // 源地址递增
.dst_inc = FALSE, // 目的地址固定(I2S寄存器)
.transfer_width = 32 // 32位传输
};
// 3. 配置I2S为多通道TDM模式
i2s_config_t i2s_cfg = {
.mode = MASTER_TX,
.standard = I2S_TDM,
.data_format = 24_BIT_LEFT_ALIGNED, // 24位数据,左对齐在32位时隙中
.channel_num = 8, // 8通道
.slot_num = 8, // 8个时隙
.sample_rate = 48000,
.mclk_multiple = 256 // MCLK = 256 × 采样率
};
// 4. 启动系统
setup_i2s(&i2s_cfg);
setup_dma(&config);
start_dma();
// 5. CPU仅需在DMA半/全传输完成中断中填充新数据
void dma_half_complete_isr() {
// 填充audio_buffer的前半部分
decode_audio(audio_buffer[0], BUFFER_SIZE/2);
}
void dma_complete_isr() {
// 填充audio_buffer的后半部分
decode_audio(audio_buffer[BUFFER_SIZE/2], BUFFER_SIZE/2);
}
DMA与I2S的触发关系:
text
时序图:
CPU: 初始化[====空闲/解码====]中断处理[====空闲====]中断处理...
│ │ │
DMA: └─开始─[===传输前半缓冲===]─中断─[===传输后半缓冲===]─中断─...
│ │ │
I2S: 发送[帧0,帧1...] 发送[帧N/2...] 发送[帧N...]
每个I2S数据请求触发一次DMA传输
5. 性能对比与设计考量
| 方面 | Single-Channel I2S | Multi-Channel I2S |
|---|---|---|
| 接口复杂度 | 简单(3线) | 相同引脚数,但时序更复杂 |
| 数据率 | 较低 | 较高(通道数倍增加) |
| DMA需求 | 可选,但对实时音频很重要 | 必需(数据量太大,CPU无法承受) |
| 应用场景 | 消费电子、耳机 | 专业音频、家庭影院、汽车音响 |
| 功耗 | 较低 | 较高(更高时钟频率) |
关键设计要点:
-
DMA缓冲区管理:
-
双缓冲/环形缓冲:确保音频连续不中断
-
缓冲区大小:权衡延迟与中断频率
-
内存对齐:优化DMA访问效率
-
-
时钟同步:
-
主/从模式:决定谁提供SCK和WS
-
时钟精度:影响音频质量(特别是多设备同步)
-
-
数据格式对齐:
-
24位音频常放在32位时隙中(左对齐或右对齐)
-
DMA需要匹配I2S数据宽度
-
总结
-
DMA是高效数据搬运的"搬运工",解放CPU
-
I2S是音频数据的"传输协议",定义格式和时序
-
Single-Channel I2S适合普通立体声应用
-
Multi-Channel I2S通过TDM技术扩展通道数,适合专业音频
在现代音频系统中,这三者紧密结合:Multi-Channel I2S提供高通道数的物理接口,DMA负责高效搬运大量音频数据,CPU专注于高层音频处理和解码,共同实现高质量、实时的音频体验。
这种架构不仅用于音频,类似的设计思想也广泛应用于其他数据流处理场景,如视频流、网络数据包、传感器数据采集等。