1. 项目概述
这个语音存储与回放系统是我去年为一个工业设备维护项目开发的实用工具。当时现场工程师需要记录设备异常声音,但市面上专业录音设备要么太贵,要么操作复杂。于是我用常见的单片机加上几个基础元件,花了三周时间做出了这个成本不到200元的小装置。
系统核心功能很简单:按下录音键开始录音,松开停止;按播放键就能回放刚才录制的音频。但实现起来涉及模拟信号采集、数字信号处理、存储管理等多个技术环节。实测在8kHz采样率下可以存储30秒左右的清晰语音,完全满足现场记录设备异响的需求。
2. 硬件设计解析
2.1 核心器件选型
主控选用STM32F103C8T6,这款ARM Cortex-M3内核的单片机有足够的处理能力(72MHz主频)和存储空间(64KB Flash+20KB RAM),关键是其内置12位ADC和DAC,省去了外接编解码芯片的麻烦。
存储方案对比了SD卡和SPI Flash后,选择了W25Q64这款8MB的SPI Flash。虽然容量比SD卡小,但胜在接口简单(只需4线SPI)、读写速度快(支持80MHz时钟),而且不怕震动——这对工业现场很重要。
2.2 电路设计要点
麦克风前置放大电路用了LM358运放搭建的两级放大器:
- 第一级增益约100倍,将麦克风mV级信号放大到0.5Vpp
- 第二级增益可调(电位器控制),用于适应不同声源强度
特别注意要在运放输入端加RC低通滤波(截止频率约3.4kHz),这是为了后续抗混叠采样做准备。实测发现不加这个滤波时,回放声音会有明显的"沙沙"杂音。
3. 软件实现细节
3.1 音频采集处理流程
c复制// 伪代码示例
void ADC_IRQHandler() {
static uint32_t sample_count = 0;
if(sample_count < MAX_SAMPLES) {
raw_data = ADC1->DR; // 读取ADC值
processed_data = apply_companding(raw_data); // μ律压缩
SPI_Flash_Write(processed_data); // 写入Flash
sample_count++;
}
}
采用8kHz采样率+8位分辨率,通过μ律压缩算法(μ=255)将12位ADC数据压缩到8位存储。这样既保证语音可懂度,又节省存储空间。一个实测数据:直接存12位数据只能录18秒,压缩后延长到32秒。
3.2 存储管理方案
SPI Flash按扇区(4KB)管理,设计了一个简单的循环缓冲区:
- 初始化时擦除前8个扇区(共32KB)
- 录音时顺序写入,写满后自动覆盖最早的数据
- 播放时从当前指针位置顺序读取
关键技巧:在扇区边界处添加2字节的帧头(0xAA55),这样即使意外断电,重启后也能通过搜索帧头找到有效数据起始位置。
4. 性能优化技巧
4.1 降低功耗的三种方法
- 动态降频:录音时CPU跑72MHz,待机时降至8MHz
- 智能供电:用MOSFET控制麦克风和运放的电源,5秒无操作自动断电
- 存储延迟写入:积累32个样本后一次性写入Flash,减少频繁擦写
实测这些优化让待机电流从15mA降到3mA,用600mAh的锂电池可以待机一周以上。
4.2 音质提升方案
通过实验对比发现两个有效改进:
- 在ADC采样前加入硬件预加重电路(RC高通,截止频率300Hz),提升语音高频分量
- 软件端实现简单的自动增益控制(AGC),动态调整放大倍数
改造后语音清晰度显著提升,特别是在嘈杂环境中。附上改造前后的频谱对比:
| 频率范围 | 原始方案 | 改进方案 |
|---|---|---|
| 300-1kHz | -18dB | -12dB |
| 1k-3kHz | -24dB | -15dB |
| >3kHz | -30dB | -22dB |
5. 常见问题排查
5.1 录音出现"爆音"
可能原因及解决方案:
- 输入过载:检查第二级运放输出是否超过3V(STM32 ADC最大输入电压)
- 解决方法:调小电位器,或在前级加入钳位二极管
- 电源干扰:示波器查看3.3V电源纹波
- 解决方法:在运放电源脚加100μF+0.1μF去耦电容
5.2 回放时有杂音
典型故障流程排查:
- 先用固定频率正弦波测试(如1kHz)
- 存储前后用串口打印数据,检查数值是否一致
- 测量SPI Flash的CLK线是否有振铃(建议加33Ω串联电阻)
- 检查DAC输出端的低通滤波(建议用二阶RC,截止频率3.4kHz)
6. 扩展应用方向
这个基础框架可以衍生出多个实用变种:
- 工业设备声纹监测:加上FFT分析,识别特定频率的异常声响
- 语音备忘录:增加RTC芯片,录音时打上时间戳
- 低成本对讲机:用两块板子通过NRF24L01无线传输音频数据
最近我正在尝试第三个方案,实测在10米范围内可以实现单向语音传输,延迟约200ms。关键是要在发送端增加ADPCM压缩,把数据量再减少50%。