PlayBack
该示例实现将频率为1KHz的正弦波信号经CODEC编码,输出音频的功能。
利用 DMA 将 I2S 数据从内存搬运到I2S的发送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
请按照以下步骤操作构建并运行该示例:
打开工程文件。
按照 快速入门 中 编译APP Image 给出的步骤构建目标文件。
编译成功后,在路径
mdk\bin
或gcc\bin
下会生成 app binapp_MP_xxx.bin
文件。按下复位按键,开始运行。
测试验证
在PDM播放器中听到1KHz的正弦波声音。
代码介绍
该章节分为以下几个部分:
源码路径
工程路径:
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、DMA模块的初始化,具体流程如下。
board_codec_init
包含了PDM相关引脚的对PAD和PINMUX的设置。
配置PAD:设置引脚、PINMUX模式、PowerOn、无内部上拉。
配置PINMUX:分配引脚分别为PDM_CLK、PDM_DATA功能。
board_i2s_init
包含了对I2S相关引脚的对PAD和PINMUX的设置。
配置PAD:设置引脚、PINMUX模式、PowerOn、无内部上拉。
配置PINMUX:分配引脚分别为BCLK_SPORT0、LRC_SPORT0、DACDAT_SPORT0功能。
driver_i2s_init
包含了对I2S外设的初始化。
使能PCC时钟。
设置I2S位时钟位16kHz。
设置为主设备模式,双声道输出,数据格式为I2S模式。
设置数据宽度为24bits,通道宽度位32bits。
driver_gdma_init
包含了对GDMA外设的初始化。
使能PCC时钟。
使用GDMA通道0。
GDMA的传输方向为内存到外设传输。
源端地址为
codec_drv_cos_table
,目的端地址为(&(I2S0->I2S_TX_FIFO_WR_ADDR)
。使能GDMA通道0总传输完成中断
GDMA_INT_Transfer
。
driver_codec_init
包含了对CODEC外设的初始化。
使能PCC时钟。
初始化CODEC模拟电路相关的配置。
设置播放模式为非静音模式。
设置播放增益。
设置DAC噪声处理为不处理。
设置数据格式为I2S格式。
设置通道长度、数据宽度、通道顺序。
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;
功能实现
执行
preload_cos_table
,准备需要发送的正弦波数据。使能I2S发送模式;使能GDMA通道0。
I2S_Cmd(I2S0, I2S_MODE_TX, ENABLE);
GDMA_Cmd(GDMA_Channel_AMIC_NUM, ENABLE);
利用GDMA将正弦波数据搬运到I2S0发送FIFO;当数据传输完成时,触发
GDMA_INT_Transfer
中断,进入中断处理函数CODEC_GDMA_Channel_Handler
。重新设置源端地址和目的端地址。
重新设置GDMA传输数据大小。
清除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);