第38章 I2S—音频播放与录音输入
全套200集视频教程和1000页PDF教程请到秉火论坛下载:www.firebbs.cn
野火视频教程优酷观看网址:http://i.youku.com/firege
本章参考资料:《STM32F4xx 中文参考手册》、《STM32F4xx规格书》、库帮助文档《stm32f4xx_dsp_stdperiph_lib_um.chm》及《I2S BUS》。
若对I2S通讯协议不了解,可先阅读《I2S BUS》文档的内容学习。
关于音频编译码器WM8978,请参考其规格书《WM8978_v4.5》来了解。
38.1 I2S简介
Inter-IC Sount Bus(I2S)是飞利浦半导体公司(现为恩智浦半导体公司)针对数字音频设备之间的音频数据传输而制定的一种总线标准。在飞利浦公司的I2S标准中,既规定了硬件接口规范,也规定了数字音频数据的格式。
38.1.1 数字音频技术
现实生活中的声音是通过一定介质传播的连续的波,它可以由周期和振幅两个重要指标描述。正常人可以听到的声音频率范围为20Hz~20KHz。现实存在的声音是模拟量,这对声音保存和长距离传输造成很大的困难,一般的做法是把模拟量转成对应的数字量保存,在需要还原声音的地方再把数字量的转成模拟量输出,参考图 381。
图 381 音频转换过程
模拟量转成数字量过程,一般可以分为三个过程,分别为采样、量化、编码,参考图 382。用一个比源声音频率高的采样信号去量化源声音,记录每个采样点的值,最后如果把所有采样点数值连接起来与源声音曲线是互相吻合的,只是它不是连续的。在图中两条蓝色虚线距离就是采样信号的周期,即对应一个采样频率(FS),可以想象得到采样频率越高最后得到的结果就与源声音越吻合,但此时采样数据量越越大,一般使用44.1KHz采样频率即可得到高保真的声音。每条蓝色虚线长度决定着该时刻源声音的量化值,该量化值有另外一个概念与之挂钩,就是量化位数。量化位数表示每个采样点用多少位表示数据范围,常用有16bit、24bit或32bit,位数越高最后还原得到的音质越好,数据量也会越大。
图 382 声音数字化过程
WM8978是一个低功耗、高质量的立体声多媒体数字信号编译码器,集成DAC和ADC,可以实现声音信号量化成数字量输出,也可以实现数字量音频数据转换为模拟量声音驱动扬声器。这样使用WM8978芯片解决了声音与数字量音频数据转换问题,并且通过配置WM8978芯片相关寄存器可以控制转换过程的参数,比如采样频率,量化位数,增益、滤波等等。
WM8978芯片是一个音频编译码器,但本身没有保存音频数据功能,它只能接收其它设备传输过来的音频数据进行转换输出到扬声器,或者把采样到的音频数据输出到其它具有存储功能的设备保存下来。该芯片与其他设备进行音频数据传输接口就是I2S协议的音频接口。
38.1.2 I2S总线接口
I2S总线接口有3个主要信号,但只能实现数据半双工传输,后来为实现全双工传输有些设备增加了扩展数据引脚。STM32f42x系列控制器支持扩展的I2S总线接口。
(1) SD(Serial Data):串行数据线,用于发送或接收两个时分复用的数据通道上的数据(仅半双工模式),如果是全双工模式,该信号仅用于发送数据。
(2) WS(Word Select):字段选择线,也称帧时钟(LRC)线,表明当前传输数据的声道,不同标准有不同的定义。WS线的频率等于采样频率(FS)。
(3) CK(Serial Clock):串行时钟线,也称位时钟(BCLK),数字音频的每一位数据都对应有一个CK脉冲,它的频率为:2*采样频率*量化位数,2代表左右两个通道数据。
(4) ext_SD(extend Serial Data):扩展串行数据线,用于全双工传输的数据接收。
另外,有时为使系统间更好地同步,还要传输一个主时钟(MCK),STM32F42x系列控制器固定输出为256* FS。
38.1.3 音频数据传输协议标准
随着技术的发展,在统一的I2S硬件接口下,出现了多种不同的数据格式,可分为左对齐(MSB)标准、右对齐(LSB)标准、I2S Philips标准。另外,STM32F42x系列控制器还支持PCM(脉冲编码调)音频传输协议。下面以STM32F42x系列控制器资源解释这四个传输协议。
STM32f42x系列控制器I2S的数据寄存器只有16bit,并且左右声道数据一般是紧邻传输,为正确得到左右两个声道数据,需要软件控制数据对应通道数据写入或读取。另外,音频数据的量化位数可能不同,控制器支持16bit、24bit和32bit三种数据长度,因为数据寄存器是16bit的,所以对于24bit和32bit数据长度需要发送两个。为此,可以产生四种数据和帧格式组合:
将16位数据封装在16位帧中
将16位数据封装在32位帧中
将24位数据封装在32位帧中
将32位数据封装在32位帧中
当使用32位数据包中的16位数据时,前16位(MSB)为有效位,16位LSB被强制清零,无需任何软件操作或DMA请求(只需一个读/写操作)。如果程序使用DMA传输(一般都会用),则24位和32位数据帧需要对数据寄存器执行两次DMA操作。24位的数据帧,硬件会将8位非有效位扩展到带有0位的32位。对于所有数据格式和通信标准而言,始终会先发送最高有效位(MSB优先)。
1. I2S Philips标准
使用WS信号来指示当前正在发送的数据所属的通道,为0时表示左通道数据。该信号从当前通道数据的第一个位(MSB)之前的一个时钟开始有效。发送方在时钟信号(CK)的下降沿改变数据,接收方在上升沿读取数据。WS信号也在SCK的下降沿变化。参考图 383,为24bit数据封装在32bit帧传输波形。正如之前所说,WS线频率对于采样频率FS,一个WS线周期包括发送左声道和右声道数据,在图中实际需要64个CK周期来完成一次传输。
图 383 I2S Philips标准24bit传输
2. 左对齐标准
在WS发生翻转同时开始传输数据,参考图 384,为24bit数据封装在32bit帧传输波形。该标准较少使用。注意此时WS为1时,传输的是左声道数据,这刚好与I2S Philips标准相反。
图 384 左对齐标准24bit传输
3. 右对齐标准
与左对齐标准类似,参考图 385,为24bit数据封装在32bit帧传输波形。
图 385 右对齐标准24bit传输
4. PCM标准
PCM即脉冲编码调制,模拟语音信号经过采样量化以及一定数据排列就是PCM了。WS不再作为声道数据选择。它有两种模式,短帧模式和长帧模式,以WS信号高电平保持时间为判别依据,长帧模式保持13个CK周期,短帧模式只保持1个CK周期,可以通过相关寄存器位选择。如果有多通道数据是在一个WS周期内传输完成的,传完左声道数据就紧跟发送右声道数据。图 386为单声道数据16bit扩展到32bit数据帧发送波形。
图 386 PCM标准16bit传输
38.2 I2S功能框图
STM32f42x系列控制器有两个I2S,I2S2和I2S3,两个的资源是相互独立的,但分别与SPI2和SPI3共用大部分资源。这样I2S2和SPI2只能选择一个功能使用,I2S3和SPI3相同道理。资源共用包括引脚共用和部分寄存器共用,当然也有部分是专用的。SPI已经在之前相关章节做了详细讲解,建议先看懂SPI相关内容再学习I2S。
控制器的I2S支持两种工作模式,主模式和从模式;主模式下使用自身时钟发生器生成通信时钟。I2S功能框图参考图 387。
图 387 I2S功能框图
1. 功能引脚
I2S的SD映射到SPI的MOSI引脚,ext_SD映射到SPI的MISO引脚,WS映射到SPI的NSS引脚,CK映射到SPI的SCK引脚。MCK是I2S专用引脚,用于主模式下输出时钟或在从模式下输入时钟。I2S时钟发生器可以由控制器内部时钟源分频产生,亦可采用CKIN引脚输入时钟分频得到,一般使用内部时钟源即可。控制器I2S引脚分布参考表 381。
表 381 STM32f42x系列控制器I2S引脚分布
引脚 |
I2S2 |
I2S3 |
SD |
PC3/PB15/PI3 |
PC12/PD6/PB5 |
ext_SD |
PC2/PB14/PI2 |
PC11/PB4 |
WS |
PB12/PI0/PB9 |
PA4/PA15 |
CK |
PB10/PB13/PI1/PD3 |
PC10/PB3 |
MCK |
PC6 |
PC7 |
CKIN |
PC9 |
其中,PI0和PI1不能用于I2S的全双工模式。
2. 数据寄存器
I2S有一个与SPI共用的SPI数据寄存器(SPI_DR),有效长度为16bit,用于I2S数据发送和接收,它实际由三个部分组成,一个移位寄存器、一个发送缓冲区和一个接收缓冲区,当处于发送模式时,向SPI_DR写入数据先保存在发送缓冲区,总线自动把发送缓冲区内容转入到移位寄存器中进行传输;在接收模式下,实际接收到的数据先填充移位寄存器,然后自动转入接收缓冲区,软件读取SPI_DR时自动从接收缓冲区内读取。I2S是挂载在APB1总线上的。
3. 逻辑控制
I2S的逻辑控制通过设置相关寄存器位实现,比如通过配置SPI_I2S配置寄存器(SPI_I2SCFGR)的相关位可以实现选择I2S和SPI模式切换、选择I2S工作在主模式还是从模式并且选择是发送还是接收、选择I2S标准、传输数据长度等等。SPI控制寄存器2(SPI_CR2)可用于设置相关中断和DMA请求使能,I2S有5个中断事件,分别为发送缓冲区为空、接收缓冲区非空、上溢错误、下溢错误和帧错误。SPI状态寄存器(SPI_SR)用于指示当前I2S状态。
4. 时钟发生器
I2S比特率用来确定I2S数据线上的数据流和I2S时钟信号频率。I2S比特率=每个通道的位数×通道数×音频采样频率。
图 388为I2S时钟发生器内部结构图。I2SxCLK(x可选2或3)可以通过RCC_CFGR寄存器的I2SSRC位选择使用PLLI2S时钟作为I2S时钟源或I2S_CKIN引脚输入时钟作为I2S时钟源。一般选择内部PLLI2S(通过R分频系数)作为时钟源。例程程序设置PLLI2S时钟为258MHz,R分频系数为3,此时I2SxCLK时钟为86MHz。
图 388 I2S时钟发生器内部结构
SPI_I2S预分频器寄存器(SPI_I2SPR)的MCKOE位用于设置MCK引脚时钟输出使能;ODD位设置预分频器的奇数因子,实际分频值=I2SDIV*2+ODD;I2SDIV为8位线性分频器,不可设置为0或1。
当使能MCK时钟输出,即MCKOE=1时,采样频率计算如下:
FS = I2SxCLK/[(16*2)*((2*I2SDIV)+ODD)*8)](通道帧宽度为16bit时)
FS = I2SxCLK/[(32*2)*((2*I2SDIV)+ODD)*4)](通道帧宽度为32bit时)
当禁止MCK时钟输出,即MCKOE=0时,采样频率计算如下:
FS = I2SxCLK/[(16*2)*((2*I2SDIV)+ODD))](通道帧宽度为16bit时)
FS = I2SxCLK/[(32*2)*((2*I2SDIV)+ODD))](通道帧宽度为32bit时)
38.3 WM8978音频编译码器
WM8978是一个低功耗、高质量的立体声多媒体数字信号编译码器。它主要应用于便携式应用。它结合了立体声差分麦克风的前置放大与扬声器、耳机和差分、立体声线输出的驱动,减少了应用时必需的外部组件,比如不需要单独的麦克风或者耳机的放大器。
高级的片上数字信号处理功能,包含一个5路均衡功能,一个用于ADC和麦克风或者线路输入之间的混合信号的电平自动控制功能,一个纯粹的录音或者重放的数字限幅功能。另外在ADC的线路上提供了一个数字滤波的功能,可以更好的应用滤波,比如"减少风噪声"。
WM8978可以被应用为一个主机或者一个从机。基于共同的参考时钟频率,比如 12MHz和13MHz,内部的PLL可以为编译码器提供所有需要的音频时钟。与STM32控制器连接使用,STM32一般作为主机,WM8978作为从机。
图 389为WM8978芯片内部结构示意图,参考来自《WM8978_v4.5》。该图给人的第一印象感觉就是很复杂,密密麻麻很多内容,特别有很多"开关"。实际上,每个开关对应着WM8978内部寄存器的一个位,通过控制寄存器的就可以控制开关的状态。
图 389 WM8978内部结构
1. 输入部分
WM8978结构图的左边部分是输入部分,可用于模拟声音输入,即用于录音输入。有三个输入接口,一个是由LIN和LIP、RIN和RIP组合而成的伪差分立体声麦克风输入,一个是由L2和R2组合的立体声麦克风输入,还有一个是由AUXL和AUXR组合的线输入或用来传输告警声的输入。
2. 输出部分
WM8978结构图的右边部分是声音放大输出部分,LOUT1和ROUT1用于耳机驱动,LOUT2和ROUT2用于扬声器驱动,OUT3和OUT4也可以配置成立体声线输出,OUT4也可以用于提供一个左右声道的单声道混合。
3. ADC和DAC
WM8978结构图的中边部分是芯片核心内容,处理声音的AD和DA转换。ADC部分对声音输入进行处理,包括ADC滤波处理、音量控制、输入限幅器/电平自动控制等等。DAC部分控制声音输出效果,包括DAC5路均衡器、DAC 3D放大、DAC输出限幅以及音量控制等等处理。
4. 通信接口
WM8978有两个通信接口,一个是数字音频通信接口,另外一个是控制接口。音频接口是采用I2S接口,支持左对齐、右对齐和I2S标准模式,以及DSP模式A和模拟B。控制接口用于控制器发送控制命令配置WM8978运行状态,它提供2线或3线控制接口,对于STM32控制器,我们选择2线接口方式,它实际就是I2C总线方式,其芯片地址固定为0011010。通过控制接口可以访问WM8978内部寄存器,实现芯片工作环境配置,总共有58个寄存器,标示为R0至R57,限于篇幅问题这里不再深入探究,每个寄存器意义参考《WM8978_v4.5》了解。
WM8978寄存器是16bit长度,高7位([15:9]bit)用于标示寄存器地址,低9为有实际意义,比如对于图 389中的某个开关。所以在控制器向芯片发送控制命令时,必须传输长度为16bit的指令,芯片会根据接收命令高7位值寻址。
5. 其他部分
WM8978作为主从机都必须对时钟进行管理,由内部PLL单元控制。另外还有电源管理单元。
38.4 WAV格式文件
WAV是微软公司开发的一种音频格式文件,用于保存Windows平台的音频信息资源,它符合资源互换文件格式(Resource Interchange File Format,RIFF)文件规范。标准格式化的WAV文件和CD格式一样,也是44.1K的取样频率,16位量化数字,因此在声音文件质量和CD相差无几!WAVE是录音时用的标准的WINDOWS文件格式,文件的扩展名为"WAV",数据本身的格式为PCM或压缩型,属于无损音乐格式的一种。
38.4.1 RIFF文件规范
RIFF有不同数量的chunk(区块)组成,每个chunk由"标识符"、"数据大小"和"数据"三个部分组成,"标识符"和"数据大小"都是占用4个字节空间。简单RIFF格式文件结构参考图 3810。最开始是ID为"RIFF"的chunk,Size为"RIFF"chunk数据字节长度,所以总文件大小为Size+8。一般来说,chunk不允许内部再包含chunk,但有两个例外,ID为"RIFF"和"LIST"的chunk却是允许。对此"RIFF"在其"数据"首4个字节用来存放"格式标识码(Form Type)","LIST"则对应"LIST Type"。
图 3810 RIFF文件格式结构
38.4.2 WAVE文件
WAVE文件是非常简单的一种RIFF文件,其"格式标识码"定义为WAVE。RIFF chunk包括两个子chunk,ID分别为fmt和data,还有一个可选的fact chunk。Fmt chunk用于标示音频数据的属性,包括编码方式、声道数目、采样频率、每个采样需要的bit数等等信息。fact chunk是一个可选chunk,一般当WAVE文件由某些软件转化而成就包含fact chunk。data chunk包含WAVE文件的数字化波形声音数据。WAVE整体结构如表 382。
表 382 WAVE文件结构
标识码("RIFF") |
数据大小 |
格式标识码("WAVE") |
"fmt" |
"fmt"块数据大小 |
"fmt"数据 |
"fact"(可选) |
"fact"块数据大小 |
"fact"数据 |
"data" |
声音数据大小 |
声音数据 |
data chunk是WAVE文件主体部分,包含声音数据,一般有两个编码格式:PCM和ADPCM,ADPCM(自适应差分脉冲编码调制)属于有损压缩,现在几乎不用,绝大部分WAVE文件是PCM编码。PCM编码声音数据可以说是在"数字音频技术"介绍的源数据,主要参数是采样频率和量化位数。
表 383为量化位数为16bit时不同声道数据在data chunk数据排列格式。
表 383 16bit声音数据格式
单声道 |
采样一 |
采样二 |
…… |
||
低字节 |
高字节 |
低字节 |
高字节 |
…… |
|
双声道 |
采样一 |
…… |
|||
左声道 |
右声道 |
…… |
|||
低字节 |
高字节 |
低字节 |
高字节 |
…… |
38.4.3 WAVE文件实例分析
利用winhex工具软件可以非常方便以十六进制查看文件,图 3811为名为"张国荣-一盏小明灯.wav"文件使用winhex工具打开的部分界面截图。这部分截图是WAVE文件头部分,声音数据部分数据量非常大,有兴趣可以使用winhex查看。
图 3811 WAV文件头实例
下面对文件头进行解读,参考表 384。
表 384 WAVE文件格式说明
|
偏移地址 |
字节数 |
数据类型 |
十六进制源码 |
内容 |
文件头 |
00H |
4 |
char |
52 49 46 46 |
"RIFF"标识符 |
04H |
4 |
long int |
F4 FE 83 01 |
文件长度:0x0183FEF4(注意顺序) |
|
08H |
4 |
char |
57 41 56 45 |
"WAVE"标识符 |
|
0CH |
4 |
char |
66 6D 74 20 |
"fmt ",最后一位为空格 |
|
10H |
4 |
long int |
10 00 00 00 |
fmt chunk大小:0x10 |
|
14H |
2 |
int |
01 00 |
编码格式:0x01为PCM。 |
|
16H |
2 |
int |
02 00 |
声道数目:0x01为单声道,0x02为双声道 |
|
18H |
4 |
int |
44 AC 00 00 |
采样频率(每秒样本数):0xAC44(44100) |
|
1CH |
4 |
long int |
10 B1 02 00 |
每秒字节数:0x02B110,等于声道数*采样频率*量化位数/8 |
|
20H |
2 |
int |
04 00 |
每个采样点字节数:0x04,等于声道数*量化位数/8 |
|
22H |
2 |
int |
10 00 |
量化位数:0x10 |
|
24H |
4 |
char |
64 61 74 61 |
"data"数据标识符 |
|
28H |
4 |
long int |
48 FE 83 01 |
声音数据量:0x0183FE48 |
38.5 I2S初始化结构体详解
标准库函数对I2S外设建立了一个初始化结构体I2S_InitTypeDef。初始化结构体成员用于设置I2S工作环境参数,并由I2S相应初始化配置函数I2S_Init调用,这些设定参数将会设置I2S相应的寄存器,达到配置I2S工作环境的目的。
初始化结构体和初始化库函数配合使用是标准库精髓所在,理解了初始化结构体每个成员意义基本上就可以对该外设运用自如了。初始化结构体定义在stm32f4xx_spi.h文件中,初始化库函数定义在stm32f4xx_spi.c文件中,编程时我们可以结合这两个文件内注释使用。
I2S初始化结构体用于配置I2S基本工作环境,比如I2S工作模式、通信标准选择等等。它被I2S_Init函数调用。
代码清单 381 I2S_InitTypeDef结构体
1 typedef struct {
2 uint16_t I2S_Mode; // I2S模式选择
3 uint16_t I2S_Standard; // I2S标准选择
4 uint16_t I2S_DataFormat; // 数据格式
5 uint16_t I2S_MCLKOutput; // 主时钟输出使能
6 uint32_t I2S_AudioFreq; // 采样频率
7 uint16_t I2S_CPOL; // 空闲电平选择
8 } I2S_InitTypeDef;
(1) I2S_Mode:I2S模式选择,可选主机发送、主机接收、从机发送以及从机接收模式,它设定SPI_I2SCFGR寄存器I2SCFG位的值。一般设置STM32控制器为主机模式,当播放声音时选择发送模式;当录制声音时选择接收模式。
(2) I2S_Standard:通信标准格式选择,可选I2S Philips标准、左对齐标准、右对齐标准、PCM短帧标准或PCM长帧标准,它设定SPI_I2SCFGR寄存器I2SSTD位和PCMSYNC位的值。一般设置为I2S Philips标准即可。
(3) I2S_DataFormat:数据格式选择,设定有效数据长度和帧长度,可选标准16bit格式、扩展16bit(32bit帧长度)格式、24bit格式和32bit格式,它设定SPI_I2SCFGR寄存器DATLEN位和CHLEN位的值。对应16bit数据长度可选16bit或32bit帧长度,其他都是32bit帧长度。
(4) I2S_MCLKOutput:主时钟输出使能控制,可选使能输出或禁止输出,它设定SPI_I2SPR寄存器MCKOE位的值。为提高系统性能一般使能主时钟输出。
(5) I2S_AudioFreq:采样频率设置,标准库提供采样采样频率选择,分别为8kHz、11kHz、16kHz、22kHz、32kHz、44kHz、48kHz、96kHz、192kHz以及默认2Hz,它设定SPI_I2SPR寄存器的值。
(6) I2S_CPOL:空闲状态的CK线电平,可选高电平或低电平,它设定SPI_I2SCFGR寄存器CKPOL位的值。一般设置为电平即可。
38.6 录音与回放实验
WAV格式文件在现阶段一般以无损音乐格式存在,音质可以达到CD格式标准。结合上一章SD卡操作内容,本实验通过FatFS文件系统函数从SD卡读取WAV格式文件数据,然后通过I2S接口将音频数据发送到WM8978芯片,这样在WM8978芯片的扬声器接口即可输出声音,整个系统构成一个简单的音频播放器。反过来的,我们可以实现录音功能,控制启动WM8978芯片的麦克风输入功能,音频数据从WM8978芯片的I2S接口传输到STM32控制器存储器中,利用SD卡文件读写函数,根据WAV格式文件的要求填充文件头,然后就把WM8978传输过来的音频数据写入到WAV格式文件中,这样就可以制成一个WAV格式文件,可以通过开发板回放也可以在电脑端回放。
38.6.1 硬件设计
开发板板载WM8978芯片,具体电路设计参考图 3812。WM8978与STM32f42x有两个连接接口,I2S音频接口和两线I2C控制接口,通过将WM8978芯片的MODE引脚拉低选择两线控制接口,符合I2C通信协议,这也导致WM8978是只写的,所以在程序上需要做一些处理。WM8978输入部分有两种模式,一个是板载咪头输入,另外一个是通过3.5mm耳机插座引出。WM8978输出部分通过3.5mm耳机插座引出,可直接接普通的耳机线或作为功放设备的输入源。
图 3812 WM8978电路设计
38.6.2 软件设计
这里只讲解核心的部分代码,有些变量的设置,头文件的包含等没有全部罗列出来,完整的代码请参考本章配套的工程。
上一章我们已经介绍了基于SD卡的文件系统,认识读写SD卡内文件方法,前面已经介绍了WAV格式文件结构以及WM8978芯片相关内容,通过WM8978音频接口传输过来的音频数据可以直接作为WAV格式文件的音频数据部分,大致过程就是程序控制WM8978启动录音功能,通过I2S音频数据接口WM8978的录音输出传输到STM32控制器指定缓冲区内,然后利用FatFs的文件写入函数把缓冲区数据写入到WAV格式文件中,最终实现声音录制功能。同样的道理,WAV格式文件中的音频数据可以直接传输给WM8978芯片实现音乐播放,整个过程与声音录制工程相反。
STM32控制器与WM8978通信可分为两部分驱动函数,一部分是I2C控制接口,另一部分是I2S音频数据接口。
bsp_wm8978.c和bsp_wm8978.h两个是专门创建用来存放WM8978芯片驱动代码。
1. I2C控制接口
WM8978要正常工作并且实现符合我们的要求,我们必须对芯片相关寄存器进行必须要配置,STM32控制器通过I2C接口与WM8978芯片控制接口连接。I2C接口内容也已经在以前做了详细介绍,这里主要讲解WM8978的功能函数。
bsp_wm8978.c文件中的I2C_GPIO_Config函数、I2C_Mode_Configu函数以及wm8978_Init函数用于I2C通信接口GPIO和I2C相关配置,属于常规配置可以参考GPIO和I2C章节理解,这里不再分析,代码具体见本章配套程序工程文件。
输入输出选择枚举
代码清单 382 输入输出选择枚举
1 /* WM8978 音频输入通道控制选项, 可以选择多路,比如 MIC_LEFT_ON | LINE_ON */
2 typedef enum {
3 IN_PATH_OFF = 0x00, /* 无输入 */
4 MIC_LEFT_ON = 0x01, /* LIN,LIP脚,MIC左声道(接板载咪头) */
5 MIC_RIGHT_ON = 0x02, /* RIN,RIP脚,MIC右声道(接板载咪头) */
6 LINE_ON = 0x04, /* L2,R2 立体声输入(接板载耳机插座) */
7 AUX_ON = 0x08, /* AUXL,AUXR 立体声输入(开发板没用到) */
8 DAC_ON = 0x10, /* I2S数据DAC (CPU产生音频信号) */
9 ADC_ON = 0x20 /* 输入的音频馈入WM8978内部ADC (I2S录音) */
10 } IN_PATH_E;
11
12 /* WM8978 音频输出通道控制选项, 可以选择多路 */
13 typedef enum {
14 OUT_PATH_OFF = 0x00, /* 无输出 */
15 EAR_LEFT_ON = 0x01, /* LOUT1 耳机左声道(接板载耳机插座) */
16 EAR_RIGHT_ON = 0x02, /* ROUT1 耳机右声道(接板载耳机插座) */
17 SPK_ON = 0x04, /* LOUT2和ROUT2反相输出单声道(开发板没用到)*/
18 OUT3_4_ON = 0x08, /* OUT3 和 OUT4 输出单声道音频(开发板没用到)*/
19 } OUT_PATH_E;
IN_PATH_E和OUT_PATH_E枚举了WM8978芯片可用的声音输入源和输出端口,具体到开发板,如果进行录用功能,设置输入源为(MIC_RIGHT_ON|ADC_ON)或(LINE_ON|ADC_ON),设置输出端口为OUT_PATH_OFF或(EAR_LEFT_ON | EAR_RIGHT_ON);对于音乐播放功能,设置输入源为DAC_ON,设置输出端口为(EAR_LEFT_ON | EAR_RIGHT_ON)。
宏定义
代码清单 383 宏定义
1 /* 定义最大音量 */
2 #define VOLUME_MAX 63 /* 最大音量 */
3 #define VOLUME_STEP 1 /* 音量调节步长 */
4
5 /* 定义最大MIC增益 */
6 #define GAIN_MAX 63 /* 最大增益 */
7 #define GAIN_STEP 1 /* 增益步长 */
8
9 /* STM32 I2C 快速模式 */
10 #define WM8978_I2C_Speed 400000
11 /* WM8978 I2C从机地址 */
12 #define WM8978_SLAVE_ADDRESS 0x34
13
14 /*I2C接口*/
15 #define WM8978_I2C I2C1
16 #define WM8978_I2C_CLK RCC_APB1Periph_I2C1
17
18 #define WM8978_I2C_SCL_PIN GPIO_Pin_6
19 #define WM8978_I2C_SCL_GPIO_PORT GPIOB
20 #define WM8978_I2C_SCL_GPIO_CLK RCC_AHB1Periph_GPIOB
21 #define WM8978_I2C_SCL_SOURCE GPIO_PinSource6
22 #define WM8978_I2C_SCL_AF GPIO_AF_I2C1
23
24 #define WM8978_I2C_SDA_PIN GPIO_Pin_7
25 #define WM8978_I2C_SDA_GPIO_PORT GPIOB
26 #define WM8978_I2C_SDA_GPIO_CLK RCC_AHB1Periph_GPIOB
27 #define WM8978_I2C_SDA_SOURCE GPIO_PinSource7
28 #define WM8978_I2C_SDA_AF GPIO_AF_I2C1
29
30 /*等待超时时间*/
31 #define WM8978_I2C_FLAG_TIMEOUT ((uint32_t)0x4000)
32 #define WM8978_I2C_LONG_TIMEOUT ((uint32_t)(10 * WM8978_I2C_FLAG_TIMEOUT))
WM8978声音调节有一定的范围限制,比如R52(LOUT1 Volume Control)的LOUT1VOL[5:0]位用于设置LOUT1