STM32 外设驱动模块:声音传感器模块

在日常生活中,声音传感器模块广泛应用于各种智能设备中,能够实现声控灯、噪音监测、安防报警等功能。今天,我们来学习如何使用高感度声音传感器模块,探索它在声控灯和音量检测等方面的应用。

一、引言

学习目标

  • 掌握高感度声音模块的使用。
  • 实现声控灯和音量检测功能。

模块应用背景

高感度声音模块具有多种应用场景,以下是一些常见的使用场景:

  1. 声控开关:比如拍手控制灯光、窗帘或玩具等设备。
  2. 声音强度监测:用于测量环境噪音,帮助制作噪音计。
  3. 安防报警:监测特定区域的异常声音(如玻璃破碎声),及时触发报警。
  4. 录音触发:当检测到声音时,自动启动录音设备,节省存储空间。
  5. 交互装置:通过特定频率或节奏的声音与装置互动。

二、模块概述

高感度声音传感器模块的主要功能是将声音信号(声压)转换为电信号。它的核心组件通常是一个驻极体麦克风,能够非常敏感地捕捉到微弱的声音,并将其放大成电信号供微控制器读取。这个模块可以有效地检测环境中的各种声音变化。

引脚介绍

  • VCC--------+:接正电源(3.3V或5V,当前使用的是3.3V)。
  • GND--------G:接地。
  • OUT------------AO:模拟信号输出引脚。
  • EN---------DO:数字信号输出引脚。

信号输出方式

  1. 模拟输出 (AO - Analog Output)

    • 信号性质:连续变化的电压信号。

    • 工作原理:模块内部的运算放大器将麦克风的微弱电信号放大,输出一个电压信号,反映环境声音的强度。

    • 输出值:电压在0到VCC之间变化,声音越大,电压越高。

    • 特点

      • 提供丰富的信息,可以获得声音的幅度、波形等详细数据。
      • 高精度,可以利用STM32的12位ADC进行精确的声音强度分析。
      • 需要处理和分析,通常需要微控制器的ADC引脚。
  2. 数字输出 (DO - Digital Output)

    • 信号性质:简单的开关信号,只有高低电平。

    • 工作原理:模块内部的比较器将模拟信号与设置好的阈值电压比较,当声音强度超过阈值时输出低电平,否则输出高电平。

    • 输出值

      • 高电平 (通常为3.3V/5V):声音强度低于阈值。
      • 低电平 (通常为0V):声音强度高于阈值。
    • 特点

      • 编程简单,直接通过GPIO输入引脚读取。
      • 可以通过调整阈值来忽略小的背景噪音,只有较大的声音才会触发信号。
      • 信息量较少,仅能判断声音是否超过阈值。

三、硬件连接

将高感度声音传感器模块与STM32连接时的硬件连接方式如下:

  • AO 模拟信号输出引脚:连接到STM32的A3引脚。
  • G:接地。
  • :连接到3.3V电源。
  • DO数字信号输出引脚:连接到STM32的B14引脚。

四、STM32CubeMX配置

在STM32的开发过程中,可以通过STM32CubeMX进行配置,以便在软件中方便地使用这个传感器模块。配置的主要内容包括模拟输入的配置和数字输入的配置,确保能够准确地读取模拟和数字信号。

配置流程

这些配置步骤将帮助你快速启动并使用高感度声音传感器模块进行各种声控和音量检测任务。

示例代码

c 复制代码
/* USER CODE BEGIN Header */
/**
  ******************************************************************************  
  * @file           : main.c  
  * @brief          : 主程序体  
  ******************************************************************************  
  * @attention  
  *  
  * Copyright (c) 2025 STMicroelectronics.  
  * All rights reserved.  
  *  
  * This software is licensed under terms that can be found in the LICENSE file  
  * in the root directory of this software component.  
  * If no LICENSE file comes with this software, it is provided AS-IS.  
  *  
  ******************************************************************************  
  */  
/* USER CODE END Header */

/* Includes ------------------------------------------------------------------*/  
#include "main.h"  
#include "adc.h"  
#include "i2c.h"  
#include "gpio.h"  

/* 用户自定义引入 ----------------------------------------------------------*/  
#include "OLED.h"  

/* Private variables ---------------------------------------------------------*/  
uint16_t adc_value = 0; // 声音传感器的ADC值  

/* Private function prototypes -----------------------------------------------*/  
void SystemClock_Config(void);  

/* 用户自定义代码 ---------------------------------------------------------*/  
int main(void)  
{  
  /* MCU 初始化 --------------------------------------------------------*/  
  HAL_Init();  
  SystemClock_Config();  
  
  /* 初始化外设 --------------------------------------------------------*/  
  MX_GPIO_Init();  
  MX_ADC1_Init();  
  MX_I2C1_Init();  
  
  /* OLED初始化并显示启动信息 */  
  OLED_Init(&hi2c1);  
  OLED_Clear();  
  OLED_ShowString(1,1,"Big sound");  
  HAL_ADC_Start(&hadc1);  // 开始ADC转换

  /* 无限循环:读取ADC值,显示到OLED屏幕上,控制设备开关 */  
  while (1)  
  {  
    // 判断GPIOB, GPIO_PIN_14引脚的电平,根据其状态控制GPIOA, GPIO_PIN_1  
    if(HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_14) == 1)  
    {  
      HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_RESET);  // 关闭设备  
    }  
    else  
    {  
      HAL_GPIO_WritePin(GPIOA, GPIO_PIN_1, GPIO_PIN_SET);  // 打开设备  
      HAL_Delay(5000);  // 延迟5秒  
    }  

    // 获取ADC转换结果并显示  
    adc_value = HAL_ADC_GetValue(&hadc1);  
    OLED_ShowNum(3, 1, adc_value, 4);  // 显示ADC值  
    HAL_Delay(500);  // 延迟500ms  
  }  
}  

/* 系统时钟配置函数 -----------------------------------------------------*/  
void SystemClock_Config(void)  
{  
  RCC_OscInitTypeDef RCC_OscInitStruct = {0};  
  RCC_ClkInitTypeDef RCC_ClkInitStruct = {0};  
  RCC_PeriphCLKInitTypeDef PeriphClkInit = {0};  

  /* 初始化RCC振荡器 */  
  RCC_OscInitStruct.OscillatorType = RCC_OSCILLATORTYPE_HSE;  
  RCC_OscInitStruct.HSEState = RCC_HSE_ON;  
  RCC_OscInitStruct.HSEPredivValue = RCC_HSE_PREDIV_DIV1;  
  RCC_OscInitStruct.HSIState = RCC_HSI_ON;  
  RCC_OscInitStruct.PLL.PLLState = RCC_PLL_ON;  
  RCC_OscInitStruct.PLL.PLLSource = RCC_PLLSOURCE_HSE;  
  RCC_OscInitStruct.PLL.PLLMUL = RCC_PLL_MUL9;  
  if (HAL_RCC_OscConfig(&RCC_OscInitStruct) != HAL_OK)  
  {  
    Error_Handler();  
  }  

  /* 初始化CPU,AHB和APB总线时钟 */  
  RCC_ClkInitStruct.ClockType = RCC_CLOCKTYPE_HCLK | RCC_CLOCKTYPE_SYSCLK  
                                | RCC_CLOCKTYPE_PCLK1 | RCC_CLOCKTYPE_PCLK2;  
  RCC_ClkInitStruct.SYSCLKSource = RCC_SYSCLKSOURCE_PLLCLK;  
  RCC_ClkInitStruct.AHBCLKDivider = RCC_SYSCLK_DIV1;  
  RCC_ClkInitStruct.APB1CLKDivider = RCC_HCLK_DIV2;  
  RCC_ClkInitStruct.APB2CLKDivider = RCC_HCLK_DIV1;  
  if (HAL_RCC_ClockConfig(&RCC_ClkInitStruct, FLASH_LATENCY_2) != HAL_OK)  
  {  
    Error_Handler();  
  }  

  /* 配置ADC时钟源 */  
  PeriphClkInit.PeriphClockSelection = RCC_PERIPHCLK_ADC;  
  PeriphClkInit.AdcClockSelection = RCC_ADCPCLK2_DIV6;  
  if (HAL_RCCEx_PeriphCLKConfig(&PeriphClkInit) != HAL_OK)  
  {  
    Error_Handler();  
  }  
}  

/* 错误处理函数 ---------------------------------------------------------*/  
void Error_Handler(void)  
{  
  __disable_irq();  
  while (1)  
  {  
    // 错误时停留在此处  
  }  
}  

/* 用户自定义函数 -------------------------------------------------------*/  
void Display_RealTime_Data(uint16_t value)  
{  
  // 显示原始ADC值  
  OLED_ShowNum(2, 6, value, 4);  
  
  // 计算电压值并显示  
  float voltage = (value * 3.3f) / 4095.0f;  
  uint16_t voltage_int = voltage * 100;  // 电压放大100倍,便于显示小数部分  
  
  OLED_ShowNum(3, 6, voltage_int / 100, 1);  // 显示电压整数部分  
  OLED_ShowChar(3, 7, '.');  // 显示小数点  
  OLED_ShowNum(3, 8, voltage_int % 100, 2);  // 显示电压小数部分  
  OLED_ShowChar(3, 10, 'V');  // 显示电压单位V  
  
  // 根据ADC值显示声音强度状态  
  if (value < 800)  
  {  
    OLED_ShowString(4, 8, "Quiet    ");  
  }  
  else if (value < 1600)  
  {  
    OLED_ShowString(4, 8, "Normal   ");  
  }  
  else if (value < 2400)  
  {  
    OLED_ShowString(4, 8, "Loud     ");  
  }  
  else if (value < 3200)  
  {  
    OLED_ShowString(4, 8, "Very Loud");  
  }  
  else  
  {  
    OLED_ShowString(4, 8, "!DANGER! ");  
  }  
}

代码说明

  1. 系统初始化

    • 初始化了所需的外设,包括GPIO、ADC和I2C(用于OLED显示屏)。
    • 配置系统时钟,确保STM32工作在高效模式。
  2. 主循环

    • 从ADC读取声音传感器的模拟信号,并将其转换为数字值。
    • 根据ADC值的大小,动态显示环境声音的强度(例如:安静、正常、响亮等)。
    • 使用GPIO控制设备开关,基于数字输出信号判断声音是否超过设定阈值。
  3. 电压显示

    • 将ADC采样值转换为电压,并显示在OLED上,精确到小数点后两位。
  4. 声音强度分类

    • 根据声音的强度(通过ADC值)对声音进行分类,显示如"安静"、"正常"、"响亮"、"非常响亮"或"危险"信息。

通过本示例代码,你可以轻松地实现一个声音检测和控制系统,结合OLED显示屏和声音传感器,可以直观地显示环境声音的变化。

相关推荐
亿道电子Emdoor3 小时前
【ARM】MDK-Functions界面设置
stm32·单片机·嵌入式硬件
学不动CV了3 小时前
ARM单片机中断及中断优先级管理详解
c语言·arm开发·stm32·单片机·嵌入式硬件·51单片机
Topplyz4 小时前
最近两个电路调试的经历与总结(二)
嵌入式硬件·硬件设计·运放
qq_526099134 小时前
是什么让边缘电脑真正工业化?
嵌入式硬件·自动化
lingzhilab5 小时前
零知IDE——基于STM32F407VET6和HC-05(ZS-040)蓝牙控制RGB与CRC校验系统
stm32·单片机·嵌入式硬件
亿道电子Emdoor6 小时前
【ARM】MDK-授权报错解决:用户/主机不在包含列表中
arm开发·stm32·单片机
jghhh017 小时前
HT16C21 驱动模拟I2C实现
单片机·嵌入式硬件·算法
机器视觉知识推荐、就业指导7 小时前
STM32 外设驱动模块:旋转编码器
stm32·单片机·嵌入式硬件
Jayyih8 小时前
IMX6ULL--EPIT,GPT
单片机·嵌入式硬件