设为首页 加入收藏

TOP

AIR32F103(六) ADC,I2S,DMA和ADPCM实现的录音播放功能(一)
2023-07-23 13:32:07 】 浏览:169
Tags:AIR32F103 ADC I2S DMA ADPCM

目录

关于

使用AIR32的ADC, I2S 和 DMA 实现简单的语音录音和播放功能, 以及使用 ADPCM 编码提升录音时长. 使用的MCU型号为 AIR32F103CCT6. 如果用CBT6, 对应的音频数据数组大小需要相应减小.

音频录音和播放

工作方式

加电后开始录音, 录音结束后循环播放

  • 录音: 麦克风模块 -> ADC采样(12bit, 8K, 11K 或 16K) -> 存储在内存
  • 播放: I2S -> I2S外设(MAX98357A / PT8211) -> 喇叭

对中间每个环节的说明

存储

首先是存储, MCU的内存有限, 如果不借助AT24C, MX25L这类外部存储, 只用内存存储的数据是有限的, AIR32F103CCT6 带 64K Byte内存, 如果按原始采样值存储, 录音时长为

  • 16bit
    • 8K: 128kbps, 约4秒
    • 11K: 176kbps, 约3秒
    • 16K: 256kbps, 约2秒
  • 8bit
    • 8K: 64kbps, 约8秒
    • 11K: 88kbps, 约6秒
    • 16K: 128kbps, 约4秒

采样

使用AIR32的ADC, 配合定时器实现精确的每秒8K, 11K和16K采样. AIR32的ADC分辨率和STM32F103一样都是固定的12bit(STM32F4之后才可以用寄存器调节分辨率)

  • 如果使用ADC的中断, 可以向高位偏移做成16bit, 也可以去掉低位做成8bit
  • 如果使用DMA, 因为AIR32不能像STM32那样, 在4字节地址上偏移一个字节取值, 所以只能按16bit(halfword)传值

音频采集设备如果直接用驻极体话筒, 采样的信号很弱(不是没有, 但是非常小), 需要加一个三极管做放大. 也可以买成品的 MAX9814 模块. 两者的效果区别不大, 但是在调试阶段, 建议用 MAX9814, 因为不用担心信号是否过饱和和失真问题, 在调通之后, 再换回低成本的驻极体话筒和三极管.

驻极体话筒放大的电路和元件参数可以参考这一篇 https://www.cnblogs.com/milton/p/15315783.html

播放

播放可以使用PWM转DAC, 也可以直接用I2S.

  • 如果使用PWM, 因为PWM本身是方波, 会产生大量的谐振噪音, 只有将PWM频率设置到16KHz以上才能明显降低噪音(因为谐振频率超出人耳的听觉范围了), 用8KHz时的噪音非常明显.
  • 因为AIR32F103全系列都支持I2S(数据手册上写只有RPT7才有, 实际上CBT6和CCT6也有), 所以直接用I2S输出是最简单的. 这时候需要一个能接收I2S输出并转为音频的模块.

I2S模块可以用 MAX98357A 模块, 自带I2S解码和放大可以直连喇叭, 也可以买PT8211/TM8211/GH8211, 0.3元一片非常便宜还是双声道, 缺点是不带功放, 如果直连喇叭得贴着耳朵才能听到, 可以再加一个LM386或者PAM8403做放大, 都非常便宜.

实现

硬件

  • AIR32F103CCT6
  • MAX9814
  • PT8211
  • 8欧小喇叭

接线

 *   AIR32F103                  MAX98357A / PT8211
 *   PB13(SPI1_SCK/I2S_CK)       -> BCLK, BCK
 *   PB15(SPI1_MOSI/I2S_SD)      -> DIN
 *   PB12(SPI1_NSS/I2S_WS)       -> LRC, WS
 *                               GND  -> GND
 *                               VIN  -> 3.3V
 *                               +    -> speaker
 *                               -    -> speaker
 * 
 *   AIR32F103                  MAX9814
 *   PA2                        -> Out
 *   3.3V                       -> VDD
 *   GND                        -> GND
 *   GND                        -> A/R
 *                                 GAIN -> float:60dB, gnd:50dB, 3.3v:40dB

代码

完整的示例代码

定义了全局变量

// 定义不同的AUDIO_FREQ值, 可以切换不同的采样频率, 8K, 11K, 16K, 越高的采样频率, 音质越好, 录音时长越短
#define AUDIO_FREQ 8000
//#define AUDIO_FREQ 11000
//#define AUDIO_FREQ 16000

// 定义存储的音频数据大小, CCT6用的是30000, CBT6 或 RPT6 可以相应的减小或增大
#define BUFF_SIZE 30000

// 音频数据数组, 同时用于DMA的接收地址
uint16_t dma_buf[BUFF_SIZE];

// I2S传输时, 用于记录传输的位置
uint32_t index;
// I2S传输时, 用于区分左右声道
__IO uint8_t lr = 0;

初始化GPIO, PA2是采样输入, PB12, PB13, PB15 用于I2S传输, PC13 是板载的LED, 用于指示录音开始和结束. 如果使用的不是Bluepill而是合宙的开发板, 可以修改为开发板对应的LED GPIO.

void GPIO_Configuration(void)
{
    GPIO_InitTypeDef GPIO_InitStructure;
    // PA2 as analog input
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_2;
    GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AIN;
    GPIO_Init(GPIOA, &GPIO_InitStructure);
    // PB12,PB13,PB15 as I2S AF output
    GPIO_InitStructure.GPIO_Pin = GPIO_Pin_12 | GPIO_Pin_13 | GPIO_Pin_15; 
    GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
首页 上一页 1 2 3 4 下一页 尾页 1/4/4
】【打印繁体】【投稿】【收藏】 【推荐】【举报】【评论】 【关闭】 【返回顶部
上一篇驱动开发学习笔记---阻塞和非阻塞.. 下一篇驱动开发学习笔记---并发与竞争

最新文章

热门文章

Hot 文章

Python

C 语言

C++基础

大数据基础

linux编程基础

C/C++面试题目