在线时间828 小时
UID3079326
注册时间2015-2-11
NXP金币12
TA的每日心情 | 郁闷 2022-4-4 11:28 |
---|
签到天数: 351 天 [LV.8]以坛为家I
金牌会员
- 积分
- 5740
- 最后登录
- 2022-4-4
|
本帖最后由 wambob 于 2017-4-24 17:33 编辑
1.数字麦克风。
声音在自然界无处不在。物理学上描述为一种振动波,频率在20HZ~20kHz之间的声波,人耳可以听到。为了记录美妙的声音,无论是模拟还是数字,都需要一个采集声音的传感器。
数字麦克风,既然称数字,输出的信号就是是数字了。
特性:
.64dB的高信噪比。
.低功耗模式低电流为235uA
.多种模式(睡眠、低功耗、标准和超声模式)
.平坦的频率响应
.RF隔离
.0高度麦克风
.支持双复用通道
.标准的SMD回流焊
.全方向
.超声支持
.灵敏度匹配
.小尺寸
其工作状态图:
从图中可以看出,改变时钟频率在某个范围,就改变了工作模式。
电路原理图
时序图
其输出的数据是1bit PDM格式的数字数据,用软件处理起来比较麻烦。LPC54114片上提供了DMIC子系统,可以通过配置寄存器将PDM(Pulse-Density Modulation) 数据转换成PCM(Pulse Code Modulation)数据,经I2S总线传送到解码器,播放声音。
2.DMIC子系统
包括双通道数字PDM麦克风接口和硬件声音活动检测器(HWVAD)。
• DMIC (双/立体声数字麦克风接口)
– PDM (Pulse-Density Modulation) 数据输入
– 灵活的抽取.
– 每通道16 个 FIFO
– 可选DC blocking
– 无需唤醒CPU ,使用DMA 从深度睡眠模式发送数据,然后自动返回深度睡眠模式.
– 数据可直接到通讯接口7 I2S.
• HWVAD (基于硬件的声音检测器):
– 用 16 kHz 采样率优化PCM信号.
– 可配置检测水平.
– 噪声包络估计寄存器输出进一步软件分析
3.例程中DMIC的初始化代码
- uint8_t dmic_init(void)
- {
- uint8_t ret = 0;
- uint32_t i = 0;
- dmic_channel_config_t dmic_channel_cfg;
-
- /* 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 uses 12MHz FRO clock */
- CLOCK_AttachClk(kFRO12M_to_DMIC);
- /*12MHz divided by 15 = 800KHz PDM clock */
- CLOCK_SetClkDiv(kCLOCK_DivDmicClk, 15, false);
- dmic_channel_cfg.divhfclk = kDMIC_PdmDiv1;
- dmic_channel_cfg.osr = 25U;
- dmic_channel_cfg.gainshft = 3U;
- dmic_channel_cfg.preac2coef = kDMIC_CompValueZero;
- dmic_channel_cfg.preac4coef = kDMIC_CompValueZero;
- dmic_channel_cfg.dc_cut_level = kDMIC_DcCut155;
- dmic_channel_cfg.post_dc_gain_reduce = 0U;
- dmic_channel_cfg.saturate16bit = 1U;
- dmic_channel_cfg.sample_rate = kDMIC_PhyFullSpeed;
- DMIC_Init(DMIC0);
-
- DMIC_ConfigIO(DMIC0, kDMIC_PdmStereo);
- DMIC_Use2fs(DMIC0, true);
- DMIC_SetOperationMode(DMIC0, kDMIC_OperationModeInterrupt);
- DMIC_ConfigChannel(DMIC0, kDMIC_Channel0, kDMIC_Left, &dmic_channel_cfg);
- DMIC_ConfigChannel(DMIC0, kDMIC_Channel1, kDMIC_Right, &dmic_channel_cfg);
- DMIC_FifoChannel(DMIC0, kDMIC_Channel0, FIFO_DEPTH, true, true);
- DMIC_FifoChannel(DMIC0, kDMIC_Channel1, FIFO_DEPTH, true, true);
-
- /*Gain of the noise estimator */
- DMIC_SetGainNoiseEstHwvad(DMIC0, 0x02U);
- /*Gain of the signal estimator */
- DMIC_SetGainSignalEstHwvad(DMIC0, 0x01U);
- /* 00 = first filter by-pass, 01 = hpf_shifter=1, 10 = hpf_shifter=4 */
- DMIC_SetFilterCtrlHwvad(DMIC0, 0x01U);
- /*input right-shift of (GAIN x 2 -10) bits (from -10bits (0000) to +14bits (1100)) */
- DMIC_SetInputGainHwvad(DMIC0, 0x04U);
- 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);
- ret = 1;
-
- return ret;
- }
复制代码 首先定义了一个DMIC通道配置变量,这是一个结构体类型,结构成员包括DMIC 时钟预分频值、过采样率、4FS PCM增益控制、2FS预加重滤波器系数值、4FS预加重滤波器系数值、DMIC DC滤波器控制值、增益调整、DMIC和抽取器采样率、16bit饱和度状态。
- typedef struct _dmic_channel_config
- {
- pdm_div_t divhfclk; /*!< DMIC Clock pre-divider values */
- uint32_t osr; /*!< oversampling rate(CIC decimation rate) for PCM */
- int32_t gainshft; /*!< 4FS PCM data gain control */
- compensation_t preac2coef; /*!< Pre-emphasis Filter coefficient value for 2FS */
- compensation_t preac4coef; /*!< Pre-emphasis Filter coefficient value for 4FS */
- dc_removal_t dc_cut_level; /*!< DMIC DC filter control values. */
- uint32_t post_dc_gain_reduce; /*!< Fine gain adjustment in the form of a number of bits to downshift */
- dmic_phy_sample_rate_t sample_rate; /*!< DMIC and decimator sample rates */
- bool saturate16bit; /*!< Selects 16-bit saturation. 0 means results roll over if out range and do not saturate.
- 1 means if the result overflows, it saturates at 0xFFFF for positive overflow and
- 0x8000 for negative overflow.*/
- } dmic_channel_config_t;
复制代码 接着初始化了两个管脚PIO1口测15、16管脚复用功能1,并且数字输出。
接着配置时钟。
- CLOCK_AttachClk(kFRO12M_to_DMIC);
复制代码 参数是个枚举类型的,元素值为MUX_A(CM_DMICCLKSEL, 0),其中#define CM_DMICCLKSEL 27 #define MUX_A(m, choice) (((m) << 0) | ((choice + 1) << 8))
展开为0x11B。
- void CLOCK_AttachClk(clock_attach_id_t connection)
- {
- bool final_descriptor = false;
- uint8_t mux;
- uint8_t pos;
- uint32_t i;
- volatile uint32_t *pClkSel;
- pClkSel = &(SYSCON->MAINCLKSELA);
- for (i = 0U; (i <= 2U) && (!final_descriptor); i++)
- {
- connection = (clock_attach_id_t)(connection >> (i * 12U)); /* pick up next descriptor */
- mux = (uint8_t)connection;
- if (connection)
- {
- pos = ((connection & 0xf00U) >> 8U) - 1U;
- if (mux == CM_ASYNCAPB)
- {
- ASYNC_SYSCON->ASYNCAPBCLKSELA = pos;
- }
- else
- {
- pClkSel[mux] = pos;
- }
- }
- else
- {
- final_descriptor = true;
- }
- }
- }
复制代码 i=0时。
往下为时钟分频 ,参数(42,14,false)
- void CLOCK_SetClkDiv(clock_div_name_t div_name, uint32_t divided_by_value, bool reset)
- {
- volatile uint32_t *pClkDiv;
- pClkDiv = &(SYSCON->SYSTICKCLKDIV);
- if (reset)
- {
- pClkDiv[div_name] = 1U << 29U;
- }
- if (divided_by_value == 0U) /* halt */
- {
- pClkDiv[div_name] = 1U << 30U;
- }
- else
- {
- pClkDiv[div_name] = (divided_by_value - 1U);
- }
- }
复制代码 算出来的值为为13,即0x0D (1101b),给寄存器赋值,如何为15分频?而不是12分频呢?
接着初始化了DMIC0。
- void DMIC_Init(DMIC_Type *base)
- {
- assert(base);
- /* Enable the clock to the register interface */
- CLOCK_EnableClock(s_dmicClock[DMIC_GetInstance(base)]);
- /* Reset the peripheral */
- RESET_PeripheralReset(kDMIC_RST_SHIFT_RSTn);
- /* Disable DMA request*/
- base->CHANNEL[0].FIFO_CTRL &= ~DMIC_CHANNEL_FIFO_CTRL_DMAEN(1);
- base->CHANNEL[1].FIFO_CTRL &= ~DMIC_CHANNEL_FIFO_CTRL_DMAEN(1);
- /* Disable DMIC interrupt. */
- base->CHANNEL[0].FIFO_CTRL &= ~DMIC_CHANNEL_FIFO_CTRL_INTEN(1);
- base->CHANNEL[1].FIFO_CTRL &= ~DMIC_CHANNEL_FIFO_CTRL_INTEN(1);
- }
复制代码 使能了AHB时钟
三个复位。
在初始化后,配置DMIC的一些设置、双通道、2FS、传输模式、FIFO。
往下是一些HWVAD的一些设置。
总结,例程有问题,只好一步步分析,解决例程麦克风没声音的问题。首先要注意DMIC数据输出的三种工作模式方式
- typedef enum _operation_mode
- {
- kDMIC_OperationModePoll = 0U, /*!< Polling mode */
- kDMIC_OperationModeInterrupt = 1U, /*!< Interrupt mode */
- kDMIC_OperationModeDma = 2U, /*!< DMA mode */
- } operation_mode_t;
复制代码 原例程里使用中断方式,但在解码器中使用DMA模式。存在问题。
|
|