PDM

PDM(Pulse Density Modulation)是一种用数字信号表示模拟信号的调制方法。PDM只有1位数据输出,要么为0,要么为1。

一、初始化

1. PDM模块的IO配置

调用IO 的初始化接口,可以将任意IO复用为pdm的colck data0或data1引脚。
void pdm_clk_io_init(uint8_t pin);
void pdm_data0_io_init(uint8_t pin);
void pdm_data1_io_init(uint8_t pin);

备注

1. 芯片的IO 一共有34个,具体情况需根据封装图来定义。
2. 为了避免不必要的bug,在使用pdm通信的时候,请先初始化IO,再进行下列参数的配置。

2. 初始化PDM模块

2.1 PDM结构体参数原型如下:

typedef struct __PDM_Init_TypeDef
{
    const struct pdm_fir *fir;  /*!< pdm filter controller configure */
    PDM_CFG_TypeDef cfg;        /*!< pdm clock rate, capture delay, sampling rate, and data gain configure */
    PDM_MODE_TypeDef mode;      /*!< pdm channel mode configure */
}PDM_Init_TypeDef;

2.2 调用初始化PDM模块函数接口

通过初始化接口,应用程序可以对PDM进行参数配置。

HAL_StatusTypeDef HAL_PDM_Init(PDM_HandleTypeDef *hpdm,PDM_Init_TypeDef *Init);

3.PDM初始化参考代码如下:

#define PDM_CLK_KHZ 1024
#define PDM_SAMPLE_RATE_HZ 16000
void pdm_init()
{
    pdm_clk_io_init(PB10);  /*!< PB10复用为pdm clk引脚 */
    pdm_data0_io_init(PB09);    /*!< PB09复用为pdm data0引脚 */
    pdm.Instance = LSPDM;   /*!< PDM外设的基址 */
    PDM_Init_TypeDef Init =
    {
        .fir = PDM_FIR_COEF_16KHZ,  /*!< 配置PDM的滤波控制器 */
        .cfg = {
            .clk_ratio = PDM_CLK_RATIO(PDM_CLK_KHZ),    /*!< 配置PDM的时钟频率为1.024MHZ */
            .sample_rate = PDM_SAMPLE_RATE(PDM_CLK_KHZ,PDM_SAMPLE_RATE_HZ), /*!< 配置PDM采样频率为16KHZ */
            .cap_delay = 30,    /*!< 配置捕获延迟为30 */
            .data_gain = 5,     /*!< 配置数据增益为5 */
        },
        .mode = PDM_MODE_Mono,  /*!< 配置PDM为单通道模式 */
    };
    HAL_PDM_Init(&pdm,&Init);   /*!< 调用PDM初始化函数 */
}

二、反初始化

  1. 反初始化PDM模块

    通过反初始化接口,应用程序可以关闭PDM外设,在运行BLE程序时降低系统的功耗。

HAL_StatusTypeDef HAL_PDM_DeInit(PDM_HandleTypeDef *hpdm);
  1. 反初始化PDM IO

    反初始化IO接口的主要目的是为了避免在进入低功耗模式时,IO上产生漏电。

void pdm_clk_io_deinit(void);
void pdm_data0_io_deinit(void);
void pdm_data1_io_deinit(void);

备注

PDM初始化动作会向系统注册PDM进入工作状态,当系统检测到有任一外设处于工作状态时,都不会进入低功耗休眠。 因此,PDM使用完毕,需要进入低功耗状态之前,必须反初始化PDM。

三、PDM相关函数接口

备注

收PDM数据的模式分为 2 种:中断模式 和 DMA 模式。

3.1 收PDM数据——中断方式

HAL_StatusTypeDef HAL_PDM_Transfer_Config_IT(PDM_HandleTypeDef *hpdm,uint16_t *pFrameBuffer0,uint16_t *pFrameBuffer1,uint16_t FrameNum);

3.2 收PDM数据——DMA方式

以DMA方式(基本模式和乒乓模式)收PDM数据如下所示:
HAL_StatusTypeDef HAL_PDM_Transfer_Config_DMA(PDM_HandleTypeDef *hpdm,uint16_t *pFrameBuffer0,uint16_t *pFrameBuffer1,uint16_t FrameNum);
HAL_StatusTypeDef HAL_PDM_PingPong_Transfer_Config_DMA(PDM_HandleTypeDef *hpdm,struct PDM_PingPong_Bufptr *CH0_Buf,struct PDM_PingPong_Bufptr *CH1_Buf,uint16_t FrameNum);

3.3 使能PDM

HAL_StatusTypeDef HAL_PDM_Start(PDM_HandleTypeDef *hpdm);

3.4 失能PDM

HAL_StatusTypeDef HAL_PDM_Stop(PDM_HandleTypeDef *hpdm);

3.5 PDM中断处理函数

void HAL_PDM_IRQHandler(PDM_HandleTypeDef *hpdm);

3.6 在PDM中断处理函数中接收完FrameNum大小数据的回调函数

void HAL_PDM_CpltCallback(PDM_HandleTypeDef *hpdm);

3.7 在DMA模式下接收完FrameNum大小pdm数据的回调函数

void HAL_PDM_DMA_CpltCallback(PDM_HandleTypeDef *hpdm,uint8_t buf_idx);