第三十五章 I2S——音频传输接口
目录
I2S(Inter-Integrated Circuit Sound)是W55MH32中用于数字音频传输的重要接口,广泛应用于各种音频设备与嵌入式系统。本文将从工作原理、注意事项、应用场景以及程序设计来讲解I2S接口,和大家一起学习和使用这一技术。
1 I2S概述
1.1 简介
I2S(Inter-Integrated Circuit Sound)是飞利浦公司为数字音频设备之间的音频数据传输而制定的一种总线标准,专门用于音频设备之间的高质量数字音频传输。在W55MH32中,I2S功能与SPI模块共享相同的硬件资源,通过将寄存器SPI_I2SCFGR的I2SMOD位置为'1'即可使能I2S功能,将SPI模块转换为I2S音频接口。
I2S接口与SPI接口使用大致相同的引脚、标志和中断,但专为音频数据传输优化。它采用独立的导线传输时钟与数据信号,通过将数据和时钟信号分离,避免了因时差诱发的失真,为用户节省了购买抵抗音频抖动的专业设备的费用。I2S已成为数字音频领域的事实标准接口,广泛应用于各种消费电子和专业音频设备中。
1.2 功能特点
W55MH32的I2S接口有以下特点:
- 单工通信(仅发送或接收)
- 主或者从操作
- 8位线性可编程预分频器,获得精确的音频采样频率(8KHz到96kHz)
- 数据格式可以是16位,24位或者32位
- 音频信道固定数据包帧为16位(16位数据帧)或32位(16、24或32位数据帧)
- 可编程的时钟极性(稳定态)
- 从发送模式下的下溢标志位和主/从接收模式下的溢出标志位
- 16位数据寄存器用来发送和接收,在通道两端各有一个寄存器
- 支持的I2S协议:
- I2S飞利浦标准
- MSB对齐标准(左对齐)
- LSB对齐标准(右对齐)
- PCM标准(16位通道帧上带长或短帧同步或者16位数据帧扩展为32位通道帧)
- 数据方向总是MSB在先
- 发送和接收都具有DMA能力
- 主时钟可以输出到外部音频设备,比率固定为256xFs(Fs为音频采样频率)
1.3 工作原理
I2S接口的核心工作原理基于三个主要信号线的协同工作:
- 串行时钟(SCK/CK):也称为位时钟(BCLK),由主设备产生,用于同步数据传输。每个时钟周期对应音频数据的一位。SCK的频率计算公式为:SCK频率 = 2 × 采样频率 × 采样位数。例如,对于44.1kHz采样率、16位精度的立体声音频,SCK频率应为44.1kHz×16bits×2(左右声道)=1.4112MHz。
- 字选择(WS):也称为帧时钟(LRCK),用于指示当前传输的音频数据所属声道。在I2S飞利浦标准下,WS为'0'表示左声道数据,为'1'表示右声道数据。WS信号在发送第一位数据(MSB)前1个时钟周期即变为有效。
- 串行数据(SD):承载实际的音频数据,采用二进制补码表示。数据总是从最高位(MSB)开始传输,与SPI接口的MSB优先模式类似。
在某些需要更高精度时钟同步的系统中,还可以使用第四个信号线:
- 主时钟(MCK):为外部音频编解码器提供系统时钟参考,通常设置为采样频率的256倍(256xFs)。当寄存器SPI_I2SPR的MCKOE位为'1'时,W55MH32可输出此额外时钟信号。
I2S的数据传输遵循严格的时序关系。在I2S飞利浦标准下,发送方在时钟信号(CK)的下降沿改变数据,接收方在上升沿读取数据。WS信号也在时钟信号的下降沿变化。这种同步机制确保了数据传输的可靠性,即使在高速率下也能保持较低的误码率。
对于不同数据格式的处理,I2S硬件提供了自动的数据对齐和填充功能。例如,当16位数据扩展到32位帧时,高16位(MSB)为有效数据,低16位被硬件强制为0x0000,无需软件干预。24位数据扩展到32位帧时,高24位为有效数据,低8位由硬件置0。这种自动处理大大简化了软件开发,特别是在使用DMA传输时。
I2S的功能框图如下:
1.4 利用DMA通信的I2S
1.4.1 I2S配合DMA通信工作原理
I2S接口与DMA控制器协同工作时,形成高效的数据传输通道。通过将寄存器SPI_CR2的TXDMAEN/RXDMAEN位置1,可使能DMA传输请求。I2S模式下DMA的工作方式与SPI模式基本相同,只是没有CRC功能。当I2S接口需要发送或接收数据时,会自动触发DMA请求:
- 发送过程:TXE标志置1时触发DMA请求,DMA控制器将数据从内存搬运至SPI_DR寄存器。
- 接收过程:RXNE标志置1时触发DMA请求,DMA控制器将数据从SPI_DR寄存器搬运至内。
存使用DMA发送和接收的时序图如下:
1.4.2 配置要点
数据格式处理
I2S支持多种数据格式,DMA需要相应配置:
数据格式 |
DMA传输次数 |
备注 |
16位→16位帧 |
1次 |
直接传输 |
16位→32位帧 |
1次 |
硬件自动补0 |
24位→32位帧 |
2次 |
硬件补低8位0 |
32位→32位帧 |
2次 |
完整32位处理 |
声道管理
- 左声道数据总是先传输
- 通过CHSIDE标志识别当前声道
- 从模式需提前准备好第一个数据
发送流程
- 配置DMA:内存→SPI_DR,设置数据宽度
- 启动传输:TXE=1时自动触发
- 声道切换:根据CHSIDE处理左右声道
- 完成处理:等待TXE=1及BSY=0后关闭
接收流程
- 配置DMA:SPI_DR→内存,设置数据宽度
- 启动传输:RXNE=1时自动触发
- 数据解析:根据标准处理数据对齐
- 关闭时序:按数据格式选择正确时序
2 应用场景
W55MH32的I2S接口凭借其高质量数字音频传输能力,在众多领域得到广泛应用:
2.1 消费类音频设备
便携式音乐播放器:连接音频DAC实现高质量音乐播放,支持从MP3解码器到功率放大器的数字音频传输。
智能音箱:用于主控芯片与数字音频处理器之间的连接,实现语音助手和音乐播放功能。
数字电视和机顶盒:传输数字音频信号到音频处理芯片或直接驱动数字功放。
2.2 专业音频设备
录音设备:连接高性能ADC实现多通道音频采集,支持24位高分辨率录音。
音频混音器:在数字域混合多个音频源,保持信号完整性。
效果处理器:传输音频数据到DSP芯片进行实时效果处理。
2.3 通信设备
VoIP电话:实现双向语音通信,同时支持回声消除等高级功能。
会议系统:连接数字麦克风阵列和音频处理单元。
无线耳机:在蓝牙模块与编解码器之间传输音频数据。
2.4 汽车电子
车载娱乐系统:连接多个音频源和功放,支持环绕声处理。
主动降噪系统:实时采集车内噪声并生成反相声波。
语音识别系统:传输高清晰度语音数据到语音处理单元。
2.5 嵌入式系统
工业控制人机界面:实现语音提示和报警功能。
医疗监护设备:传输心音、呼吸音等生物音频信号。
智能家居:用于门铃、对讲系统等需要音频功能的设备。
3 注意事项
- 时钟同步:从模式需确保在外部时钟有效前完成初始化。
- 数据对齐:注意不同标准(Philips/MSB/LSB)的数据对齐差异。
- 电源管理:模拟部分供电需加强滤波处理。
- PCB布局:时钟信号线应尽量短并考虑端接匹配。
- 关闭顺序:严格按照规范流程关闭接口,避免数据损坏。
4 程序设计
4.1 IIS_CS4344例程
IIS_CS4344例程主要实现了基于W55MH32芯片的I2S音频传输功能。以下是实现过程和结果验证:
4.1.1 I2S初始化
I2S的初始化函数为IIS_Configuration()函数:
void IIS_Configuration(void)
{
I2S_InitTypeDef I2S_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_AFIO, ENABLE);
GPIO_PinRemapConfig(GPIO_Remap_SWJ_JTAGDisable, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_Init(GPIOC, &GPIO_InitStructure);
SPI_I2S_DeInit(SPI3);
I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx;
I2S_InitStructure.I2S_Standard = I2S_Standard_Phillips;
I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b;
I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq_8k;
I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low;
I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Enable;
I2S_Init(SPI3, &I2S_InitStructure);
SPI_I2S_DMACmd(SPI3, SPI_I2S_DMAReq_Tx, ENABLE);
I2S_Cmd(SPI3, ENABLE);
}
该函数首先使能了相关时钟并释放GPIOA15资源(PA15默认为调试接口,必须先释放其默认的调试功能,否则,调试接口会持续占用该引脚,导致I2S无法正常工作。),然后配置GPIOA15、GPIOB3、GPIOB5和GPIOC7为复用推挽输出模式以连接I2S的SCK、SD、WS和MCLK信号,接着将SPI3初始化为I2S模式并设置为主机发送模式,采用飞利浦标准、16位数据格式、8kHz采样率,启用MCLK输出和低时钟极性,最后使能DMA传输以提高数据效率并激活I2S外设。
4.1.2 DMA初始化
DMA_Configuration()为DMA初始化函数:
void DMA_Configuration(void)
{
DMA_InitTypeDef DMA_InitStructure;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_DMA2, ENABLE);
DMA_DeInit(DMA2_Channel2);
DMA_InitStructure.DMA_PeripheralBaseAddr = (uint32_t)&SPI3->DR;
DMA_InitStructure.DMA_MemoryBaseAddr = (uint32_t)I2S3_Buffer_Tx;
DMA_InitStructure.DMA_DIR = DMA_DIR_PeripheralDST;
DMA_InitStructure.DMA_BufferSize = BufferSize;
DMA_InitStructure.DMA_PeripheralInc = DMA_PeripheralInc_Disable;
DMA_InitStructure.DMA_MemoryInc = DMA_MemoryInc_Enable;
DMA_InitStructure.DMA_PeripheralDataSize = DMA_PeripheralDataSize_HalfWord;
DMA_InitStructure.DMA_MemoryDataSize = DMA_MemoryDataSize_HalfWord;
DMA_InitStructure.DMA_Mode = DMA_Mode_Circular;
DMA_InitStructure.DMA_Priority = DMA_Priority_VeryHigh;
DMA_InitStructure.DMA_M2M = DMA_M2M_Disable;
DMA_Init(DMA2_Channel2, &DMA_InitStructure);
DMA_ITConfig(DMA2_Channel2, DMA_IT_TC, ENABLE);
/* Enable SPI1 DMA TX request */
DMA_Cmd(DMA2_Channel2, DISABLE);
}
该函数首先使能了DMA2时钟,然后将DMA2通道2初始化为从内存到外设的传输模式,设置外设基址为SPI3的数据寄存器(用于I2S通信),内存基址为音频数据缓冲区I2S3_Buffer_Tx,配置传输方向为内存到外设、缓冲区大小为BufferSize,禁用外设地址自增、启用内存地址自增,设置数据宽度为半字(16位,与I2S数据格式匹配),采用循环模式确保连续传输,设置优先级为非常高,禁用内存到内存模式,最后使能传输完成中断并暂时禁用DMA通道。
4.1.3 中断配置函数
NVIC_Configuration()为NVIC(嵌套向量中断控制器)的配置函数:
void NVIC_Configuration(void)
{
NVIC_InitTypeDef NVIC_InitStructure;
NVIC_InitStructure.NVIC_IRQChannel = DMA2_Channel2_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
}
该函数首先定义NVIC了初始化结构体,然后将中断通道设置为DMA2通道2(对应I2S3的TX DMA传输),配置抢占优先级和子优先级均为0(最高优先级),使能该中断通道,最后调用初始化函数完成配置,整体实现了对DMA2通道2传输完成事件的高优先级中断响应设置,确保音频数据传输中断能被及时处理。
4.1.4 中断服务函数
DMA2_Channel2_IRQHandler()为DMA2通道2的中断服务函数:
void DMA2_Channel2_IRQHandler(void)
{
if (DMA_GetITStatus(DMA2_IT_TC2) == SET)
{
DMA_ClearITPendingBit(DMA2_IT_TC2);
DMA_ClearFlag(DMA2_FLAG_TC2);
DMA_Cmd(DMA2_Channel2, DISABLE);
Flag = 1;
}
}
程序首先检查是否为DMA传输完成中断(TC2),若是则清除中断挂起位和完成标志位,禁用DMA2通道2以暂停传输,最后将标志位Flag置1以通知主程序数据已传输完毕,整体实现了对I2S音频数据DMA传输完成的响应处理,确保在数据发送完成后能进行必要的状态更新和后续操作。
4.1.5 数据处理函数
DATA_Processing()是数据处理函数,通过以下步骤实现将8位数据转换为16位格式:
void DATA_Processing(void)
{
uint32_t i;
for (i = 0; i < DATA_LEN / 2; i++)
{
I2S3_Buffer_Tx[i] = DATA[2 * i] << 8 | DATA[2 * i + 1];
}
}
程序首先定义循环计数器,然后对长度为DATA_LEN的8位数据源数组DATA进行遍历,每次取连续的两个8位数据,将前一个左移8位后与后一个按位或运算,组合成一个16位数据存入目标数组I2S3_Buffer_Tx中,整体实现了将8位原始数据转换为适合I2S传输的16位数据格式,确保音频数据能够正确地通过I2S接口发送。
4.1.6 主程序
主程序main()通过以下步骤实现I2S音频数据的持续传输:
int main(void)
{
RCC_ClocksTypeDef clocks;
delay_init();
UART_Configuration(115200);
RCC_GetClocksFreq(&clocks);
printf("\n");
printf("SYSCLK: %3.1fMhz, HCLK: %3.1fMhz, PCLK1: %3.1fMhz, PCLK2: %3.1fMhz, ADCCLK: %3.1fMhz\n",
(float)clocks.SYSCLK_Frequency / 1000000, (float)clocks.HCLK_Frequency / 1000000,
(float)clocks.PCLK1_Frequency / 1000000, (float)clocks.PCLK2_Frequency / 1000000, (float)clocks.ADCCLK_Frequency / 1000000);
printf("IIS CS4344 Test.\n");
IIS_Configuration();
DMA_Configuration();
NVIC_Configuration();
DATA_Processing();
DMA_Cmd(DMA2_Channel2, ENABLE);
while (1)
{
if (Flag == 1)
{
printf("IIS DMA Data Send Success\n");
Flag = 0;
DMA_Configuration();
DMA_Cmd(DMA2_Channel2, ENABLE);
}
}
}
程序首先初始化系统时钟和延时函数,配置115200波特率的UART用于调试信息输出,获取并打印系统各时钟频率;接着依次配置I2S接口、DMA通道、NVIC中断控制器,并将8位原始数据处理为16位格式以适配I2S传输;然后启用DMA通道开始数据传输;最后在主循环中检测传输完成标志Flag,若置1则打印成功信息、重置标志,重新配置并启用DMA通道以实现循环传输,整体实现了通过I2S接口持续发送音频数据的功能。
4.1.7 下载验证
程序下载运行后,首先打印了系统各时钟的频率和示例名称,然后每发送成功一次I2S数据就会打印数据发送成功的信息:
此时我们接上DAC音频转换器、戴上耳机就能持续听到“微信到账100万元”的音频内容。
4.2 IIS_Dma例程
IIS_Dma例程通过I2S接口和DMA传输机制,发送预设的音频数据。该例程的I2S初始化、DMA初始化、中断配置函数与IIS_CS4344例程保持一致,这里不再赘述。其他程序设计如下:
4.2.1 发送数据
I2S3_Buffer_Tx为需要发送的测试数据:
uint16_t I2S3_Buffer_Tx[BufferSize] = {0x0102, 0x0304, 0x0506, 0x0708, 0x090A, 0x0B0C,
0x0D0E, 0x0F10, 0x1112, 0x1314, 0x1516, 0x1718,
0x191A, 0x1B1C, 0x1D1E, 0x1F20, 0x2122, 0x2324,
0x2526, 0x2728, 0x292A, 0x2B2C, 0x2D2E, 0x2F30,
0x3132, 0x3334, 0x3536, 0x3738, 0x393A, 0x3B3C,
0x3D3E, 0x3F40};
4.2.2 中断服务函数
DMA2_Channel2_IRQHandler是W55MH32中DMA2通道2的中断处理函数:
void DMA2_Channel2_IRQHandler(void)
{
if (DMA_GetITStatus(DMA2_IT_TC2) == SET)
{
DMA_ClearITPendingBit(DMA2_IT_TC2);
DMA_ClearFlag(DMA2_FLAG_TC2);
DMA_Cmd(DMA2_Channel2, DISABLE);
Flag = 1;
}
}
当DMA完成预设的32个16位数据传输后触发。函数首先检查传输完成中断状态,若中断已触发则清除中断挂起位和传输完成标志,避免重复响应;接着禁用DMA2通道2,停止数据传输;最后将全局标志位Flag置1,通知主程序DMA传输已完成,主循环检测到该标志后会输出成功信息并重置标志。此函数实现了DMA传输的中断响应与状态反馈,是I2S音频数据传输流程中的关键环节。
4.2.1 主程序
主程序main()通过以下步骤实现I2S音频数据的传输:
int main(void)
{
RCC_ClocksTypeDef clocks;
delay_init();
UART_Configuration(115200);
RCC_GetClocksFreq(&clocks);
printf("\n");
printf("SYSCLK: %3.1fMhz, HCLK: %3.1fMhz, PCLK1: %3.1fMhz, PCLK2: %3.1fMhz, ADCCLK: %3.1fMhz\n",
(float)clocks.SYSCLK_Frequency / 1000000, (float)clocks.HCLK_Frequency / 1000000,
(float)clocks.PCLK1_Frequency / 1000000, (float)clocks.PCLK2_Frequency / 1000000, (float)clocks.ADCCLK_Frequency / 1000000);
printf("IIS DMA Test.\n");
IIS_Configuration();
DMA_Configuration();
NVIC_Configuration();
DMA_Cmd(DMA2_Channel2, ENABLE);
while (1)
{
if (Flag == 1)
{
printf("IIS DMA Data Send Success\n");
Flag = 0;
}
}
}
程序首先初始化系统时钟、UART调试接口并打印时钟信息,接着配置I2S接口(复用SPI3)、DMA2通道2(循环模式)和NVIC中断控制器,随后启用DMA开始将预设的32个16位音频数据循环传输到I2S接口,主循环持续检测DMA传输完成标志位Flag,当Flag被中断处理函数置1时,打印传输成功信息并重置标志,不过因中断处理函数中禁用了DMA通道,实际数据仅能传输一次,此代码常用于音频设备初始化测试。
4.2.2 下载验证
程序下载运行后,首先打印了系统各时钟的频率和示例名称,然后I2S数据发送成功后打印数据发送成功的信息:
通过逻辑分析仪就可以解析出发送的数据:
首帧和尾帧的数据实际已经可以看到有数据脉冲信号,未解析属于硬件初始化特性(FIFO填充)或解析器同步延迟原因,不影响实际音频功能。
4.3 IIS_Int
IIS_Int例程通过I2S接口和中断控制器实现音频数据的中断驱动传输。其他程序设计如下:
4.4 I2S初始化
IIS_Configuration()函数用于初始化W55MH32的I2S接口(复用SPI3外设)及中断配置,其内容如下:
void IIS_Configuration(void)
{
I2S_InitTypeDef I2S_InitStructure;
GPIO_InitTypeDef GPIO_InitStructure;
NVIC_InitTypeDef NVIC_InitStructure;
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA | RCC_APB2Periph_GPIOB | RCC_APB2Periph_GPIOC, ENABLE);
RCC_APB1PeriphClockCmd(RCC_APB1Periph_SPI3, ENABLE);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_15;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOA, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_3 | GPIO_Pin_5;
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOB, &GPIO_InitStructure);
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7;
GPIO_Init(GPIOC, &GPIO_InitStructure);
NVIC_InitStructure.NVIC_IRQChannel = SPI3_IRQn;
NVIC_InitStructure.NVIC_IRQChannelPreemptionPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelSubPriority = 0;
NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
NVIC_Init(&NVIC_InitStructure);
SPI_I2S_DeInit(SPI3);
I2S_InitStructure.I2S_Mode = I2S_Mode_MasterTx;
I2S_InitStructure.I2S_Standard = I2S_Standard_Phillips;
I2S_InitStructure.I2S_DataFormat = I2S_DataFormat_16b;
I2S_InitStructure.I2S_AudioFreq = I2S_AudioFreq_8k;
I2S_InitStructure.I2S_CPOL = I2S_CPOL_Low;
I2S_InitStructure.I2S_MCLKOutput = I2S_MCLKOutput_Enable;
I2S_Init(SPI3, &I2S_InitStructure);
SPI_I2S_ITConfig(SPI3, SPI_I2S_IT_TXE, ENABLE);
I2S_Cmd(SPI3, ENABLE);
}
函数首先使能GPIOA/B/C和SPI3的时钟,配置相关引脚为复用推挽输出(包括数据输出、字选择、串行时钟和主时钟引脚);接着配置NVIC中断控制器,设置SPI3中断的优先级并使能中断;然后重置SPI3并设置I2S参数,包括主发送模式、飞利浦标准、16位数据格式、8kHz采样率、低时钟极性和主时钟输出;最后启用发送缓冲区空中断(TXE)并使能I2S外设。该配置适用于简单音频发送场景,通过中断驱动方式实现数据传输。
4.4.1 中断服务函数
SPI3_IRQHandler()是SPI3外设的中断处理函数,用于处理I2S发送缓冲区空(TXE)事件,函数内容如下:
void SPI3_IRQHandler(void)
{
if (SPI_I2S_GetITStatus(SPI3, SPI_I2S_IT_TXE) == SET)
{
/* Send a data from I2S3 */
SPI_I2S_SendData(SPI3, I2S3_Buffer_Tx[TxIdx++]);
}
if (TxIdx == 32)
{
SPI_I2S_ITConfig(SPI3, SPI_I2S_IT_TXE, DISABLE);
}
}
当检测到TXE标志置位时,函数从预设的32元素数据缓冲区I2S3_Buffer_Tx中读取一个16位数据发送到I2S接口,并递增索引TxIdx;当TxIdx达到32时,表示所有数据发送完毕,函数禁用TXE中断以停止传输。该函数实现了基于中断的单次数据块发送,适用于小规模固定数据的传输场景。
4.4.2 主程序
以下为该例程的主程序,用于测试I2S接口的中断驱动数据发送功能:
int main(void)
{
RCC_ClocksTypeDef clocks;
delay_init();
UART_Configuration(115200);
RCC_GetClocksFreq(&clocks);
printf("\n");
printf("SYSCLK: %3.1fMhz, HCLK: %3.1fMhz, PCLK1: %3.1fMhz, PCLK2: %3.1fMhz, ADCCLK: %3.1fMhz\n",
(float)clocks.SYSCLK_Frequency / 1000000, (float)clocks.HCLK_Frequency / 1000000,
(float)clocks.PCLK1_Frequency / 1000000, (float)clocks.PCLK2_Frequency / 1000000, (float)clocks.ADCCLK_Frequency / 1000000);
printf("IIS Int Test.\n");
IIS_Configuration();
while (1);
}
程序先初始化延时函数和UART1串口,获取并打印系统各时钟频率,然后初始化I2S接口(配置GPIO、中断及I2S参数),最后进入无限循环,数据发送由I2S发送缓冲区空中断驱动,主程序不参与具体传输逻辑。
4.4.3 下载验证
程序下载运行后,首先打印了系统各时钟的频率和示例名称,I2S触发中断之后开始发送数据,数据缓冲区有数据之后便不再触发:
逻辑分析仪解析数据如下:
同样的,首帧和尾帧的数据实际也已经可以看到有数据脉冲信号,未解析属于硬件初始化特性(FIFO填充)或解析器同步延迟原因,不影响实际音频功能。
5 总结
W55MH32的I2S接口为数字音频应用提供了强大而灵活的解决方案。通过与SPI模块共享硬件资源,它既实现了专用音频接口的高性能,又保持了设计的经济性。支持多种音频标准和数据格式使其能够与绝大多数音频编解码器无缝协作,满足从消费电子到专业音频设备的各种需求。