[I2S]I2S多数据线同时使用介绍

一、先楫I2S多数据线介绍

先楫的I2S外设支持4条TXD和4条RXD数据线,使用1个I2S外设,即可同时与4个Codec传输音频数据。

注意: 因为共享数据格式配置寄存器,4个TXD和4个RXD数据线需要工作在相同的数据格式。

1.1 I2S外设结构框图

先楫产品I2S结构框图

1.2 I2S多数据线连接框图

二、实现I2S 4数据线同时使用

2.1 配置I2S外设

使用i2s_config_multiline_transferAPI进行多数据线收发,如下是配置I2S 4数据线TXD进行发送的配置示例。

/*
 * I2S主模式多数据线配置函数
 * 配置I2S 4数据线TXD进行发送
 */
void i2s_master_multiline_config(void)
{
    i2s_config_t i2s_config;
    i2s_multiline_transfer_config_t transfer;
    uint32_t i2s_mclk_hz;

    /* 配置I2S接口 */
    i2s_get_default_config(I2S_MASTER, &i2s_config);
    i2s_config.tx_fifo_threshold = I2S_TX_FIFO_THRESHOLD;  /* 设置发送FIFO阈值 */
    i2s_config.enable_mclk_out = true;                     /* 使能主时钟输出 */
    i2s_init(I2S_MASTER, &i2s_config);

    /* 配置I2S传输参数 */
    i2s_get_default_multiline_transfer_config(&transfer);
    transfer.sample_rate = audio_data.sample_rate;         /* 设置采样率 */
    transfer.channel_num_per_frame = 2;                    /* 每帧通道数 */
    transfer.audio_depth = audio_data.audio_depth;         /* 设置位深 */
    transfer.channel_length = i2s_channel_length_32_bits;  /* 通道长度 */
    transfer.master_mode = true;                           /* 主模式 */
    transfer.protocol = I2S_PROTOCOL_MSB_JUSTIFIED;        /* MSB对齐协议 */

    /* 使能4个发送数据线 */
    transfer.tx_data_line_en[0] = true;
    transfer.tx_data_line_en[1] = true;
    transfer.tx_data_line_en[2] = true;
    transfer.tx_data_line_en[3] = true;

    /* 配置通道槽掩码 */
    transfer.tx_channel_slot_mask[0] = (1 << audio_data.channel_num) - 1;
    transfer.tx_channel_slot_mask[1] = (1 << audio_data.channel_num) - 1;
    transfer.tx_channel_slot_mask[2] = (1 << audio_data.channel_num) - 1;
    transfer.tx_channel_slot_mask[3] = (1 << audio_data.channel_num) - 1;

    /* 配置I2S数据格式 */
    i2s_mclk_hz = clock_get_frequency(I2S_MASTER_CLOCK_NAME);
    if (status_success != i2s_config_multiline_transfer(I2S_MASTER, i2s_mclk_hz, &transfer)) {
        printf("I2S config failed!\n");
    }
}

2.2 音频数据搬运

需要连续将源数据写入I2S->TXD[0-3]寄存器实现音频发送。
需要连续从I2S->RXD[0-3]寄存器数据读出实现音频接收。

2.2.1 使用中断方式处理数据搬运

设置I2S的FIFO阈值,并使能对应中断,在中断服务函数中写入数据到I2S的发送寄存器TXD和从I2S的接收寄存器RXD读取数据。

可以适用于先楫支持I2S的全部系列

可以参考附件中的参考例程i2s_multiline_interrupt

2.2.2 使用DMA方式处理数据搬运

  • 在HPM6700/HPM6400/HPM6300/HPM6800系列中,I2S的多条数据线共享一个DMA请求,且这些平台上的DMA外设并不支持burst小循环,无法实现DMA同时为多个I2S数据线搬运数据。

    原因说明:例如想实现I2S 4个数据线的数据发送,由于DMA不支持burst小循环,需要使用4个DMA通道处理4个数据线的发送请求,这造成1个DMA请求要用于4个DMA通道,这是DMA不能不支持的使用情况。

  • 在HPM6E00系列,I2S的4条数据线还是共享一个DMA请求,但是其DMAv2外设支持Burst小循环,能够将I2S->TXD[0-3]或者I2S0->RXD[0-3]作为一个burst进行遍历,使用一个DMA通道就可以完成I2S4根数据线的发送任务或者接收任务。

    可以参考附件中的参考例程i2s_multiline_dmav2

  • 在HPM6P00系列,I2S的4条数据线有4个独立TX/RX DMA请求,这样可以使用4个DMA通道来处理4个I2S数据线的发送或接收任务。

    可以参考附件中的参考例程i2s_4_dma_req_multiline

参考例程和说明

附件i2s_multiline参考例程

例程同样可以在hpm_sdk_extra中获取,其网址:
github: github: hpm_sdk_extra
gitee: gitee: hpm_sdk_extra

参考例程是按照先楫HPM_SDK中的samples形式组织,可以使用相应工具构建工程,进行编译和测试。

由于先楫的EVK并未考虑I2S的4数据线使用情况,附件例程实现的I2S数据4数据线发送并不能在EVK上直接运行观察效果,需要自行设计板子,留出I2S 4数据线的接口,运行程序使用逻辑分析仪等工具测量I2S 4数据线的发送情况。

例程中的引脚需要按照实际板子进行修改:

void init_i2s_multiline_pin(void)
{
    /* 配置I2S引脚功能 */
    HPM_IOC->PAD[IOC_PAD_PB11].FUNC_CTL = IOC_PB11_FUNC_CTL_I2S0_MCLK;  /* 主时钟 */
    HPM_IOC->PAD[IOC_PAD_PB01].FUNC_CTL = IOC_PB01_FUNC_CTL_I2S0_BCLK;  /* 位时钟 */
    HPM_IOC->PAD[IOC_PAD_PB10].FUNC_CTL = IOC_PB10_FUNC_CTL_I2S0_FCLK;  /* 帧时钟 */
    HPM_IOC->PAD[IOC_PAD_PB00].FUNC_CTL = IOC_PB00_FUNC_CTL_I2S0_TXD_0; /* TX数据线0 */
    HPM_IOC->PAD[IOC_PAD_PB03].FUNC_CTL = IOC_PB03_FUNC_CTL_I2S0_TXD_1; /* TX数据线1 */
    HPM_IOC->PAD[IOC_PAD_PB05].FUNC_CTL = IOC_PB05_FUNC_CTL_I2S0_TXD_2; /* TX数据线2 */
    HPM_IOC->PAD[IOC_PAD_PB02].FUNC_CTL = IOC_PB02_FUNC_CTL_I2S0_TXD_3; /* TX数据线3 */
}

使用逻辑分析观察引脚信号:

0
0

订阅

发表回复 0

Your email address will not be published. Required fields are marked *