本帖最后由 小马哥-1650185 于 2017-7-4 12:11 编辑
本周任务主要是音频相关的,这一贴,我们就先了解认识下音频的相关的知识,研究探索下DMIC&HWVAD,先来看下我们的开发板,与音频相关的模块有:
1.一个 PDM 数字麦克风(SPH0641LM4H)------对应板子上的U7
2.一个支持 I2S 音频输入/输出接口(WM8904)-------对应板子上的CN7(Ao:音频输出)和CN8(Ai:音频输入)
本帖主要来说说数字麦克风吧,在这之前,你应该知道下我们能够听到的声音频率在20HZ~20kHz之间,低于这个范围的是次声波,高于的是超声波。
下面就切入正题吧。。。
(本帖前半部分主要说下demo历程,后半部分是重难点,分析DMIC和HWVADX工作机制)
为了搞明白原理,小马哥也是咬文嚼字的把文档一字一字的嚼了一遍,童鞋们,多支持下,投个票吧,投1号小马哥哦!!!
首先我们来看下板子上用到的数字麦克(SPH0641LM4H)
sph0641lu4h 是一个微型、高性能、低功耗的数字麦克风,有一个比特PDM输出。包括一个声传感器、一个低噪声输入缓冲器和一个sigma- delta调制器,支持双复用通道,到达64db的信噪比,有多种性能模式(睡眠、低功耗、标准和超声模式。)
其工作状态图如下,可以看出,工作模式是根据时钟频率划分的。
时序图
引脚定义
以上就是数字麦克风 中 我们需要知道的东西。下面来看下54114的DMIC子系统吧 ------------------------------------------------------------------------ 54114的DMIC子系统包括双通道数字PDM麦克风接口 (DMIC)和硬件声音活动检测器(HWVAD)。
DMIC接口 主要是讲接收到来自 数字麦克风的PDM数据,转换成24位 可以 被CPU或DMA读取,或者发送到I2S接口输出的PCM数据。
PDM有2个通道(左、右),可以无需唤醒CPU ,使用DMA 从深度睡眠模式发送数据,然后自动返回深度睡眠模式,数据可直接到通讯接口7 的I2S总线.HWVAD用 16 kHz 采样率优化PCM信号. PDM引脚定义
知道了上面的基础知识,现在研究下板子上面的麦克吧。 看原理图,发现dmic接口复用的FUNC1即:
然后就需要把这两个接口配置下喽 - /* PDM interface */
- IOCON_PinMuxSet(IOCON, 1, 15, IOCON_FUNC1 | IOCON_DIGITAL_EN); /* PDM CLK 0 */
- IOCON_PinMuxSet(IOCON, 1, 16, IOCON_FUNC1 | IOCON_DIGITAL_EN); /* PDM DATA 0 */
复制代码初始化DMIC时钟为12MHZ,PDM 15分频后为800Khz 这里出于能耗的原因,在DMIC接口块之外完成所需的DMIC时钟配置,这里就是在SYSCON块中使用DMICCLKDIV。 - CLOCK_AttachClk(kFRO12M_to_DMIC);
- CLOCK_SetClkDiv(kCLOCK_DivDmicClk, 14, false);//(14+1)·分频
复制代码接下来就是配置dmic结构体,初始化dmic,hwvad
ps:HWVAD设置启动流程,后文有详解。。。
(注:DMIC_Use2fs(DMIC0, true);//pcm数据从2fs输出,可以将需要的DMIC时钟减少2倍,降低功耗。)
配置完成后,当硬件声音活动检测器 检测到信号时,触发HWVAD0中断,进入相应的中断服务函数,LED9 翻转,并打印信息。
分析:
一旦HWVAD触发了中断,必须给寄存器 ST10 写 1 , 手动清除中断标志位,然后写 0 进入正常模式,等下下一次中断的触发。
ps:这里加延时 是为了产生一个高电平脉冲 来复位中断标志位,下面有详解。。。。
- void DMIC0_HWVAD_Callback(void)
- {
- volatile int i;
- PRINTF("HWVAD触发中断---LED9 BLIND-------\r\n\r\n");
- led_toggle(3);
- /* reset hwvad internal interrupt */
- DMIC_CtrlClrIntrHwvad(DMIC0, true);
- /* wait for HWVAD to settle */
- for (i = 0; i <= 500U; i++)
- {
-
- }
- /*HWVAD Normal operation */
- DMIC_CtrlClrIntrHwvad(DMIC0, false);
- led_toggle(3);
- PRINTF("\r\n-------------\r\n");
- }
复制代码从下图 可以看到 检测到声响,震动等 时候,程序进入hwvad中断,并向串口打印信息
/////////////////////////////////思路分析篇章////////////////////
HWVAD:
硬件语音活动检测器(HWVAD)通过一个过滤器块来分析DMIC通道0的PCM数据。通过分析噪声层和信号波,产生了不同的滤波器输出。当信号和噪声结果被检测到时,就会触发HWVAD中断。
其中:
1.信号滤波器输出的增益(HWVADTHGS)和噪声滤波器输出的增益(HWVADTHGN)可以根据不同的声音,独立设置。
2.16位PCM输入信号可以在寄存器hwvad增益的增益设置中向左或向右移动。这增加或减少了HWVAD处理的输入信号的容量。请注意,重置值0x05等于1的增益系数,信号没有向任何方向移动。
3.增益因子( [z8 * (THGS+1)] > [z7 * (THGN+1)] )决定了信号与噪声的比例。
分析:
ST10寄存器:
中断到来时,中断标志位拉高,这时候进入中断后必须清除这个中断标志位,通过ST10寄存器的一个短的上升沿脉冲,也就是ST10=1,需要持续一会,在拉低,进入正常模式,等待下一次触发。。。这里就解释了,前面中断服务函数里面那个for循环延时的原因了。。。
RSTT寄存器:可以复位所有的探测滤波器,复位后,滤波器需要收敛,所以在这个过程中,采集的数据不不稳定的,所以,中断向量表中的HWVAD中断应该被屏蔽掉,也就是需要把ST10寄存器拉高一段时间,demo中的PDM时钟微微800khz,延时2.5ms就可以了,这就解释了初始化识货的那个for循环延时了。。。
HWVAD完整的启动设置顺序如下:
1.通过RSTT 位复位探测器,并且延时一会,等到滤波器收敛到信号探测条件
2.通过ST10位拉高来清除在过滤器不稳定的时候 产生的虚假中断 。(虚线所示)
3.使能HWVAD中断核中断向量等级
4.通过ST10拉高产生 的脉冲 ,清除中断标志位,并等待处理下一次中断。
通过流程分析,就可以明白初始化中最后面的代码了。。。
再看下代码对号入座吧。。。。
- DisableDeepSleepIRQ(HWVAD0_IRQn);
- DMIC_HwvadEnableIntCallback(DMIC0, DMIC0_HWVAD_Callback);
- DMIC_EnableChannnel(DMIC0, (DMIC_CHANEN_EN_CH0(1) | DMIC_CHANEN_EN_CH1(1)));
- /* reset hwvad internal interrupt */
- DMIC_CtrlClrIntrHwvad(DMIC0, true);
- /* To clear first spurious interrupt */
- for (i = 0; i < 0xFFFFU; i++)
- {
- }
- /*HWVAD Normal operation */
- DMIC_CtrlClrIntrHwvad(DMIC0, false);
- NVIC_ClearPendingIRQ(HWVAD0_IRQn);
- EnableDeepSleepIRQ(HWVAD0_IRQn);
复制代码
DMCI:
DMIC接口 主要是讲接收到来自 数字麦克风的PDM数据,转换成24位 可以 被CPU或DMA读取,或者发送到I2S接口输出的PCM数据。
处理机制如下图
PDC-------->PCM:
PDM到PCM转换块的设计是为PCM输出信号提供最好的结果,以16khz的采样率,覆盖在通信系统中广泛使用的增强的8 kHz语音波段。
DMIC时钟频率与PCM音频采样率之间的关系是:
FIFO & DMA:
DMIC接口的16位宽的FIFO由两个通道,每个通道由的16个条目组成。如果不使用DMA的操作,可以启用DMIC FIFO中断,通知ARM核心FIFO的状态。
为了搞明白原理,小马哥也是咬文嚼字的把文档一字一字的嚼了一遍,童鞋们,多支持下,投个票吧,投1号小马哥哦!!!
|