AI8051U 的 I2S(集成电路内置音频总线)接口主要用于驱动外部音频编解码器或数字功放,实现高质量的数字音频播放。官方和社区已经基于此开发了USB 声卡、TF 卡音频播放器等成熟应用。
一:工作原理:
AI8051U 内部集成了 I2S 接口,负责将数字音频数据(如 PCM 格式)传输给外部的音频芯片。最常见的硬件搭配是 AI8051U + TLV320AIC23B 立体声编解码器。
工作流程:单片机通过 I2S 总线将音频数据发送给 TLV320AIC23B,该芯片负责将数字信号转换为模拟信号,并通过耳机或线路输出。系统主频通常设置为 36.864MHz,这是为了满足 48kHz 采样率的整数倍要求。
音频格式:最常见的配置是 48kHz 采样率、16位立体声数据。在某些应用中,如从 Flash 播放音频,可能会使用 ADPCM 等压缩格式以节省空间
二:开发注意事项:
在进行 I2S 音频开发时,有几个关键点需要注意:
中断处理:I2S 数据通常在中断中填充,确保音频流连续不间断。例如,在 20kHz 的中断频率下填充左右声道的数据。
音量控制:音量调节通常通过控制 I2S 数据的幅值来实现。例如,在 USB 声卡例程中,可以通过按键调整音量大小。
更换音频芯片:如果将音频芯片从 TLV320AIC23B 更换为 TAS5805M 等其他型号,通常只需要修改 I2C 控制接口的初始化代码,而 I2S 的数据发送中断处理函数一般无需改动。
数据格式:音频数据的格式(如采样率、位数、通道数)必须在 I2S 接口的初始化中与音频源严格匹配。
三:软件代码:
3.1 I2S 初始化函数
void I2S_config(void)
{
I2SMD = 0xff; //内部保留字节,需设置为FFH
I2SSR = 0x00; //状态寄存器清0
I2SCR = 0x80+0x00; //使能发送缓冲区空中断(0x80), +0x00:Motorola格式, +0x10:TI格式
HSCLKDIV = 1; //高速时钟分频器 1~255 (默认2)
I2S_CLKDIV = 1; //I2S主时钟分频
I2SMCKDIV = I2S_MCLKDIV; //I2S时钟分频,I2SMCLK = 主频/2/I2S_CLKDIV/HSCLKDIV/I2SMCKDIV, 或I2SMCLK = PLLCLK/2/I2S_CLKDIV/HSCLKDIV/I2SMCKDIV
I2SPRH = (MCKOE << 1) + (I2S_BCLKDIV & 1); //设置I2S_BMCLK分频系数的bit0, 并允许或禁止输出MCLK。
I2SPRL = I2S_BCLKDIV/2; //设置I2S_BMCLK分频系数的bit8~bit1
I2SCFGH = I2S_MODE; //设置I2S模式为主机发送模式
I2SCFGL = (PCMSYNC << 7) + (STD_MODE << 4) + (CKPOL << 3) + (DATLEN << 1) + CHLEN;
P_SW3 = (P_SW3 & 0x3f) | (1<<6); //I2S端口切换, 0: P3.2(BCLK) P3.3(MCLK) P3.4(SD) P3.5(WS), 2024-7-21
// 1: P1.7(BCLK) P1.6(MCLK) P1.5(SD) P1.4(WS),
// 2: P2.3(BCLK) P2.2(MCLK) P2.1(SD) P2.0(WS),
// 3: P4.3(BCLK) P1.6(MCLK) P4.1(SD) P4.0(WS),
I2SCFGH |= I2SEN; //使能I2S模块
}3.2 I2S 中断处理部分:
void I2S_ISR(void) interrupt I2S_VECTOR
{
u16 j;
if (I2SSR & 0x02) //发送缓冲区空
{
I2SDRH = (u8)(dac /256); //更新音频数据, 单声道不分左右
I2SDRL = (u8)(dac %256);
if((I2SSR & 0x04) == 0) //左声道, 解码ADPCM,启动ADC
{
if(B_record) //正在录音, 则启动ADC
{
ADC_RES = 0; ADC_RESL = 0;
ADC_START = 1; //启动ADC转换, 完成后自动清零
}
if(++cnt_1ms >= (u8)(SampleRate/1000))
{
DisplayScan(); //1ms扫描显示一位
cnt_1ms = 0;
if(++cnt_20ms == 20) cnt_20ms = 0, B_20ms = 1; //20ms时隙
}
}
else //右声道
{
if(B_PlayEn) //正在播放
{
Alaw_decode(); //解压缩后得到16位有符号DAC
if(++PlayByteCnt >= FileLength) B_PlayEn = 0, B_stop = 1; //播放完成了
}
else dac = 0;
if(B_record) //正在录音, 读取ADC,A-LAW压缩
{
j = (u16)ADC_RES * 256 + (u16)ADC_RESL;
ADC_FLAG = 0; //清除ADC完成(中断)标志
Alaw_encode(j); //输入12bit无符号的ADC值
}
}
}
// I2SSR &= ~0x5B; //已自动清除中断标志
}四:实物如下

我要赚赏金
