基于STM32的录音机设计

一、系统概述与核心功能

1. 系统定位

基于STM32的录音机以“音频采集-编码存储-回放控制-低功耗续航”为核心,实现声音信号的实时录制、WAV格式存储、播放控制及文件管理,支持麦克风输入、耳机/喇叭输出、SD卡扩展存储,适用于会议记录、语音备忘、音乐练习等场景,替代传统磁带/数字录音笔,提供高性价比嵌入式录音方案。

2. 核心功能模块

模块 功能描述
音频采集 麦克风模块(如MAX9814)采集声音,STM32通过ADC/I2S接口实现8-16kHz采样、16位量化
音频编码 软件编码为PCM/WAV格式(可选ADPCM压缩),添加WAV头(RIFF块、fmt块、data块)
存储管理 SD卡(FAT32格式)存储录音文件,支持文件创建/删除/重命名,FatFS文件系统管理
回放控制 播放/暂停/停止/快进/快退,音量调节(DAC输出/PWM调功放),支持循环播放
用户交互 OLED显示(录音时长、文件列表、电量),按键/旋转编码器操作,LED状态指示
低功耗设计 待机时关闭非必要模块(显示/编码),STM32进入STOP模式,续航≥8小时(2000mAh电池)

二、硬件设计方案

1. 核心硬件选型

模块 型号 关键参数 接口方式
主控MCU STM32F407ZGT6 168MHz Cortex-M4,1MB Flash,192KB RAM,I2S、DAC、SDIO、DMA,支持FPU/DSP 核心控制器
音频采集 MAX9814 驻极体麦克风+自动增益控制(AGC),输出模拟信号(0-3.3V),信噪比>60dB ADC1_IN0(PA0,12位ADC)
音频输出 STM32内部DAC+TPA6130A2 DAC1(PA4)输出模拟音频,TPA6130A2功放(3.3V/1.5W)驱动耳机/喇叭 DAC+ I2C(功放控制)
存储模块 Micro SD卡(TF卡) 8GB-32GB,Class 10(高速读写),FAT32格式 SDIO(SDIO_D0-D3+CLK+CMD)
显示模块 OLED 12864(I2C) 0.96寸,128×64像素,低功耗(<10mA),显示文件列表、录音时长、电量 I2C1(PB6=SCL,PB7=SDA)
用户输入 轻触按键×4+旋转编码器 按键(录音/播放/停止/菜单),编码器(音量调节/快进快退) GPIO(PC0-PC3按键,PA6-PA7编码器)
电源模块 3.7V锂电池+TP4056+AMS1117 3.7V/2000mAh锂电池,TP4056充电(5V Micro USB),AMS1117-3.3V/1.8V稳压输出 供电一体化(带过充保护)
辅助模块 有源蜂鸣器+LED 蜂鸣器(操作提示音),LED(红/绿双色,电源/录音状态) GPIO(PB0=蜂鸣器,PB1=LED)

2. 硬件电路设计要点

2.1 核心电路连接

  • STM32最小系统:8MHz外部晶振+32.768kHz RTC晶振,SWD调试接口(PA13/PA14),复位电路(10kΩ上拉+0.1μF电容)。
  • 音频采集(MAX9814):VCC=3.3V,OUT接PA0(ADC1_IN0),AGC引脚悬空(默认开启),GND共地,输出经RC滤波(1kΩ+0.1μF)后接入ADC。
  • 音频输出(DAC+功放):STM32 DAC1(PA4)输出→TPA6130A2 INL引脚,TPA6130A2 VCC=3.3V,OUTL/OUTR接耳机插座(3.5mm),I2C(PB6/PB7)控制音量。
  • SD卡(SDIO):SDIO_D0-D3(PC8-PC11)、SDIO_CLK(PC12)、SDIO_CMD(PD2),VCC3.3V供电,GND共地。

2.2 抗干扰设计

  • 电源隔离:麦克风与STM32电源通过磁珠(600Ω@100MHz)隔离,避免AGC电路噪声干扰。
  • 信号滤波:MAX9814输出加二阶低通滤波(截止频率8kHz,匹配采样率),ADC输入并联10nF电容去耦。
  • PCB布局:音频走线(PA0、PA4)短且远离数字信号,模拟地(AGND)与数字地(DGND)单点连接(0Ω电阻)。

三、软件设计与核心代码

1. 系统架构(FreeRTOS多任务调度)

采用FreeRTOS实时操作系统,划分5个核心任务(优先级从高到低):

  1. 音频采集任务(优先级4):通过ADC DMA采集麦克风信号,存储至环形缓冲区。
  2. 编码存储任务(优先级3):读取环形缓冲区数据,编码为WAV格式,写入SD卡(FatFS)。
  3. 回放控制任务(优先级3):解析WAV文件,通过DAC DMA输出音频,响应播放/暂停指令。
  4. 用户交互任务(优先级2):扫描按键/编码器,更新OLED显示,处理菜单操作(文件选择、删除)。
  5. 低功耗管理任务(优先级1):检测无操作超时(5分钟),关闭显示/功放,进入STOP模式。

2. 核心代码实现(基于HAL库)

2.1 音频采集与DMA传输(ADC)

#include "audio_capture.h"
#include "stm32f4xx_hal.h"

#define ADC_BUFFER_SIZE 1024  // 环形缓冲区大小(1024×2字节=2KB)
uint16_t adc_buffer[ADC_BUFFER_SIZE];
uint16_t dma_index = 0;  // DMA传输索引

// ADC初始化(PA0,12位,DMA传输)
void ADC1_Init(void) {
  ADC_ChannelConfTypeDef sConfig = {0};
  hadc1.Instance = ADC1;
  hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;  // 84MHz/4=21MHz
  hadc1.Init.Resolution = ADC_RESOLUTION_12B;
  hadc1.Init.ScanConvMode = DISABLE;
  hadc1.Init.ContinuousConvMode = ENABLE;  // 连续转换
  hadc1.Init.DMAContinuousRequests = ENABLE;  // DMA连续请求
  hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
  HAL_ADC_Init(&hadc1);
  
  sConfig.Channel = ADC_CHANNEL_0;  // PA0
  sConfig.Rank = 1;
  sConfig.SamplingTime = ADC_SAMPLETIME_480CYCLES;  // 480周期采样(16kHz采样率)
  HAL_ADC_ConfigChannel(&hadc1, &sConfig);
  
  // 启动DMA传输(循环模式)
  HAL_ADC_Start_DMA(&hadc1, (uint32_t*)adc_buffer, ADC_BUFFER_SIZE);
}

// DMA传输完成中断回调(半满/全满时触发)
void HAL_ADC_ConvHalfCpltCallback(ADC_HandleTypeDef* hadc) {
  // 处理前半缓冲区数据(录音/存储)
  process_audio_data(adc_buffer, ADC_BUFFER_SIZE/2);
}

void HAL_ADC_ConvCpltCallback(ADC_HandleTypeDef* hadc) {
  // 处理后半缓冲区数据
  process_audio_data(&adc_buffer[ADC_BUFFER_SIZE/2], ADC_BUFFER_SIZE/2);
}

2.2 WAV文件编码与存储(FatFS)

#include "ff.h"
#include "wav_encoder.h"

FIL wav_file;  // FATFS文件对象
uint32_t data_size = 0;  // 录音数据大小

// WAV头结构(44字节)
typedef struct {
  char riff[4];          // "RIFF"
  uint32_t file_size;    // 文件总大小-8
  char wave[4];          // "WAVE"
  char fmt[4];           // "fmt "
  uint32_t fmt_size;     // fmt块大小(16)
  uint16_t audio_format; // 音频格式(1=PCM)
  uint16_t channels;     // 声道数(1=单声道)
  uint32_t sample_rate;  // 采样率(16000)
  uint32_t byte_rate;    // 字节率=采样率×声道数×位数/8
  uint16_t block_align;  // 块对齐=声道数×位数/8
  uint16_t bits_per_sample; // 位深(16)
  char data[4];          // "data"
  uint32_t data_size;    // 数据块大小
} WAV_Header_t;

// 创建WAV文件并写入头
uint8_t create_wav_file(const char* filename) {
  WAV_Header_t header = {
    .riff = {'R','I','F','F'},
    .wave = {'W','A','V','E'},
    .fmt = {'f','m','t',' '},
    .fmt_size = 16,
    .audio_format = 1,
    .channels = 1,
    .sample_rate = 16000,
    .byte_rate = 16000*1*16/8,
    .block_align = 1*16/8,
    .bits_per_sample = 16,
    .data = {'d','a','t','a'}
  };
  
  FRESULT res = f_open(&wav_file, filename, FA_CREATE_NEW | FA_WRITE);
  if (res != FR_OK) return 1;
  
  // 写入WAV头(数据大小暂设为0,后续更新)
  header.data_size = 0;
  header.file_size = 36;  // 44-8=36(初始值)
  f_write(&wav_file, &header, sizeof(header), NULL);
  return 0;
}

// 写入音频数据(PCM)
void write_audio_data(uint16_t* data, uint32_t len) {
  UINT bw;
  f_write(&wav_file, data, len*2, &bw);  // 16位数据,2字节/点
  data_size += len*2;
}

// 关闭文件时更新WAV头
void close_wav_file(void) {
  WAV_Header_t header;
  f_lseek(&wav_file, 0);
  f_read(&wav_file, &header, sizeof(header), NULL);  // 读取原头
  header.data_size = data_size;
  header.file_size = 36 + data_size;
  f_lseek(&wav_file, 0);
  f_write(&wav_file, &header, sizeof(header), NULL);  // 更新头
  f_close(&wav_file);
}

2.3 音频回放(DAC DMA输出)

#include "audio_playback.h"

DAC_HandleTypeDef hdac;
TIM_HandleTypeDef htim6;  // DAC触发定时器(16kHz)

// DAC初始化(PA4,TIM6触发)
void DAC1_Init(void) {
  DAC_ChannelConfTypeDef sConfig = {0};
  hdac.Instance = DAC;
  HAL_DAC_Init(&hdac);
  
  sConfig.DAC_Trigger = DAC_TRIGGER_T6_TRGO;  // TIM6触发
  sConfig.DAC_OutputBuffer = DAC_OUTPUTBUFFER_ENABLE;
  HAL_DAC_ConfigChannel(&hdac, &sConfig, DAC_CHANNEL_1);
  
  // 启动DAC DMA(循环模式)
  HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*)playback_buffer, PLAYBACK_BUFFER_SIZE, DAC_ALIGN_12B_R);
}

// 定时器6初始化(16kHz触发DAC)
void TIM6_Init(void) {
  htim6.Instance = TIM6;
  htim6.Init.Prescaler = 83;  // 84MHz/84=1MHz
  htim6.Init.Period = 62;     // 1MHz/62≈16kHz
  HAL_TIM_Base_Init(&htim6);
  HAL_TIM_Base_Start(&htim6);  // 启动定时器
}

// 播放WAV文件(解析头+读取数据)
void play_wav_file(const char* filename) {
  FIL file;
  WAV_Header_t header;
  UINT br;
  
  f_open(&file, filename, FA_READ);
  f_read(&file, &header, sizeof(header), &br);  // 读取WAV头
  
  // 检查格式(PCM、单声道、16位、16kHz)
  if (header.audio_format != 1 || header.channels != 1 || header.bits_per_sample != 16 || header.sample_rate != 16000) {
    f_close(&file);
    return;
  }
  
  // 读取数据块并播放(通过DAC DMA)
  uint16_t play_buffer[PLAYBACK_BUFFER_SIZE];
  while (f_read(&file, play_buffer, sizeof(play_buffer), &br) == FR_OK && br > 0) {
    // 等待DMA缓冲区空闲(简化处理,实际需用双缓冲)
    HAL_DAC_Start_DMA(&hdac, DAC_CHANNEL_1, (uint32_t*)play_buffer, PLAYBACK_BUFFER_SIZE, DAC_ALIGN_12B_R);
    while (HAL_DAC_GetState(&hdac) != HAL_DAC_STATE_READY);  // 等待传输完成
  }
  f_close(&file);
}

2.4 主程序框架(FreeRTOS任务调度)

#include "stm32f4xx_hal.h"
#include "FreeRTOS.h"
#include "task.h"
#include "audio_capture.h"
#include "audio_playback.h"
#include "ff.h"
#include "oled.h"

int main(void) {
  HAL_Init();
  SystemClock_Config();  // 168MHz
  MX_GPIO_Init();        // 按键、LED、编码器
  MX_ADC1_Init();        // 音频采集ADC
  MX_DAC1_Init();        // 音频输出DAC
  MX_SDIO_SD_Init();     // SD卡SDIO
  MX_FATFS_Init();       // FatFS初始化
  OLED_Init();           // OLED显示
  
  // FreeRTOS任务创建
  xTaskCreate(AudioCapture_Task, "Capture", 256, NULL, 4, NULL);  // 采集
  xTaskCreate(EncodeStore_Task, "Encode", 256, NULL, 3, NULL);    // 编码存储
  xTaskCreate(Playback_Task, "Playback", 256, NULL, 3, NULL);      // 回放
  xTaskCreate(UI_Task, "UI", 128, NULL, 2, NULL);                  // 用户交互
  xTaskCreate(LowPower_Task, "LowPower", 128, NULL, 1, NULL);      // 低功耗
  
  vTaskStartScheduler();  // 启动调度器
  while (1);
}

四、关键技术与优化

1. 音频质量优化

  • 采样率与位深:16kHz采样率+16位量化(满足语音清晰度),避免过高采样率浪费存储。
  • AGC控制:MAX9814自动增益控制避免大信号削波,小信号放大,提升动态范围。
  • 去噪处理:软件实现IIR低通滤波(截止频率3.4kHz,模拟电话音质)或FFT去噪(需STM32F4 DSP支持)。

2. 存储效率优化

  • WAV格式选择:未压缩PCM(音质好,文件大)或ADPCM压缩(4:1压缩比,文件小,需软件编码)。
  • 文件管理:按日期自动创建文件夹(如RECORD/20231001/),避免单目录文件过多。

3. 低功耗设计

  • 动态电源管理:录音/播放时开启功放,待机时关闭;SD卡空闲时进入睡眠模式(f_mount(NULL, "", 0))。
  • STM32低功耗模式:无操作时进入STOP模式(关闭ADC/DAC时钟),通过按键/编码器中断唤醒。

参考代码 基于STM32录音机设计 www.youwenfan.com/contentcnt/133699.html

五、系统调试与扩展

1. 调试步骤

阶段 操作 工具
硬件调试 测量MIC输出(0-3.3V)、DAC输出(0-1.2V) 示波器、万用表
SD卡挂载 用FatFS测试程序创建/读写文件 串口打印文件列表
录音测试 录入语音,用Audacity分析WAV文件(采样率/位深) Audacity(音频分析软件)
回放测试 播放录音,检查是否有杂音/失真 耳机/喇叭+人耳听辨

2. 扩展功能

  • 蓝牙传输:添加HC-05模块,通过蓝牙将录音文件发送至手机APP。
  • 语音识别:集成LD3320语音模块,实现“开始录音”“停止录音”语音控制。
  • 云存储:通过ESP8266模块上传录音至OneNET/阿里云,支持远程下载。
posted @ 2026-04-22 10:11  yu8yu7  阅读(18)  评论(0)    收藏  举报