找回密码
 立即注册
楼主: 梁工

Ai8051U 实现USB声卡(播放或录音+播放),读TF卡/SD卡 音频播放器,32位8051,重磅开源

  [复制链接]

8

主题

23

回帖

128

积分

注册会员

积分
128
发表于 2026-9-6 22:40:23 | 显示全部楼层
使用ai8051实验箱,主频为40MhzAICUBE配置I2S测试TLV320AIC23B,I2S配置如下,终于可以出声了
I2S配置.png
演示程序是想输出500KHZ左右到的音频,但实际输出在1.29kHZ,而且还不稳定,不知道是什么原因。
这是演示代码 TLV320DEMO.zip (757.36 KB, 下载次数: 2)

点评

TLV320AIC23B最高支持96KHz采样,最高输出48KHz的正弦波信号。 你要输出500KHz的音频信号? 这远超过采样率了。 超过20KHz的音频人耳将听不到。  详情 回复 发表于 2026-9-6 23:02
回复

使用道具 举报 送花

83

主题

8216

回帖

1万

积分

超级版主

积分
17634
 楼主| 发表于 2026-9-6 23:02:12 | 显示全部楼层
指*** 发表于 2026-9-6 22:40
使用ai8051实验箱,主频为40MhzAICUBE配置I2S测试TLV320AIC23B,I2S配置如下,终于可以出声了

演示程序是 ...

TLV320AIC23B最高支持96KHz采样,最高输出48KHz的正弦波信号。
你要输出500KHz的音频信号? 这远超过采样率了。
超过20KHz的音频人耳将听不到。
回复

使用道具 举报 送花

8

主题

23

回帖

128

积分

注册会员

积分
128
发表于 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



回复

使用道具 举报 送花

8

主题

23

回帖

128

积分

注册会员

积分
128
发表于 2026-9-7 22:48:57 | 显示全部楼层
继续测试,为了测试方便,单片机主频选用40Mhz。所以输出频率不是1Khz。
在AICUBE中改为以下参数,输出稳定
I2S配置2.png
请问,问题AICUBE中的采样率只有3.91K了,是计算错了吗?
示波器波形.jpg

TLVAIC23B.rar

726.57 KB, 下载次数: 0

回复

使用道具 举报 送花

8

主题

23

回帖

128

积分

注册会员

积分
128
发表于 2026-9-7 22:55:32 | 显示全部楼层
波形问题dac_L = T_SINE_16[TestTonePhase >> 12]+32768;解决
回复

使用道具 举报 送花

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

QQ|手机版|深圳国芯人工智能有限公司 ( 粤ICP备2022108929号-2 )

GMT+8, 2026-9-22 06:03 , Processed in 0.076953 second(s), 60 queries .

Powered by Discuz! X3.5

© 2001-2026 Discuz! Team.

快速回复 返回顶部 返回列表