Digital Microphone
本示例实现DMIC采集数字语音经CODEC解码的功能。
DMIC采集数字语音数据,经CODEC编码,送到 I2S 接收FIFO,利用 DMA 将数据搬运到 UART 。
PC端收到UART传输的数据,使用音频解析软件解析数据,并播放录制的语音。
环境需求
该示例支持以下开发套件:
Hardware Platforms |
Board Name |
---|---|
RTL87x2G HDK |
RTL87x2G EVB |
更多信息请参考快速入门。
硬件连线
EVB外接DMIC模块,连接P2_2和CLK,P2_3和DATA。
EVB外接FT232模块,连接P3_2和RX,P3_3和TX。
编译和下载
该示例的工程路径如下:
Project file: samples\peripheral\codec\dmic\proj\rtl87x2g\mdk
Project file: samples\peripheral\codec\dmic\proj\rtl87x2g\gcc
请按照以下步骤操作构建并运行该示例:
打开工程文件。
按照 快速入门 中 编译APP Image 给出的步骤构建目标文件。
编译成功后,在路径
mdk\bin
或gcc\bin
下会生成 app binapp_MP_xxx.bin
文件。按下复位按键,开始运行。
测试验证
准备阶段
启动 PuTTY 或 UartAssist 等PC终端,连接到使用的COM端口,并进行以下UART设置:
波特率: 3000000
8 数据位
1 停止位
无校验
无硬件流控
启动音频解析软件。
测试阶段
开始录音到录音完成,采集到的语音数据,解码后通过UART发送到PC终端。
从PC终端复制解码数据到新建HEX bin文档中。
使用音频解析软件查看解码后的语音波形,也可以播放语音。
代码介绍
该章节分为以下几个部分:
源码路径
工程路径:
sdk\samples\peripheral\codec\dmic\proj
源码路径:
sdk\samples\peripheral\codec\dmic\src
该工程的工程文件代码结构如下:
└── Project: dmic
└── 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_uart.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
包含了CODEC和DMIC相关引脚的对PAD和PINMUX的设置。
配置PAD:设置引脚、PINMUX模式、PowerOn、无内部上拉。
配置PINMUX:分配引脚分别为DMIC1_CLK、DMIC1_DAT、BCLK_SPORT0、LRC_RX_SPORT0、SDI_CODEC_SLAVE、SDO_CODEC_SLAVE功能。
Pad_Config(DMIC_MSBC_CLK_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE,
PAD_OUT_LOW);
Pad_Config(DMIC_MSBC_DAT_PIN, PAD_PINMUX_MODE, PAD_IS_PWRON, PAD_PULL_NONE, PAD_OUT_DISABLE,
PAD_OUT_LOW);
Pinmux_Config(DMIC_MSBC_CLK_PIN, DMIC1_CLK);
Pinmux_Config(DMIC_MSBC_DAT_PIN, DMIC1_DAT);
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_RX_SPORT0);
Pinmux_Config(CODEC_TX_PIN, SDI_CODEC_SLAVE);
Pinmux_Config(CODEC_RX_PIN, SDO_CODEC_SLAVE);
board_uart_init
包含了UART相关引脚的PAD和PINMUX的设置,参照 amic初始化。
driver_i2s_init
包含了对I2S外设的初始化,参照 amic初始化。
driver_uart_init
包含了对UART外设的初始化,参照 amic初始化。
driver_gdma_init
包含了对DMA外设的初始化,参照 amic初始化。
driver_codec_init
包含了对CODEC外设的初始化。
使能PCC时钟。
麦克风类型选择DMIC。
设置DMIC时钟频率为2500kHz。
设置通道0数字麦克风的数据锁存方式为上升沿锁存。
设置采样频率为16kHz。
设置数据格式为I2S格式。
设置通道宽度为32位。
设置RX数据宽度为16位。
设置I2S通道顺序为左右。
RCC_PeriphClockCmd(APBPeriph_CODEC, APBPeriph_CODEC_CLOCK, ENABLE);
...
CODEC_InitStruct.CODEC_Ch0MicType = CODEC_CH_DMIC;
CODEC_InitStruct.CODEC_DmicClock = DMIC_Clock_2500KHz;
CODEC_InitStruct.CODEC_Ch0DmicDataLatch = DMIC_Ch_Rising_Latch;
CODEC_InitStruct.CODEC_SampleRate0 = SAMPLE_RATE_16KHz;
CODEC_InitStruct.CODEC_I2SFormat = CODEC_I2S_DataFormat_I2S;
CODEC_InitStruct.CODEC_I2SChannelLen = I2S_CHANNELLEN_32;
CODEC_InitStruct.CODEC_I2SRxDataWidth = CODEC_I2S_Rx_DataWidth_16Bits;
CODEC_InitStruct.CODEC_I2SChSequence = CODEC_I2S_CH_L_R;
功能实现
使能I2S发送模式和接收模式;使能GDMA通道0。
I2S_Cmd(I2S0, I2S_MODE_TX | I2S_MODE_RX, ENABLE);
GDMA_Cmd(GDMA_Channel_AMIC_NUM, ENABLE);
DMIC采集到模拟语音数据,经CODEC解码,送到I2S0接收FIFO,利用GDMA将数据搬运到UART5;当数据传输完成时,触发
GDMA_INT_Transfer
中断,进入中断处理函数GDMA_Channel_DMIC_Handler
。重新设置源端地址和目的端地址。
重新设置GDMA传输数据大小。
清除GDMA通道0
GDMA_INT_Transfer
中断挂起位,使能GDMA通道0。
GDMA_SetSourceAddress(GDMA_Channel_DMIC, (uint32_t)(&(I2S0->I2S_RX_FIFO_RD_ADDR)));
GDMA_SetDestinationAddress(GDMA_Channel_DMIC, (uint32_t)(&(UART5->UART_RBR_THR)));
GDMA_SetBufferSize(GDMA_Channel_DMIC, AUDIO_FRAME_SIZE / 4);
GDMA_ClearINTPendingBit(GDMA_Channel_DMIC_NUM, GDMA_INT_Transfer);
GDMA_Cmd(GDMA_Channel_DMIC_NUM, ENABLE);