dirty123 发表于 2025-11-23 11:26

【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]
查看完整版本: 【CY8CKIT-062S2-AI 测评】--MIC拾音