PlayBack

实现将频率为1KHz的正弦波信号经CODEC编码,输出音频的功能。 利用GDMA将I2S数据从内存搬运到I2S0的发送FIFO,再通过CODEC编码为PDM信号。 外接PDM播放器,可以实现播放固定频率的正弦波语音。

环境需求

该示例支持以下开发套件:

开发套件

Hardware Platforms

Board Name

RTL87x2G HDK

RTL87x2G EVB

更多信息请参考 快速入门

硬件连线

EVB外接录音播放模块,连接P4_3和CLK,P4_2和DATA。

编译和下载

该示例的工程路径如下:

Project file: samples\peripheral\codec\playback\proj\rtl87x2g\mdk

Project file: samples\peripheral\codec\playback\proj\rtl87x2g\gcc

请按照以下步骤操作构建并运行该示例:

  1. 打开工程文件。

  2. 按照 快速入门编译APP Image 给出的步骤构建目标文件。

  3. 编译成功后,在路径 mdk\bingcc\bin 下会生成 app bin app_MP_xxx.bin 文件。

  4. 按照 快速入门MPTool 给出的步骤将app bin烧录至EVB内。

  5. 按下复位按键,开始运行。

测试验证

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

代码介绍

该章节分为以下几个部分:

  1. 源码路径

  2. 初始化函数将在 初始化 章节介绍。

  3. 初始化后的功能实现将在 功能实现 章节介绍。

源码路径

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

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

该工程的工程文件代码结构如下:

└── Project: playback
    └── secure_only_app
        └── Device                   includes startup code
            ├── startup_rtl.c
            └── system_rtl.c
        ├── CMSIS                    includes CMSIS header files
        ├── CMSE Library             Non-secure callable lib
        ├── Lib                      includes all binary symbol files that user application is built on
            └── rtl87x2g_io.lib
        ├── Peripheral               includes all peripheral drivers and module code used by the application
            ├── rtl_rcc.c
            ├── rtl_pinmux.c
            ├── rtl_gdma.c
            ├── rtl_nvic.c
            ├── rtl_codec.c
            └── rtl_i2s.c
        └── APP                      includes the ble_peripheral user application implementation
            ├── main_ns.c
            └── io_codec.c

初始化

初始化流程包括了codec、uart、i2s 、gdma 模块的初始化,具体流程如下。


board_codec_init 包含了PDM相关引脚的对PAD和PINMUX的设置。

  1. 配置PAD:设置引脚、PINMUX模式、PowerOn、无内部上拉。

  2. 配置PINMUX:分配引脚分别为PDM_CLK、PDM_DATA功能。


board_i2s_init 包含了对I2S相关引脚的对PAD和PINMUX的设置。

  1. 配置PAD:设置引脚、PINMUX模式、PowerOn、无内部上拉。

  2. 配置PINMUX:分配引脚分别为BCLK_SPORT0、LRC_SPORT0、DACDAT_SPORT0功能。


driver_i2s_init 包含了对I2S外设的初始化。

  1. 使能PCC时钟。

  2. 设置I2S位时钟位16kHz。

  3. 设置为主设备模式,双声道输出,数据格式为I2S模式。

  4. 设置数据宽度为24bits,通道宽度位32bits。


driver_gdma_init 包含了对GDMA外设的初始化。

  1. 使能PCC时钟。

  2. 使用GDMA通道0。

  3. GDMA的传输方向为 内存外设 传输。

  4. 源端地址为 codec_drv_cos_table ,目的端地址为 (&(I2S0->I2S_TX_FIFO_WR_ADDR)

  5. 使能GDMA通道0总传输完成中断 GDMA_INT_Transfer


driver_codec_init 包含了对CODEC外设的初始化。

  1. 使能PCC时钟。

  2. 初始化CODEC模拟电路相关的配置。

  3. 设置播放模式为非静音模式。

  4. 设置播放增益。

  5. 设置DAC噪声处理为不处理。

  6. 设置数据格式为I2S格式。

  7. 设置通道长度、数据宽度、通道顺序。

RCC_PeriphClockCmd(APBPeriph_CODEC, APBPeriph_CODEC_CLOCK, ENABLE);
CODEC_AnalogCircuitInit();
...
CODEC_InitStruct.CODEC_DaMute = CODEC_UNMUTE;
CODEC_InitStruct.CODEC_DaGain = 0xAF;
CODEC_InitStruct.CODEC_DaC_Dither = DAC_DA_DITHER_DISABLE;
CODEC_InitStruct.CODEC_I2SFormat = CODEC_I2S_DataFormat_I2S;
CODEC_InitStruct.CODEC_I2SChannelLen = I2S_CHANNELLEN_32;
CODEC_InitStruct.CODEC_I2STxDataWidth = CODEC_I2S_Tx_DataWidth_24Bits;
CODEC_InitStruct.CODEC_I2SChSequence = CODEC_I2S_CH_L_R;

功能实现

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

  2. 使能I2S发送模式;使能GDMA通道0。

I2S_Cmd(I2S0, I2S_MODE_TX, ENABLE);
GDMA_Cmd(GDMA_Channel_AMIC_NUM, ENABLE);
  1. 利用GDMA将正弦波数据搬运到I2S0发送FIFO;当数据传输完成时,触发 GDMA_INT_Transfer 中断,进入中断处理函数 CODEC_GDMA_Channel_Handler

    1. 重新设置源端地址和目的端地址。

    2. 重新设置GDMA传输数据大小。

    3. 清除GDMA通道0 GDMA_INT_Transfer 中断挂起位,使能GDMA通道0。

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);