|
|
发表于 2026-9-7 16:37:31
|
显示全部楼层
遇到问题后认真看l 看相关资料。记录如下:
一、I2S发送缓冲区中断的条件
控制项 寄存器/位 地址
状态标志 TXE(I2SSR的B1位) 7EFD99H
中断允许 TXEIE(I2SCR的B7位) 7EFD98H
触发条件:当I2S发送缓冲区变空时,TXE标志置1。若 TXEIE=1(允许发送缓冲区空中断),则产生I2S中断。
根据手册,I2SSR的 TXE 位定义是"发送缓冲区空标志位"。当I2S发送模块取走当前要发的数据后,发送缓冲区变空,TXE置1,若TXEIE=1则触发中断。
中断触发后,代码通过 CHSID(I2SSR的B2位) 来判断当前是左声道还是右声道:
if (I2SSR & 0x04) // CHSID=1,右声道
{
// 发送右声道数据
}
else // CHSID=0,左声道
{
// 发送左声道数据
}
所以一次TXE中断 = 一个声道的一个采样点数据被取走,需要补下一个声道的数据。
二、数据帧
帧的构成
I2S的一个完整的帧(Frame) 包含 左右两个声道各一个数据:
组成 说明
左声道数据 1个采样点(16位或32位)
右声道数据 1个采样点(16位或32位)
合计 = 1帧 = 2 × 每通道位数
根据手册中I2S比特率公式:
I2S比特率 = 每个通道的比特数 × 通道数 × 音频采样频率(FS)
对于16位音频、左声道和右声道:I2S比特率 = 16 × 2 × FS
所以当 CHLEN=0(16位) 时,一个帧 = 16 bit(左) + 16 bit(右) = 32 bit。
当 CHLEN=1(32位) 时,一个帧 = 32 bit(左) + 32 bit(右) = 64 bit。
帧率 = 采样率
每个采样周期(1/FS)发送一帧(左右声道各一个采样点)。所以:
采样率 FS = 44100Hz 时,每秒钟发送 44100 帧
采样率 FS = 32000Hz 时,每秒钟发送 32000 帧
三、完整的发送时序
以 16位音频、双声道、采样率32kHz 为例:
时间轴 ──►
┌──────┐ ┌──────┐ ┌──────┐ ┌──────┐
│ L声道 │ │ R声道 │ │ L声道 │ │ R声道 │ ...
└──────┘ └──────┘ └──────┘ └──────┘
│ │ │ │
└── 一帧 ──┘ └── 一帧 ──┘
(L+R=32bit) (L+R=32bit)
TXE中断触发点:
L发送完→TXE中断(补R) R发送完→TXE中断(补L) L发送完→TXE中断(补R) ...
实际的中断触发频率 = 采样率 × 2 = 32000 × 2 = 64000 次/秒
即每秒钟触发 64000次中断,每次中断补一个声道的16位数据。
四、频率计算
采样率为 32kHz,16个数据点(16点/周期),输出频率:
f = 32000/16 = 2000Hz =2kHz
每帧(左右声道各一个采样点)= 2次中断
一个完整周期(16点)= 16帧 = 32次中断
32kHz采样率下,每帧时间 = 1/32000 = 31.25 µs
16帧的时间 = 16 × (1/32000) = 0.5 ms
1秒内完成 2000 个完整周期 → 输出频率 2kHz ✓
1帧 = 2次中断(左声道1次 + 右声道1次)每周期16点 = 16帧 = 32次中断
程序中定义数据为16个
u16 code T_SINE_16[16] = {
32768, 45014, 55395, 62332, 64768, 62332, 55395, 45014,
32768, 20522, 10141, 3204, 768, 3204, 10141, 20522
};
中断代码为,左右声道都一样的数据
void I2S_ISR(void) interrupt I2S_VECTOR
{
u8 i;
if (I2SSR & 0x02) //发送缓冲区空
{
if (I2SSR & 0x04) //右声道
{
i = dac_index + 0x80; //单极性转成双极性(无符号转有符号)
I2SDRH = i; //发送下一帧音频数据
I2SDRL = 0;
if(B_rise)
{
if(++dac_index == 255)
B_rise = 0;
}
else
{
if(--dac_index == 0)
B_rise = 1;
}
}
else //左声道
{
i = dac_index + 0x80; //单极性转成双极性(无符号转有符号)
I2SDRH = i; //发送下一帧音频数据
I2SDRL = 0;
}
}
}
则上面的16个数据,共16帧,正好产生32次中断,(假设先左声道后右声道)即第1次中断为发送左声道数据T_SINE_16[0],第2次中断为发送右声道数据T_SINE_16[0],第3次中断为发送左声道数据T_SINE_16[1],第4次中断为发送右声道数据T_SINE_16[1],。。。
时间轴(单位:µs)→
0 31.25 62.5 93.75 125 156.25 187.5 218.75 250
│ │ │ │ │ │ │ │
├──帧0─────┤──帧1──────┤──帧2──────┤──帧3─────┤──帧4──────┤──帧5──────┤──帧6──────┤──帧7──...
L=pt[0] L=pt[1] L=pt[2] L=pt[3] L=pt[4] L=pt[5] ...
R=pt[0] R=pt[1] R=pt[2] R=pt[3] R=pt[4] R=pt[5] ...
(下半帧R)
0.5ms = 16帧 = 一个完整波形周期
1ms = 32帧 = 两个完整波形周期
...
每帧 = 左右声道各一个采样点 = 1/32000 = 31.25µs
16帧 = 一个完整信号周期 = 16/32000 = 0.5ms
频率 = 1/0.5ms = 2000Hz
|
|