STM32 H7使用ADC采集模拟麦克风信号
分类: 硬件 发布于: 2023-09-30

stm32H7的ADC极具使用价值,使用定时器的更新事件作为触发时钟源,可以在任意时钟下便捷的采集模拟硅麦的信号。下述是调试记录。

ADC 配置

首先基于cubemx创建工程,并配置好时钟。其中ADC时钟配置需按照手册要求,不可过高,对于声音信号采集,10MHz已经足够。然后在对应管脚选择输入,大多数硅麦都是单端输入,选择"Single-ended"即可,其它保持默认。然后在参数中选择独立模式即"Independent mode" 。主要配置:

  • 分频系数,默认1,不分频
  • 分辨率,选16bit
  • Scan Conversion Mode 设置为 Disabled。如果是多声道,则需要设置为Enable,并改适当修改其他必要的配置。
  • Continuous Conversion Mode 设置为 Disabled
  • Discontinuous Conversion Mode 设置为 Disabled
  • End Of Conversion Selection 设置为 End of single conversion
  • Overrun behaviour 设置为 preserved
  • Left Bit Shift 设置为 No bit shift
  • Conversion Data Management Mode 设置为 DMA circular mode
  • Low Power Auto Wait 设置为 Disabled

由于不需要过采样,因此过采样相关配置均关闭。在 "ADC_Regular_ConversionMode" 的详细配置如下:

  • Enable Regular Conversions 设置为 Enable
  • Enable Regular Oversampling 设置为 Disable
  • Number Of Conversion 单声道设置为1。但如果是多声道,按需选择,同时需要注意数据组织格式
  • External Trigger Conversion Source 选择对应的触发源,这里是 Timer 4 Trigger Out event。在没有配置好定时器之前,这里可能不会有此选项,此时需要先配置定时器
  • External Trigger Conversion Edge 可选上升沿时检测

此外,需注意Rank的配置,这里用来配置单独通道的采样。"Offset Number"和"Offset Signed Saturation"分别设置为"no offset"和"Disable",采样时间可以按需选择,周期越长理论上越精确。

其他设置组均保持关闭或禁用状态,然后在DMA中添加对应的配置,mode选择"从外设到memory",mode设置为 "circular",memory选择"Increment Address"即地址自增。同时打开 FIFO 半满阈值:勾选"Use FIFO",threshold 选择 "Half Full",Data Width均选择"Half Word",Brust Size 选择 "Single"。最后使能DMA中断。

定时器配置

将定时器设置为ADC的触发源时,“Mode”配置栏中仅需选择时钟源。在这里 Counter Mode 选择 "up",禁用Auto-load preload,不分频,此时触发频率即为 定时器时钟频率 / (Prescaler + 1) / (Counter Period + 1)。

这里采样率为44.1 Khz,Timer 时钟频率为100Mhz,则Prescaler 设置为9,Counter Period设置为226,实际频率 = 100_000_000/ (9+1) / (226 + 1) ≈ 44.052 Khz。

最后在 Trigger Out Parameters中做如下配置:

  • Master/Slave Mode 设置为 Disabled
  • Trigger Event Selection TRGO 设置为 Update Event

启动 ADC 采样和DMA传输

在启动ADC传输之前,需要先使能定时器,相关HAL库代码如下:

// htim4按需替换
HAL_TIM_Base_Start(&htim4);

// 启动传输
uint16_t ADCValue[512] = {0};
HAL_ADC_Start_DMA(&hadc2, (void *)ADCValue, 512);

// 终止传输
HAL_ADC_Stop_DMA(&hadc2);

在启动传输后,需要在DMA回调函数中处理采集到的数据,即:

void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef *hadc);
void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef *hadc);

参考资料:

  1. 【安富莱】STM32H7用户手册...硬汉嵌入式论坛