PlayBack

该示例实现将频率为 1KHz 的正弦波信号经 CODEC 编码,输出音频的功能。

利用 GDMAI2S 数据从内存搬运到 I2S 的发送 FIFO ,再通过 CODEC 编码为 PDM 信号。

外接 PDM 播放器,可以实现播放固定频率的正弦波语音。

环境需求

该示例的环境需求,可参考 环境需求

硬件连线

EVB 外接 PDM 播放器,连接 P4_3 和 CLK,P4_2 和 DATA。

编译和下载

该示例的编译和下载流程,可参考 编译和下载

测试验证

在 PDM 播放器中听到 1KHz 的正弦波声音。

代码介绍

该章节主要介绍示例中的初始化和相应功能实现的代码和流程说明。

源码路径

工程文件和源码路径如下:

  • 工程路径: sdk\samples\peripheral\codec\playback\proj

  • 源码路径: sdk\samples\peripheral\codec\playback\src

初始化

外设的初始化流程可参考 General Introduction 中的 初始化流程 部分。

初始化流程包括了 CODEC、UART、I2S、GDMA 模块的初始化,具体流程如下。

  1. 调用 Pad_Config()Pinmux_Config(), 配置 PDM 相关引脚对应引脚的 PAD 和 PINMUX。

    void board_codec_init(void)
    {
        Pad_Config(PDM_CLK_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE, PAD_OUT_LOW);
        Pad_Config(PDM_DAT_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE, PAD_OUT_LOW);
    
        Pinmux_Config(PDM_CLK_PIN, PDM_CLK);
        Pinmux_Config(PDM_DAT_PIN, PDM_DATA);
    }
    
  2. 调用 Pad_Config()Pinmux_Config() ,配置 I2S 相关引脚对应引脚的 PAD 和 PINMUX。

    void board_i2s_init(void)
    {
        Pad_Config(CODEC_BCLK_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE, PAD_OUT_LOW);
        Pad_Config(CODEC_LRCLK_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE,PAD_OUT_LOW);
        Pad_Config(CODEC_TX_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE, PAD_OUT_LOW);
        Pad_Config(CODEC_RX_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_ENABLE, PAD_OUT_LOW);
    
        Pinmux_Config(CODEC_BCLK_PIN, BCLK_SPORT0);
        Pinmux_Config(CODEC_LRCLK_PIN, LRC_SPORT0);
        Pinmux_Config(CODEC_TX_PIN,  DACDAT_SPORT0);
    }
    
  3. 执行 I2S_StructInit()I2S_Init() , 初始化 I2S 外设。I2S0 的初始化参数配置如下:

I2S master RX 初始化参数

I2S Hardware Parameters

Setting in the I2S_InitStruct

I2S master RX

Sample Rate (Mi)

I2S_InitTypeDef::I2S_RxBClockMi

0x271

Sample Rate (Ni)

I2S_InitTypeDef::I2S_RxBClockNi

0x10

Device Mode

I2S_InitTypeDef::I2S_DeviceMode

I2S_DeviceMode_Master

Channel Type

I2S_InitTypeDef::I2S_RxChannelType

I2S_Channel_stereo

Data Format

I2S_InitTypeDef::I2S_RxDataFormat

I2S_Mode

Data Width

I2S_InitTypeDef::I2S_RxDataWidth

I2S_Width_24Bits

  1. 执行 GDMA_StructInit()GDMA_Init(), 初始化 GDMA 外设。GDMA 的初始化参数配置如下:

GDMA 初始化参数

GDMA Hardware Parameters

Setting in the GDMA_InitStruct

GDMA Channel

Channel Num

GDMA_InitTypeDef::GDMA_ChannelNum

0

Transfer Direction

GDMA_InitTypeDef::GDMA_DIR

GDMA_DIR_MemoryToPeripheral

Source Address Increment or Decrement

GDMA_InitTypeDef::GDMA_SourceInc

DMA_SourceInc_Inc

Destination Address Increment or Decrement

GDMA_InitTypeDef::GDMA_DestinationInc

DMA_DestinationInc_Fix

Source Data Size

GDMA_InitTypeDef::GDMA_SourceDataSize

GDMA_DataSize_Word

Destination Data Size

GDMA_InitTypeDef::GDMA_DestinationDataSize

GDMA_DataSize_Word

Source Burst Transaction Length

GDMA_InitTypeDef::GDMA_SourceMsize

GDMA_Msize_4

Destination Burst Transaction Length

GDMA_InitTypeDef::GDMA_DestinationMsize

GDMA_Msize_4

Source Address

GDMA_InitTypeDef::GDMA_SourceAddr

codec_drv_cos_table

Destination Address

GDMA_InitTypeDef::GDMA_DestinationAddr

&(I2S0->I2S_TX_FIFO_WR_ADDR)

Destination Handshake

GDMA_InitTypeDef::GDMA_DestHandshake

GDMA_Handshake_I2S0_TDM0_TX

  1. 配置 GDMA 总传输完成中断 GDMA_INT_Transfer 和 NVIC, NVIC 相关配置可参考 中断配置

  2. 对 CODEC 外设的初始化。

    1. 调用 CODEC_AnalogCircuitInit() 初始化模拟电路。

    2. 调用 RCC_PeriphClockCmd() ,开启 CODEC 时钟。

    3. 执行 CODEC_StructInit()CODEC_Init(), 初始化 CODEC 外设。CODEC 的初始化参数配置如下:

CODEC 初始化参数

CODEC Hardware Parameters

Setting in the CODEC_InitStruct

CODEC

Da Mute

CODEC_InitTypeDef::CODEC_DaMute

CODEC_UNMUTE

Da Gain Mode

CODEC_InitTypeDef::CODEC_DaGain

0xAF

DaC Dither

CODEC_InitTypeDef::CODEC_DaC_Dither

DAC_DA_DITHER_DISABLE

I2S Data Format

CODEC_InitTypeDef::CODEC_I2SFormat

CODEC_I2S_DataFormat_I2S

I2S Channel Len

CODEC_InitTypeDef::CODEC_I2SChannelLen

I2S_CHANNELLEN_32

I2S Data Width

CODEC_InitTypeDef::CODEC_I2SRxDataWidth

CODEC_I2S_Tx_DataWidth_24Bits

I2S Channel Sequence

CODEC_InitTypeDef::CODEC_I2SChSequence

CODEC_I2S_CH_L_R

  1. 执行 preload_cos_table ,准备需要发送的正弦波数据。

  2. 调用 I2S_Cmd() ,使能 I2S 发送模式。调用 GDMA_Cmd(),使能 GDMA 传输。

功能实现

正弦波数据由 GDMA 从内存搬运到 I2S TX FIFO 中,经过 CODEC 的 DA 模块转换,外接 PDM 放大器后可听到音频。 数据在各个模块的传输顺序如下图所示。

这里应该是 PLAYBACK 波形图片

音频数据传输模块

  1. 当 GDMA 传输数据量达到设定的 BlockSize 时,会触发 GDMA_INT_Transfer 中断。在中断处理函数内重新设置源端地址,目的端地址和 BlockSize,并重新使能 GDMA 传输,以确保能够连续传输数据。

    GDMA_SetSourceAddress(CODEC_GDMA_Channel, (uint32_t)codec_drv_cos_table);
    GDMA_SetDestinationAddress(CODEC_GDMA_Channel, (uint32_t)(&(I2S0->I2S_TX_FIFO_WR_ADDR)));
    GDMA_SetBufferSize(CODEC_GDMA_Channel, CODEC_DRV_COS_TABLE_SAMPLE);
    GDMA_ClearINTPendingBit(CODEC_GDMA_Channel_NUM, GDMA_INT_Transfer);
    GDMA_Cmd(CODEC_GDMA_Channel_NUM, ENABLE);