【CY8CKIT-062S2-AI 测评】--MIC拾音
本帖最后由 dirty123 于 2025-11-23 11:29 编辑本篇实现MICMIC拾音功能。
一.硬件原理
开发板板载两个PDM(脉冲密度调制)微型数字麦克风,在开发板背面边角侧。引脚有PDM_CLK时钟脚和PDM_DATA数字脚,硬件原理如下
此麦克风使用到PDM (脉冲密度调制)和PCM (脉冲编码调制)。PDM信号是高速的单比特流,无法被传统的音频处理器(DSP)或软件直接识别和处理,因此需要转换为标准的PCM格式。PCM作为数字音频领域的绝对标准,几乎所有软件、硬件和文件格式(如WAV、FLAC)都直接支持PCM数据,便于进行滤波、混音、均衡器等复杂的数字信号处理。这个过程本质上是数字信号处理中的采样率转换和数据重构,核心步骤有两步:
采样率转换(抽取 - Decimation)
目的是将极高的PDM采样率(如3.072 MHz)降低到标准PCM采样率(如48 kHz)。这个降低的比率称为“抽取因子”,例如从3.072 MHz到48 kHz的抽取因子是64:1。直接简单地丢弃样本会造成严重的信号失真,因此必须配合第二步的滤波操作。
低通滤波与噪声整形
这是转换的核心。PDM信号中包含的大量高频量化噪声必须被滤除。转换过程通常使用一种高效的CIC(级联积分梳状)滤波器 来实现
。该滤波器会计算一小段时间窗口(例如64个PDM时钟周期)内“1”的密度,并将这个密度值转换成一个多比特的幅度值输出。这样,既完成了数据的转换,也将大部分高频噪声滤除了。
PDM侧重于高效率的模数转换和传输,PCM侧重于通用的处理和兼容性。
二.工程代码准备
1.创建工程
选择外设里音频PDM PCM Audio,如下
2.VSCode创建的工程如下
3.工程代码梳理
1.宏定义与按键事件
(1)参数阈值引脚等宏定义
/*******************************************************************************
* Macros
********************************************************************************/
/* Define how many samples in a frame */
#define FRAME_SIZE (1024)
/* Noise threshold hysteresis */
#define THRESHOLD_HYSTERESIS 3u
/* Volume ratio for noise and print purposes */
#define VOLUME_RATIO (4*FRAME_SIZE)
/* Desired sample rate. Typical values: 8/16/22.05/32/44.1/48kHz */
#define SAMPLE_RATE_HZ 8000u
/* Decimation Rate of the PDM/PCM block. Typical value is 64 */
#define DECIMATION_RATE 64u
/* Audio Subsystem Clock. Typical values depends on the desire sample rate:
- 8/16/48kHz : 24.576 MHz
- 22.05/44.1kHz : 22.579 MHz */
#define AUDIO_SYS_CLOCK_HZ 24576000u
/* PDM/PCM Pins */
#define PDM_DATA P10_5
#define PDM_CLK P10_4
(2)pdm、pcm配置。主要采样率、编码率与模式(立体声,使用左右mic)等。
/* HAL Config */
const cyhal_pdm_pcm_cfg_t pdm_pcm_cfg =
{
.sample_rate = SAMPLE_RATE_HZ,
.decimation_rate = DECIMATION_RATE,
.mode = CYHAL_PDM_PCM_MODE_STEREO,
.word_length = 16,/* bits */
.left_gain = 0, /* dB */
.right_gain = 0, /* dB */
};
(3)按键中断回调。主要是通过事件置标志位,在主函数调高噪声阈值(noise_threshold)
void button_isr_handler(void *arg, cyhal_gpio_event_t event)
{
(void) arg;
(void) event;
button_flag = true;
}
cyhal_gpio_callback_data_t cb_data =
{
.callback = button_isr_handler,
.callback_arg = NULL
};2.main函数
(1)系统与时钟、串口、用户LED、按键初始化
(2)pdm、pcm初始化。
这里有注册pdm_pcm_isr_handler回调,检查MIC用数据,在回调里置标志位
void pdm_pcm_isr_handler(void *arg, cyhal_pdm_pcm_event_t event)
{
(void) arg;
(void) event;
pdm_pcm_flag = true;
}
(3)主函数实现
检查microphone有数据,计算音量。根据当前音量与比率,打印多少个“-”。根据音量是否超过(噪声)阈值,使用户led来亮/灭。通过按键,来调高(噪声)阈值.实现代码如下
for(;;)
{
/* Check if any microphone has data to process */
if (pdm_pcm_flag)
{
/* Clear the PDM/PCM flag */
pdm_pcm_flag = 0;
/* Reset the volume */
volume = 0;
/* Calculate the volume by summing the absolute value of all the
* audio data from a frame */
for (uint32_t index = 0; index < FRAME_SIZE; index++)
{
volume += abs(audio_frame);
}
/* Prepare line to report the volume */
printf("\n\r");
/* Report the volume */
for (uint32_t index = 0; index < (volume/VOLUME_RATIO); index++)
{
printf("-");
}
/* Turn ON the LED when the volume is higher than the threshold */
if ((volume/VOLUME_RATIO) > noise_threshold)
{
cyhal_gpio_write((cyhal_gpio_t) CYBSP_USER_LED, CYBSP_LED_STATE_ON);
}
else
{
cyhal_gpio_write((cyhal_gpio_t) CYBSP_USER_LED, CYBSP_LED_STATE_OFF);
}
/* Setup to read the next frame */
cyhal_pdm_pcm_read_async(&pdm_pcm, audio_frame, FRAME_SIZE);
}
/* Reset the noise threshold if User Button is pressed */
if (button_flag)
{
/* Reset button flag */
button_flag = false;
/* Get the current volume and add a hysteresis as the new threshold */
noise_threshold = (volume/VOLUME_RATIO) + THRESHOLD_HYSTERESIS;
/* Report the new noise threshold over UART */
printf("\n\rNoise threshold: %lu\n\r", (unsigned long) noise_threshold);
}
cyhal_syspm_sleep();
}
}
三.调试测验
1.编译烧录
2.打开串口,查看日志
随着外接声音的高低,出现打印“-”的长短,用户led灯伴随亮/灭。
至此,实现麦克风拾音功能。
页:
[1]