注册 登录
电子工程世界-论坛 返回首页 EEWORLD首页 频道 EE大学堂 下载中心 Datasheet 专题
ccccccc@的个人空间 https://home.eeworld.com.cn/space-uid-947001.html [收藏] [复制] [分享] [RSS]
日志

《STM32H7S78-DK 开发套件二周目评测:简单声音采集之驱动MAX4466高精度声音传感器》

已有 272 次阅读2024-10-18 11:48 |个人分类:STM32H7S78-DK

MAX4466是一款高精度声音传感器,能够将声音信号转化为相应的模拟电压输出。STM32H7系列微控制器具备高性能的ADC(模数转换器)功能,可以精确地采集模拟信号并进行数字化处理。

 

 
使用STM32H7S78-DK开发板,通过ADC(模数转换器)采集MAX4466高精度声音传感器的模拟信号,最终实现一个简单的音量检测功能。
有下面个步骤:
- 从MAX4466传感器采集音频信号。
- 对采集的数据进行处理,获得稳定的音量信息。

 

  1. **硬件连接**:
    - **引脚连接**:

    -如上图所示,可以将MAX4466传感器的输出引脚连接到STM32的ADC输入引脚(即PC0,ADC12_IN10),设置该GPIO的ADC功能属性。
     
  2. **使用CubeMX进行配置**:
    - 在CubeMX中,进行如下设置:
    - **选择ADC模块**:选择ADC1,设置为12位分辨率,适合音频信号处理。
    - **设置采样时间**:设置为3.5个ADC时钟周期,确保稳定采样。
    - **设置转换模式**:选择单次转换模式(Single Conversion),适合简单应用。
    - **时钟设置**: 确保ADC时钟频率与采样时间相匹配,避免采样延迟。
    - **引脚设置**:配置PC0为ADC输入模式。
  3. **生成代码并导入Keil**:
    - 在CubeMX中生成代码,并导入Keil进行后续的代码开发。
  4. - 在Keil中,检查  初始化ADC并读取值的代码
    #include "stm32h7xx_hal.h"
    
       ADC_HandleTypeDef hadc1;
    
       void ADC_Init(void) {
           // 使能ADC时钟
           __HAL_RCC_ADC12_CLK_ENABLE(); 
    
           // ADC配置
           hadc1.Instance = ADC1;
           hadc1.Init.Resolution = ADC_RESOLUTION_12B; // 12位分辨率
           hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE; // 禁用扫描模式
           hadc1.Init.ContinuousConvMode = DISABLE; // 禁用连续转换
           hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START; // 软件触发
           hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT; // 数据右对齐
           hadc1.Init.NbrOfConversion = 1; // 单次转换
           HAL_ADC_Init(&hadc1); // 初始化ADC
       }
    
       uint32_t Read_ADC_Value(void) {
           HAL_ADC_Start(&hadc1); // 启动ADC转换
           HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY); // 等待转换完成
           return HAL_ADC_GetValue(&hadc1); // 返回ADC值
       }
  5. **数据处理**:在main代码中进行添加下面的代码进行采集信息的数据处理
    1. **滤波处理**: 使用简单的移动平均滤波器平滑采样值,减少波动。
      float moving_average(float new_value) {
      static float avg = 0;
      static int count = 0;
      count++;
      avg += (new_value - avg) / count; // 计算平均值
      return avg;
      }
    2. -  **偏移量校正**:在初始化时获取基准值,以确保测量的准确性。
      static int32_t offset = 0;
      void Calculate_Offset(void) {
      for (int i = 0; i < 100; i++) {
      HAL_ADC_Start(&hadc1);
      HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY);
      offset += HAL_ADC_GetValue(&hadc1); // 累加ADC值
      }
      offset /= 100; // 计算平均偏移量
      }
      uint32_t Get_Corrected_ADC_Value(void) {
      uint32_t adc_value = Read_ADC_Value(); // 读取ADC值
      return adc_value - offset; // 返回校正后的值
      }

       

  6. **UART配置**:
    - 通过UART输出采样结果,方便观察和调试。当然也可以使用LED进行对应的显示。在CUBEMAX进行对应的配置;

  •  

     
  • UART_HandleTypeDef huart1;
    void UART_Init(void) {
    // 使能USART1时钟
    __HAL_RCC_USART1_CLK_ENABLE();
    // USART配置
    huart1.Instance = USART1;
    huart1.Init.BaudRate = 115200; // 波特率
    huart1.Init.WordLength = USART_WORDLENGTH_8B; // 字长
    huart1.Init.StopBits = USART_STOPBITS_1; // 停止位
    huart1.Init.Parity = USART_PARITY_NONE; // 无奇偶校验
    huart1.Init.Mode = USART_MODE_TX_RX; // 发送接收模式
    HAL_UART_Init(&huart1); // 初始化UART
    }
    void UART_Send_Data(uint32_t data) {
    char buffer[20];
    sprintf(buffer, "ADC Value: %lu\n", data); // 格式化输出
    HAL_UART_Transmit(&huart1, (uint8_t*)buffer, strlen(buffer), HAL_MAX_DELAY); // 发送数据
    }

     

  1. **主程序**:
- 在主循环中读取ADC值,并通过UART输出。
int main(void) {
HAL_Init(); // 初始化HAL库
ADC_Init(); // 初始化ADC
UART_Init(); // 初始化UART
Calculate_Offset(); // 计算偏移量
while (1) {
uint32_t corrected_value = Get_Corrected_ADC_Value(); // 获取校正后的ADC值
float smoothed_value = moving_average(corrected_value); // 平滑处理
UART_Send_Data(corrected_value); // 发送ADC值
}
}

 

### **噪声处理**
- **滤波策略**:可以通过选择适当的滤波窗口,达到避免数据波动的效果。并且考虑使用中位数滤波或加权平均滤波,以处理异常值和噪声。
### **性能优化**
- **使用DMA**: 对于快速连续采样的需求,可以考虑使用DMA(直接存储器访问)进行数据采集,减轻CPU负担。
DMA_HandleTypeDef hdma_adc1;
void DMA_Init(void) {
__HAL_RCC_DMA2_CLK_ENABLE(); // 使能DMA时钟
hdma_adc1.Instance = DMA2_Stream0;
hdma_adc1.Init.Channel = DMA_CHANNEL_0; // 选择通道
hdma_adc1.Init.Direction = DMA_PERIPH_TO_MEMORY; // 从外设到内存
hdma_adc1.Init.PeriphInc = DMA_PINC_DISABLE; // 禁用外设地址递增
hdma_adc1.Init.MemInc = DMA_MINC_ENABLE; // 启用内存地址递增
hdma_adc1.Init.PeriphDataAlignment = DMA_PDATAALIGN_WORD; // 外设数据对齐
hdma_adc1.Init.MemDataAlignment = DMA_MDATAALIGN_WORD; // 内存数据对齐
hdma_adc1.Init.Mode = DMA_CIRCULAR; // 循环模式
hdma_adc1.Init.Priority = DMA_PRIORITY_HIGH; // 高优先级
HAL_DMA_Init(&hdma_adc1); // 初始化DMA
__HAL_LINKDMA(&hadc1, DMA_Handle, hdma_adc1); // 连接DMA与ADC
}

 

 

本文来自论坛,点击查看完整帖子内容。

评论 (0 个评论)

facelist doodle 涂鸦板

您需要登录后才可以评论 登录 | 注册

热门文章