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.

[参考译文] TAS2563:MCU 集成

Guru**** 2416110 points
Other Parts Discussed in Thread: TAS2563

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

https://e2e.ti.com/support/audio-group/audio/f/audio-forum/1402156/tas2563-mcu-integration

器件型号:TAS2563

工具与软件:

在获取在定制 ESP32-S3板上播放音频时遇到问题。 器件通过 I2C 和 I2S 的接线和通信均按预期工作、我认为通过各种寄存器进行器件配置时存在问题。

在另一个论坛博文中、我们提供了一些简单的 MCU 实现代码。

https://e2e.ti.com/support/audio-group/audio/f/audio-forum/1037161/tas2563-code-example-for-mcu/3855350?tisearch=e2e-sitesearch&keymatch=TAS2563%252525252520MCU#3855350

此代码具有一些编辑功能、但仍不能播放音频。 我尝试打开模块的音调发生器、但仍然没有声音。

要从扬声器简单扬声器进行单声道音频输出、最少需要哪些寄存器设置? I2S 数据在16bps 时的采样率为44100。

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

    赦免2个语法错误。

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

    我也对这方面的解决方案感兴趣。

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

    尊敬的 Halen:

    您能否在播放尝试前后读取 IRQ 标志寄存器? 这是簿0页0上的寄存器0x24到0x27。

    在器件运行期间停止输入时钟(SBCLK 和/或 FSYNC)会导致器件触发时钟错误检测并自动关闭、是否会在不播放音频时停止时钟? 如果确实如此、请确保在停止时钟之前将器件设置为 SW SHUTDOWN、并仅在时钟重新开启后将器件设置为 ACTIVE 模式。 软件关断和工作模式由寄存器0x02控制。

    此致、
    伊万·萨拉扎尔
    应用工程师

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

    我将尝试它。

    IRQ 寄存器有几个标志。

    PLL 锁定

    器件上电

    器件断电

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

    尊敬的 Halen:

    在尝试播放之前和之后是否相同?
    这些特定的标志应该是可以的、这些只是通知标志、而不是错误标志。

    还请根据我上一篇文章中提出的问题来评论时钟序列。

    此致、
    伊万·萨拉扎尔
    应用工程师

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

    这些 IRQ 标志在回放之前、期间和之后显示。

    我设置的时钟时序应该是正确的。 这是我的设置代码和寄存器配置。

      // I2S 设置
      I2S_CONFIG_t I2S_CONFIG ={
        .mode =(I2S_MODE_t)(I2S_MODE_MASTER | I2S_MODE_TX)、
        .sample_rate = 44100
        .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT、
        .channel_format = I2S_CHANNEL_FMT_RIGHT_LEFT、
        .communication_format = I2S_COMM_FORMAT_I2S
        .intr_alloc_FLAGS = 0//默认中断优先级
        .dma_buf_count = 8
        .dma_buf_len = 512
        .use_apll = false
        .tx_desc_auto_clear = true//如果下溢、则自动清除
        FIXED_MCLK = 0};

      // I2S 引脚配置
      I2S_PIN_CONFIG_t PIN_CONFIG ={
        .bcK_io_num = I2S_BCLK
        .ws_io_num = i2s_word
        .data_out_num = I2S_SDO
        .data_in_num = I2S_SDI};

      I2S_DRIVER_INSTALL (I2S_NUM_0、&I2S_CONFIG0NULL);
      I2S_SET_Pin (I2S_NUM_0、&PIN_CONFIG);
      I2S_SET_clk (I2S_NUM_044100、I2S_BITS_PER_SAMPLE_16BIT、I2S_CHANNEL_MONO);

      // TAS2563设置
      tas2563_CONFIG_REGISTERS (TAS2563_LEFT_I2C_ADDRESS1);//断电 RESET
      tas2563_CONFIG_REGISTERS (TAS2563_LEFT_I2C_ADDRESS2);//编程
      tas2563_CONFIG_REGISTERS (TAS2563_LEFT_I2C_ADDRESS3);//配置
      tas2563_CONFIG_REGISTERS (TAS2563_LEFT_I2C_ADDRESS4);//上电
      tas2563_CONFIG_REGISTERS (TAS2563_LEFT_I2C_ADDRESS5);//取消静音




    忽略下面的格式、这些是正在设置的页面和寄存器

    //定义数组
    CFG_reg POWER_DOWN_RESET[]={
      {0x00、0x00}、
      {0x7F0x00}、
      {0x020x0E}、// i/v 检测关断+关断
      {0x010x01}、// RESET
      {CFG_META_DELAY0x01}、
      {0x080x5e//单声道左 PCM + 32位
    };

    cfg_reg PLL[]={
      // PLL 设置(在原始代码中禁用)
    };

    cfg_reg powerup[]={
      {0x00、0x00}、
      {0x7F0x00}、
      {0x300x1d}、// Clear int
      {0x1a0xff}、//禁用整数
      {0x1b0xff}、//禁用 int
      {0x020x00}、//启用 I/v sense、active
      {0x000x02}、//簿=2、页=0
      {0x7F0x00}、
      {0x5c0x00}、// PICN
      {0x5c0x2F}、
      {0x640x70}、// pICNDelay
      {0x00、0x00}、
      {0x7F0x00}、//簿=0、页=0
      {0x1a0xf8}、//整数
      {0x1b、0xb1}、
      {0x020x00}、//启用 I/v sense、active
    };

    cfg_reg 取消静音[]={
      {0x00、0x00}、
      {0x7F0x00}、
      {0x020x00}、// i/v 检测启用+关断
    };

    cfg_reg 程序[]={
      //如果需要、添加程序序列
    };

    cfg_reg 配置[]={
      //如果需要、添加配置序列
    };
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    尊敬的 Halen:

    您写入到器件中的逻辑是什么? 您也使用任何头文件或二进制文件吗?

    此致、
    伊万·萨拉扎尔
    应用工程师

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

    不、我的程序要长得多。 这是设置代码中最有可能发生问题的重要部分。

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

    这是我的完整 AmplifierController.cpp 代码。 要启动程序,请调用 amp_init ();然后调用 amp_play_wav ();

    #include "AmplifierController.h"
    
    bool amp_init()
    {
        // I2S setup
        i2s_config_t i2s_config = {
            .mode = (i2s_mode_t)(I2S_MODE_MASTER | I2S_MODE_TX),
            .sample_rate = 44100,
            .bits_per_sample = I2S_BITS_PER_SAMPLE_16BIT,
            .channel_format = I2S_CHANNEL_FMT_ONLY_LEFT,
            .communication_format = I2S_COMM_FORMAT_I2S,
            .intr_alloc_flags = 0, // Default interrupt priority
            .dma_buf_count = 8,
            .dma_buf_len = 512,
            .use_apll = false,
            .tx_desc_auto_clear = true, // Auto clear if underflow
            .fixed_mclk = 0};
    
        // I2S pin configuration
        i2s_pin_config_t pin_config = {
            .bck_io_num = I2S_BCLK,
            .ws_io_num = I2S_WORD,
            .data_out_num = I2S_SDO,
            .data_in_num = I2S_SDI};
    
        i2s_driver_install(I2S_NUM_0, &i2s_config, 0, NULL);
        i2s_set_pin(I2S_NUM_0, &pin_config);
        i2s_set_clk(I2S_NUM_0, 44100, I2S_BITS_PER_SAMPLE_16BIT, I2S_CHANNEL_MONO);
    
        // TAS2563 Setup
        tas2563_config_registers(TAS2563_LEFT_I2C_ADDRESS, 1); // power down reset
        tas2563_config_registers(TAS2563_LEFT_I2C_ADDRESS, 2); // program
        tas2563_config_registers(TAS2563_LEFT_I2C_ADDRESS, 3); // config
        tas2563_config_registers(TAS2563_LEFT_I2C_ADDRESS, 4); // power up
        tas2563_config_registers(TAS2563_LEFT_I2C_ADDRESS, 5); // unmute
    
        return true;
    }
    
    void amp_play_wav()
    {
        readRegister(TAS2563_TDM_DET);
        readRegister(TAS2563_TDM_CONFIG_REG0);
    
        readRegister(TAS2563_INT_LTCH0);
        readRegister(TAS2563_INT_LTCH1);
        readRegister(TAS2563_INT_LTCH2);
        readRegister(TAS2563_INT_LTCH3);
    
        // Open the .wav file
        File wavFile = SD.open("/Lord of the Rangs Short.wav");
        if (!wavFile)
        {
            Serial.println("Failed to open file for reading");
            return;
        }
    
        // Skip the WAV header (typically 44 bytes)
        wavFile.seek(44);
    
        // Buffer for reading WAV data
        byte buffer[512];
        size_t bytes_written;
        int num = 0;
        while (wavFile.available())
        {
            int bytesRead = wavFile.read(buffer, sizeof(buffer));
    
            // Write the buffer to the I2S interface
            i2s_write(I2S_NUM_0, buffer, bytesRead, &bytes_written, portMAX_DELAY);
    
            if (num % 1000 == 0)
            {
                readRegister(TAS2563_TDM_DET);
                readRegister(TAS2563_TDM_CONFIG_REG0);
                readRegister(TAS2563_INT_LTCH0);
                readRegister(TAS2563_INT_LTCH1);
                readRegister(TAS2563_INT_LTCH2);
                readRegister(TAS2563_INT_LTCH3);
            }
    
            // Check if the bytes written match the bytes read from the file
            if (bytes_written != bytesRead)
            {
                Serial.println("I2S write error");
            }
            num++;
        }
    
        wavFile.close();
        Serial.println("Playback finished");
    
        readRegister(TAS2563_TDM_DET);
        readRegister(TAS2563_TDM_CONFIG_REG0);
    }
    
    // Function to write to a TAS2563 register
    void writeRegister(uint8_t reg, uint8_t value)
    {
        Wire.beginTransmission(TAS2563_LEFT_I2C_ADDRESS); // Begin I2C communication with TAS2563
        Wire.write(reg);                                  // Send the register address
        Wire.write(value);                                // Send the data to write to the register
        Wire.endTransmission();                           // End transmission
    
        // Optionally, print out the operation for debugging
        Serial.print("Wrote to reg 0x");
        Serial.print(reg, HEX);
        Serial.print(": 0x");
        Serial.println(value, HEX);
    }
    
    // Function to read from a TAS2563 register (for debugging)
    uint8_t readRegister(uint8_t reg)
    {
        Wire.beginTransmission(TAS2563_LEFT_I2C_ADDRESS); // Begin I2C communication with TAS2563
        Wire.write(reg);                                  // Send the register address
        Wire.endTransmission(false);                      // End transmission but keep the connection alive
    
        Wire.requestFrom(TAS2563_LEFT_I2C_ADDRESS, (uint8_t)1); // Request 1 byte of data from the register
        uint8_t value = Wire.read();                            // Read the byte
    
        // Optionally, print out the operation for debugging
        Serial.print("Read from reg 0x");
        Serial.print(reg, HEX);
        Serial.print(": 0x");
        Serial.println(value, HEX);
    
        return value;
    }
    
    // I2C Transfer Function (Stub for actual I2C implementation)
    uint16 PltI2cTransfer(uint8 address, uint8 *tx, uint16 tx_len, uint8 *rx, uint16 rx_len)
    {
        Wire.beginTransmission(address >> 1); // Arduino Wire library uses 7-bit address
        Wire.write(tx, tx_len);
        Wire.endTransmission();
        if (rx_len > 0)
        {
            uint8_t response = Wire.requestFrom(address >> 1, rx_len);
    
            for (int i = 0; i < rx_len && Wire.available(); i++)
            {
                rx[i] = Wire.read();
            }
        }
        return I2C_TEST_PASSED;
    }
    
    uint16 tas2563_write_reg(uint8 SlaveAddr, uint8 *regValue, uint16 count)
    {
        SlaveAddr = (SlaveAddr << 1) | WRITE_I2C;
        Serial.println("Writing");
        return PltI2cTransfer(SlaveAddr, regValue, count, 0, 0);
    }
    
    uint16 tas2563_read_reg(uint8 SlaveAddr, uint8 *regValue, uint16 count)
    {
        SlaveAddr = (SlaveAddr << 1) | READ_I2C;
        Serial.println("Reading");
        return PltI2cTransfer(SlaveAddr, 0, 0, regValue, count);
    }
    
    void tas2563_transmit_registers(uint8 SlaveAddr, cfg_reg *r, int n)
    {
        int i = 0;
        while (i < n)
        {
            switch (r[i].command)
            {
            case CFG_META_SWITCH:
                // Used in legacy applications. Ignored here.
                break;
            case CFG_META_DELAY:
                delay(r[i].param);
                break;
            case CFG_META_BURST:
                tas2563_write_reg(SlaveAddr, (unsigned char *)&r[i + 1], r[i].param);
                i += (r[i].param / 2) + 1;
                break;
            default:
                tas2563_write_reg(SlaveAddr, (unsigned char *)&r[i], 1);
                break;
            }
            i++;
        }
    }
    
    void tas2563_config_registers(uint8 SlaveAddr, uint8 id)
    {
        if (id == 1)
            tas2563_transmit_registers(SlaveAddr, power_down_reset, power_down_reset_size);
        if (id == 2)
            tas2563_transmit_registers(SlaveAddr, program, program_size);
        if (id == 3)
            tas2563_transmit_registers(SlaveAddr, configuration, configuration_size);
        if (id == 4)
            tas2563_transmit_registers(SlaveAddr, powerup, powerup_size);
        if (id == 5)
            tas2563_transmit_registers(SlaveAddr, unmute, unmute_size);
    }
    
    void amp_loop()
    {
        // nothing
    }


    此代码在回放之前、期间或之后没有显示 IRQZ 标志。 我应该查找哪些标志才能正确播放音频?

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

    更进一步的研究。  所有数据都正常、我认为它读取数据正常、因为不存在标志。 我认为这与电源有关。 如果我通过5V USB 线路为此芯片供电、正确的电源引脚配置是什么。 所有数据表和示例显示了连接到外部电池以便使用升压模式的 VBST 和 SW 引脚。 现在、我将这些引脚通过稳压器连接到3V3电源线。 IOVDD 通过稳压器连接到3V3稳压器、VDD 通过稳压器连接到1V8电源线。 这是我的原理图。 请注意、SDZ 引脚未连接、通过焊接连接来固定此引脚、以使芯片保持有效状态。 由于所有 I2C 通信都工作、因此该连接是有效的。

    I2C 地址选择是一个简单的2x4引脚接头、可以按预期工作。 扬声器上的 OUT 线使用2x4引脚接头来选择各种铁氧体磁珠滤波器。

    我已使用示波器查看 I2S 数据线、它们是否按预期工作。 芯片应正常接收 I2S 数据、这让我认为扬声器输出功率有问题。

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

    尊敬的 Halen:

    您是否也可以使用示波器检查输出引脚? 尝试播放音频时、您完全看到任何切换信号吗?  

    此致、
    伊万·萨拉扎尔
    应用工程师

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

    没有信号。 线路保持低电平。

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

    尊敬的 Halen:

    在两天前的代码中、我注意到寄存器0x02在不同位置设置为0x00、包括加电和取消静音例程。 我希望该寄存器仅针对取消静音设置为0x00、并针对其余设置保持在软件关断状态。

    我想知道器件如何无法输出任何内容、但仅触发这3个 IRQ 标志。 您是否在错误处理过程中执行了任何软件复位?

    从原理图上看、我唯一关心的是 C16和 C21、它们似乎直接连接在 D 类的输出端 优先在电感/电阻串联元件之后连接任何容性负载。

    此致、
    伊万·萨拉扎尔
    应用工程师

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

    该问题非常奇怪、即使没有 SW 电感器电路、放大器也不会输出任何内容。 设置为0x00的寄存器两次是从我之前提到的示例 MCU 集成和设置代码收集的、更改时没有任何效果。

    我对设置代码进行了一些小的更改、现在、IRQ 标志未触发。

    对于这些电容器、我可以移除它们、因为它们只是在扬声器之前作为快速滤波器、这也是从示例 PCB 布局数据表中提取的。 我没有看到他们在那里是没有音频播放的原因。

    下面有一个建议、如果 SDZ 引脚未激活芯片、它是否仍能响应 I2C 命令? 我的修复方法可能有问题、并且未正确保持芯片处于运行状态。 我想这是因为 I2C 命令仍然可以正常工作、但如果芯片可以在 SDZ 引脚悬空时使用 I2C、则可能是问题所在。

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

    尊敬的 Halen:

    我不希望 I2C 在 SDz 被下拉时做出响应、它实际上应该会复位器件寄存器。
    不管怎样、我都会仔细检查一下、并在周一早上返回结果。

    主机的数据输出连接到 TAS2563上的 SDIN 引脚、是否正确? SDOUT/SDIN 视图的命名有时会导致交换这些名称。

    此致、
    伊万·萨拉扎尔
    应用工程师

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

    谢谢你。 是的、我曾尝试切换 SDIN / SDOUT 引脚只是为了确定、现在仍然没有任何反应。

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

    尊敬的 Halen:

    我已经确认、只要下拉 SDz 引脚、器件就不会回复 I2C 事务。

    是否可以使用工作台电源进行测试? 这应该有助于排除可能的电源问题。

    此致、
    伊万·萨拉扎尔
    应用工程师

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

    使用工作台电源可得到相同的结果。 当器件播放时、不会有额外的电流消耗。 我认为板载电源调节可能有故障。 现在正在处理。