This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] TAS2560:音频 I2S

Guru**** 1649650 points
Other Parts Discussed in Thread: TAS2560
请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/audio-group/audio/f/audio-forum/1273017/tas2560-audio-i2s

器件型号:TAS2560

尊敬的先生:

我最终让 TAS2560播放8 kHz 16位声音。 然而,声音不会变成它被认为的方式。 我已附加两个文件

1)它会播放音频文件、说明  "所有过境均有步行标志"  

2) 2)生成的1kHz 正弦波、具有以下功能:

uint32_t generate_stereo_tone(uint16_t *buffer, unsigned int sample_rate, double duration, double frequency, bool reset, uint16_t writeBufferSize)
{
    unsigned int num_samples = (unsigned int)(sample_rate * duration);
    short amplitude = 32767; // 16-bit maximum amplitude
    static unsigned int k = 0;
    uint16_t maxBufferSize=(writeBufferSize/2)-1;
    int addr=0;
    uint16_t test=0;

    if (reset == true || k>=num_samples)
    {
        k =1;
    }
    else{
        for (unsigned int i = k; i < num_samples; i++)
        {
            double time = (double)i / sample_rate;

           buffer[2 * (i-k)+1] = (short)(amplitude * sin(2 * M_PI * frequency * time)); // Left channel
           buffer[2 * (i - k)] = 0;                                           // Right channel (silence)


            if ((i - k) ==maxBufferSize)
            {
                k = i;
                return (num_samples-i);
            }
        }
    }
}

e2e.ti.com/.../1-khz.m4ae2e.ti.com/.../Walk-SIgn-On.m4a

您能不能建议什么必须是问题,有时它感觉我没有给它足够的数据,但似乎很难相信,因为我有4个写入缓冲区,每一个1024字节下面是我的 i2x 设置代码:

void I2S_Setup()
{
    // Initialize the I2S driver
    I2S_init();
    I2S_Params i2sParams;

    // Initialize I2S opening parameters
    //     I2S_Params i2sParams;
    I2S_Params_init(&i2sParams);
    i2sParams.samplingFrequency = SAMPLE_RATE;
    i2sParams.fixedBufferLength = WRITE_BUF_LENGTH * 2;
    i2sParams.bitsPerWord = 16;
    i2sParams.writeCallback = writeCallbackFxn;
    i2sParams.readCallback = readCallbackFxn;
    i2sParams.errorCallback = errCallbackFxn;
    i2sParams.CCLKDivider = 4;
    i2sParams.isDMAUnused = true;

    i2sHandle = I2S_open(CONFIG_I2S_0, &i2sParams);

    I2S_startClocks(i2sHandle);
}

这是我的游戏主题:

void *playAudioThread(void *arg0)
{

    int k;
    I2S_Transaction *lastAchievedTransaction;
    bool static firstTime = true;
    uint32_t offset;

    uint32_t events;
    printf("Transaction1 address = 0x%x  writeBuf1 address = 0x%x\n", &i2sWrite1, &writeBuf1);
    printf("Transaction2 address = 0x%x  writeBuf2 address = 0x%x\n", &i2sWrite2, &writeBuf2);
    printf("Transaction3 address = 0x%x  writeBuf3 address = 0x%x\n", &i2sWrite3, &writeBuf3);
    printf("Transaction4 address = 0x%x  writeBuf4 address = 0x%x\n\n\n", &i2sWrite4, &writeBuf4);


    //initAudioBuffers();
   
    I2S_Setup();

    uint32_t bytesRemaining = 0;

    while (1)
    {

        if (playStop == true)
        {
            if(firstTime == true)
            {
                initAudioBuffers();
                bytesRemaining=preload_Config_AudioBuffers(writeBuf1, writeBuf2, writeBuf3, writeBuf4, playFile, 0, WRITE_BUF_LENGTH);
                firstTime = false;
                I2S_setWriteQueueHead(i2sHandle, &i2sWrite1);
                I2S_startWrite(i2sHandle);
                offset=0;
            }


            if (writeFinished == true)
            {

                if(transactionFinished != NULL)
                {


                    // Need a critical section to be sure to have corresponding bufPtr and bufSize
                     uintptr_t key = HwiP_disable();
                     uint16_t *buf = transactionFinished->bufPtr;
                     uint16_t bufLength = transactionFinished->bufSize / sizeof(uint16_t);
                     bytesRemaining = loadAudioChunk(buf, playFile, offset, WRITE_BUF_LENGTH);
                     offset=offset+WRITE_BUF_LENGTH;
                     HwiP_restore(key);
                     List_put(&i2sWriteList, (List_Elem*)transactionFinished);
                    // audio_console_print_function(console_debug,"Reload Buffer");
                }

//
                if (bytesRemaining <= 0x100)
                {
                   endTicks = Clock_getTicks();
                    elapsedTimeTicks = endTicks - startTicks;
                    Task_sleep(CLOCK_MS(150));
                    I2S_stopWrite(i2sHandle);
                    // I2S_stopClocks(i2sHandle);
                    StopSound();
                    bytesRemaining = 0;
                    firstTime = true;
                    playStop=false;
                    writeFinished = false;
                    audio_console_print_function(console_debug,"Sound file Played");
                }
                writeFinished = false;
                //audio_console_print_function(console_debug,"transaction complete %x ,bytes remaining %d, no of completions: %d",transactionFinished, bytesRemaining,transactionFinished->numberOfCompletions);
            }
            else
            {
                 Task_sleep(CLOCK_MS(5));
            }
        }
        else
        {
            Task_sleep(CLOCK_MS(100));
            I2S_stopWrite(i2sHandle);
        }
    }
}

写入回调

static void writeCallbackFxn(I2S_Handle handle, int_fast16_t status, I2S_Transaction *transactionPtr) {

     // We must remove the previous transaction (the current one is not over)
       transactionFinished = (I2S_Transaction*)List_prev(&transactionPtr->queueElement);
//      audio_console_print_function(console_debug,"transaction complete prev%x",(I2S_Transaction*)List_prev(&transactionPtr->queueElement));
//      audio_console_print_function(console_debug,"transaction complete next%x",(I2S_Transaction*)List_next(&transactionPtr->queueElement));
    // audio_console_print_function(console_debug,"transaction complete %x",transactionFinished);
      if(transactionFinished != NULL){
          // Remove the finished transaction from the write queue
          List_remove(&i2sWriteList, (List_Elem*)transactionFinished);

          writeFinished=true;
      }
      if(status>I2S_TRANSACTION_SUCCESS)
      {
          audio_console_print_function(console_debug,"I2S Error %x", status);
      }
      if(status==I2S_ALL_TRANSACTIONS_SUCCESS)
      {
          audio_console_print_function(console_debug,"Buffer UnderRun");
          writeFinished=false;
      }


 }

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Nadeem:

    您能否确认输入时钟频率是多少? 8kHz 和16位的 FS 似乎是一个相当低的比率。 请注意、最小输入时钟频率为512kHz。

    此致、
    -Ivan Salazar
    应用工程师

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    感谢您的回复。  

    WCLK = 7.98khz

    BCLK = 255.31kHz

    MCLK = 12MHz

    这是您要求的吗? 这是我从 I2S 端口发出的信号。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    当我看起来像波,它似乎它的剪辑。 另一个有趣的我注意到,总是有一个脉冲显示在视频中,虽然没有声音正在播放。 请忽略视频的声音...我的电脑上正在播放一些内容。 视频只是显示了扬声器的输出而没有播放任何内容。

    e2e.ti.com/.../WhatsApp-Video-2023_2D00_09_2D00_21-at-12.24.01-PM.mp4

    当某件事情是播放的脉冲仍然像方波,只是增加的持续时间(脉宽增加)。 可能是其削波?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Nadeem:

    请注意、这是一个 D 类放大器、因此如果在测量时未使用 RC 或 LC 滤波器进行滤波、则输出波形为 PWM 信号。 因此、这可能是可以的。
    关于时钟设置、我仍然认为 BCLK 可能太低、我将在今天晚些时候或下周早些时候再次进行检查并提供进一步评论。

    此致、
    -Ivan Salazar
    应用工程师

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    这位男士有什么最新消息吗?

    谢谢你的时间。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Nadeem:

    还没有时间对此进行测试、我将在本周尝试为其设置一些时间。

    此致、
    -Ivan Salazar
    应用工程师

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Nadeem:

    我无法使用 MCLK = 12MHz 进行测试、但我使用此设置进行了测试、似乎工作正常:

    • MCLK = 12.288MHz (1536比 WCLK)
    • BCLK = 256kHz
    • WCLK = 8kHz

    在本次测试中、我使用了 PPC3内的 End System Integration 面板 、您可以在其中选择时钟源、频率和采样率。 如果我尝试使用12MHz、输出噪声会很大、但这是因为我在使用12.288MHz。

    您可以使用我从 PPC3生成的以下连接配置进行测试:

    e2e.ti.com/.../8K_5F00_12M_5F00_TAS2560.cfg

    此致、
    -Ivan Salazar
    应用工程师