210学习日记(14)_支持声卡

来源:互联网 发布:mysql安全配置 编辑:程序博客网 时间:2024/06/07 07:25

210学习日记(14)

--支持声卡

我想,声卡一定是大家比较喜欢和关注的吧。接下来我将S3C2440S5PV210的声卡部分进行对比讲解。

IIS(Inter-IC Sound)由飞利浦公司开发,是一种常用的音频设备接口,主要用于CD、MD、MP3等设备。

1.播放音频的过程:

                       IIS接口发送声音

  DDR——>S5PV210——————————>解码芯片WM8960(DAC的过程)——>耳机

2.录音的过程:

                                           IIS接收声音数据

  MIC——>编码芯片WM8960(ADC的过程)———————————>S5PV210——>DDR

3.IIS接口(共有5个引脚用于IIS)

LRCK----------------------------------左右声道控制信号

SCLK----------------------------------串行时钟

SDI-------------------------------------数据输入

SDO------------------------------------数据输出

CDCLK--------------------------------为编解码芯片提供系统同步时钟

从上面可以看出,有三个引脚都与音频信号的频率有关,可见要用好IIS,就要把信号频率设置正确。 SCLK为串行时钟(也叫位时钟BCLK ),每一个时钟信号传送一位音频信号,因此SCLK的频率=声道数×采样频率×采样位数,如采样频率fs为44.1kHz,采样的位数为16位,声道数2个(左、右两个声道),则SCLK的频率=32fs=1411.2kHz。

LRCK为帧时钟,用于切换左、右声道,如LRCK为高电平表示正在传输的是左声道数据,为低电平表示正在传输的是右声道数据,因此LRCK的频率应该正好等于采样频率。

CDCLK为系统时钟,由于IIS只负责数字音频信号的传输,而要真正实现音频信号的放、录,还需要额外的处理芯片(以UDA1341,WM8960为例),CDCLK为该芯片提供系统同步时钟,即编解码时钟,主要用于音频的A/D、D/A采样时的采样时钟,一般CDCLK为256fs或384fs。

通过以上分析可以发现,采样频率fs对频率的设置至关重要。而fs不是任意设置的,一般基于不同的应用场合和听觉效果,而设置不同的几个固定的值,如8kHz、16kHz、22.05kHz、44.1kHz、48kHz、96kHz等。为了使系统得到以fs为基数的各类时钟信号,就要精心计算系统时钟(CDCLK)。

以下将分别讲述如何设置S3C2440S5PV210向外提供的系统时钟CDCLK和IIS的时钟源:

(1).s3c2440用于IIS的时钟源有PCLK和MPLLin,以PCLK作为IIS的时钟源为例。

PCLK经过两个预分频器处理后分别得到SCLK、LRCK和CDCLK(预分频器A得到SCLK、LRCK,预分频器B得到CDCLK)。寄存器IISPSR是IIS预分频器寄存器,5~9位是预分频器A,0~4位是预分频器B,一般来说,这两个预分频器的值N相等,即只要知道一个,另一个也就知道。以CDCLK来计算预分频器B的值N为例,即CDCLK=PCLK / (N+1),PCLK与FCLK有一定的比例关系,而FCLK又是由输入频率Fin得到。在这里,我们为了简化计算,不改变PCLK与FCLK的比例关系(即维持在启动代码中定义的1:8的关系),那么由Fin而得到CDCLK一共涉及到四个参数:MDIV、PDIV、SDIV和前面公式中的N,涉及到的寄存器有MPLLCON和IISPSR。因此要得到这四个参数值,就需要一点耐心地计算,原则是误差最小,其中需要注意的是,计算的结果(包括中间过程的结果)不要溢出,即不要超过32位。例如Fin为12MHz,我们设置采样频率fs=44.1kHz,而CDCLK=384fs=16.9344MHz,那么经过计算,最终得到N=3,MDIV=150,PDIV=5,SDIV=0,即时钟相关的代码如下:

IISPSR = (3<<5) | 3;,MPLLCON = (150<<12) | (5<<4) | 0;

(2).S5PV210用于IIS的时钟源有Audio bus clock和I2SCLK,以I2SCLK作为IIS的时钟源为例。

关于时钟的设置,我在前面的日志中讲过一句非常重要的话,就是一定要找到对应时钟的图,这样才能够知道时钟源之间的来龙去脉,否则完全不知道设置什么(关系太多太复杂),该图如下:

注:上图在S5PV210的芯片手册的1864页能够找到!!

我们假设设置采样频率fs=44.1kHz(事实我们要播放的wav文件的采样频率确实是这么多,可以从它的头部信息中得到),CDCLK=256fs,而且IISPSR的预分频值N5(事实我们后面初始化WM8960时也是这样设置的)

那么,I2SCLK = (5 + 1) * CDCLK = 6 * 256 * 44.1kHz = 67.7Mhz

从上图可以看出,I2SCLK是由MUXi2sa_OUT经过分频系数分频得到的,为了便于计算,我们就将该分频系数设置为(0 + 1)好了,而MUXi2sa_OUT的来源,我们选择为Main Clk(CLKMUX_ASS_out),而CLKMUX_ASS_out的时钟来源,我们就选为FOUT_EPLL好了。

经过一系列的选择,最终得出要求是:

FOUT_EPLL = 67.7Mhz

那么,FOUT_EPLL又由谁来设置呢?

S5PV210的芯片手册的361页的图中可以看出,FOUT_EPLL就是EPLL锁相环的输出,因此我们只需要设置该锁相环,让它输出67.7Mhz就行了,就算公式如下:

FOUT = (MDIV + K / 65536) * FIN / (PDIV * 2的SDIV次方)

最终得出IIS的时钟的初始化相关代码如下:

/* 设置锁相环

 * SDIV [2:0]  : SDIV = 0x3

 * PDIV [13:8] : PDIV = 0x3

 * MDIV [24:16]: MDIV = 0x43

 * LOCKED  [29]: 1 = 使能锁

 * ENABLE  [31]: 1 = 使能锁相环

 *

 * Fout = (0x43+0.7)*24M / (3 * 2^3) = 67.7*24M/24 = 67.7Mhz

 */

EPLL_CON0 = 0xa8430303; /* MPLL_FOUT = 67.7Mhz */

EPLL_CON1 = 0xbcee;          /* K = 0xbcee */

/* 时钟源的设置

 * APLL_SEL[0] :1 = FOUTAPLL

 * MPLL_SEL[4] :1 = FOUTMPLL

 * EPLL_SEL[8] :1 = FOUTEPLL

 * VPLL_SEL[12]:1 = FOUTVPLL

 * MUX_MSYS_SEL[16]:0 = SCLKAPLL

 * MUX_DSYS_SEL[20]:0 = SCLKMPLL

 * MUX_PSYS_SEL[24]:0 = SCLKMPLL

 * ONENAND_SEL [28]:1 = HCLK_DSYS

 */

CLK_SRC0 = 0x10001111;

/* 时钟源的进一步设置(AUDIO SUBSYSTEMCLK SRC)

 * bit[3:2]: 00 = MUXi2s_a_out来源于Main CLK

 * bit[0]  : 1 = Main CLK来源于FOUT_EPLL

 */

CLK_CON = 0x1;

/* 由于AUDIO SUBSYSTEMCLK DIV寄存器使用的是默认值,故分频系数为1 */

注意:

Fs是指采样频率,即每秒钟取样数,该参数的值在WAV音频文件中是查得到的,而且该参数在时钟的设置中至关重要,时钟的设置,也是至关重要的,直接关系到声音是否能够播放成功的问题!!

以下将对比S3C2440S5PV210IIS相关寄存器:

(1).S3C2440有关IIS的寄存器除了IISPSR外,还包括IIS控制寄存器IISCON,主要用于控制数据传输的方式、预分频器和IIS接口是否开启;IIS模式寄存器IISMOD,主要用于设置IIS的时钟源、主从方式、接收发送方式、串行接口方式、每个声道串行数据位数和各种频率值;IIS的FIFO接口寄存器IISFCON用于设置和判断数据传输的FIFO状态;而寄存器IISFIFO则用于音频数据的传输。

(2).S5PV210有关IIS的寄存器除了IISPSR外,还包括IIS控制寄存器IISCON,主要用于控制数据传输的方式(是否使用DMA)、IIS接口是否开启;IIS模式寄存器IISMOD,主要用于设置IIS的时钟源、主从方式、串行接口方式、设置和判断数据传输的FIFO状态和每个声道串行数据位数和各种频率值;IIS的IISTXD寄存器用于发送数据;而IISRXD寄存器则用于接收数据。

从以上两点可以看出,S3C2440S5PV210IIS大同小异。

所以,最终的IIS初始化函数如下:(包括时钟的初始化)

void IIS_init(void)

{

/* 设置对应GPIO用于IIS */

GPICON = 0x22222222;

/* 设置锁相环

 * SDIV [2:0]  : SDIV = 0x3

 * PDIV [13:8] : PDIV = 0x3

 * MDIV [24:16]: MDIV = 0x43

 * LOCKED  [29]: 1 = 使能锁

 * ENABLE  [31]: 1 = 使能锁相环

 *

 * Fout = (0x43+0.7)*24M / (3 * 2^3) = 67.7*24M/24 = 67.7Mhz

 */

EPLL_CON0 = 0xa8430303; /* MPLL_FOUT = 67.7Mhz */

EPLL_CON1 = 0xbcee;          /* K = 0xbcee */

/* 时钟源的设置

 * APLL_SEL[0] :1 = FOUTAPLL

 * MPLL_SEL[4] :1 = FOUTMPLL

 * EPLL_SEL[8] :1 = FOUTEPLL

 * VPLL_SEL[12]:1 = FOUTVPLL

 * MUX_MSYS_SEL[16]:0 = SCLKAPLL

 * MUX_DSYS_SEL[20]:0 = SCLKMPLL

 * MUX_PSYS_SEL[24]:0 = SCLKMPLL

 * ONENAND_SEL [28]:1 = HCLK_DSYS

 */

CLK_SRC0 = 0x10001111;

/* 时钟源的进一步设置(AUDIO SUBSYSTEMCLK SRC)

 * bit[3:2]: 00 = MUXi2s_a_out来源于Main CLK

 * bit[0]  : 1 = Main CLK来源于FOUT_EPLL

 */

CLK_CON = 0x1;

/* 由于AUDIO SUBSYSTEMCLK DIV寄存器使用的是默认值,故分频系数为1 */

// IISCDCLK  11.289Mhz = 44.1K * 256fs 

// IISSCLK    1.4112Mhz = 44.1K * 32fs

// IISLRCLK   44.1Khz

/* 预分频值

 * bit[13:8] : N = 5

 * bit[15]   : 使能预分频

 */

IISPSR = 1<<15 | 5<<8;

/* 设置IIS控制器

 * bit[0]: 1 = 使能IIS

 */

IISCON |= 1<<0 | (unsigned)1<<31;

/* 设置各个时钟输出

 * bit[2:1]:IISSCLK(位时钟)  44.1K * 32fs = 1.4112Mhz

 * bit[3:4]:IISCDCLK(系统时钟) 44.1K * 256fs = 11.289Mhz

 * bit[9:8]:10 = 既可以发送又可以接收

 * bit[10] :0 = PCLK is internal source clock for IIS 

 */

IISMOD = 1<<9 | 0<<8 | 1<<10;

}

以下将对比UDA1341和WM8960的控制方式:

我们从原理图上可以看出:

(1).UDA1341:

s3c2440与UDA1341之间除了我们前面介绍过的IIS接口相连接外,还有一个称之为L3总线的连接,用于s3c2440配置UDA1341内部的寄存器。由于s3c2440不具备L3总线接口,因此我们是用三个通用IO口来模拟L3,从而实现L3总线的传输。UDA1341有两种模式:地址模式和数据传输模式。地址模式表示传输的是地址信息,它的高6位永远是000101,低两位表示的是传输的模式,是状态模式、数据0模式还是数据1模式,其中状态模式主要用于配置UDA1341的各类初始状态,数据模式主要用于改善音频输入、输出的效果。

L3总线控制传输:

地址模式(L3MODE=0时进入地址模式,L3DAT传输的为地址)

是用于选择设备和定义目标寄存器,在这种模式下,8位数据高6位是设备地址(UDA1341的地址固定为000101),低两位是数据模式下选择的寄存器(00:DATA0,01:DATA1,10:STATUS)。只要没有再改变地址模式下的数据,则数据模式下的数据始终是传输到上一个地址模式所定义的寄存器内。

地址模式时序为: L3MODE置电平->L3CLOCK置高电平->L3CLOCK置低电平->写一位地址->延时->L3CLOCK置高电平->L3CLOCK置低电平,开始写地址下一位->...8位地址写完->L3MODE,L3CLOCK置高电平。

数据模式(L3MODE=1时进入数据模式,L3DAT传输的为数据)

用于设置寄存器。此模式下,STATUS用于设置复位,系统时钟频率,数据输入格式,直流滤波器,输入增益开关,输出增益开关;DATA0分为直接寻址模式和扩展寻址模式,直接寻址模式是直接进行模式的控制,包括音量、重低音、高音、峰值检测位置、去加重、静音和模式,而扩展寻址模式是在直接寻址模式下先设置3位扩展地址,再在直接寻址模式下设置5位扩展数据,包括数字混音器控制、自动增益控制、麦克灵敏度控制、输入增益、自动增益时间常数及输出等级;在DATA1下,可以读取到被检测峰值。

时序为L3CLOCK置低电平->写一位数据->延时->L3CLOCK置高电平->L3CLOCK置低电平,开始写下一位数据->...8位数据写完,向之前写入的地址地址,一次写数据完成。

注意:

无论是地址模式,还是数据模式,传输的数据时,都是先发送低位的数据!!!

STATUS 控制寄存器

D7

D6

D5

D4

D3

D2

D1

D0

0

RST

SC1

SC0

IF2

IF1

IF0

DC

1

OGS

IGS

PAD

PDA

DS

PC1

PC0

D7=0:

RST(复位),1:复位,0:不复位;

SC1:SC0(系统时钟设置,fs表示的是采样频率):

0 0          512fs

0 1          384fs

1 0          256fs

1 1          不使用

系统时钟应和数据输入总线系统时钟一致,如IIS总线输入,则系统时钟应和IIS总线频率一致。系统时钟是由IIS总线的SCLK来设置的,当SCLK频率确定以后,就可以根据以上信息(512fs)来计算出fs(采样频率),当然也可以先确定fs,然后根据fs去计算出SCLK(系统时钟),然后再去设置IIS的系统时钟。

IF2:IF1:IF0(数据输入模式选择,即数据传输遵循的是什么协议(比如IIS协议等等)):

0 0 0      IIS总线(S3C2440支持该协议)

0 0 1      最低有效位对齐的16位

0 1 0      最低有效位对齐的18位

0 1 1      最低有效位对齐的20位

1 0 0      最高有效位对齐

1 0 1      最低有效位对齐的16位输入和最高有效位对齐的输出

1 1 0      最低有效位对齐的18位输入和最高有效位对齐的输出

1 1 1      最低有效位对齐的20位输入和最高有效位对齐的输出

DC(直流滤波器使能):0 禁用,1 使能;

D7=1:

OGS(输出增益开关) 0 增益为0,      1 增益6dB

IGS (输入增益开关) 0 增益为0,     1 增益6dB

PAD (ADC极性)    0 不反相,       1 反相

PDA (DAC极性)    0 不反相,       1 反相

DS  (双倍速设置)   0 单倍数回放    1 双倍速回放

PC1:PC0(电源控制)

0 0          ADC电源切断,DAC电源切断

0 1          ADC电源切断,DAC电源接通

1 0          ADC电源接通,DAC电源切断

1 1          ADC电源接通,DAC电源接通

DATA0 直接控制寄存器

D7

D6

D5

D4

D3

D2

D1

D0

0

0

VC5

VC4

VC3

VC2

VC1

VC0

0

1

BB3

BB2

BB1

BB0

TR1

TR0

1

0

PP

DE1

DE0

MT

M1

M0

1

1

0

0

0

EA2

EA1

EA0

1

1

1

ED4

ED3

ED2

ED1

ED0

VC5:VC4:VC3:VC2:VC1:VC0(音量控制,该处的值越大,声音越小):

BB3 :BB2 :BB1: BB0(低音增强):

TR1:TR0(高音增强)

PP(峰值检测位置): 0 音调特性之前 1 音调特性之后

DE1: DE0(去加重):

0 0                               不去加重

0 1                               32kHz去加重

1 0                               44.1kHz去加重

1 1                               48kHz去加重

MT(静音):              0 不静音 1 静音

M1:M0(音频滤波模式选择):

0 0                               平均值

0 1/1 0                         最小值

1 1                               最大值

EA2 EA1 EA0 (扩展地址,代表着一个扩展的寄存器),ED4 ED3 ED2 ED1 ED0(扩展数据,代表着要像扩展寄存器写入的数据)

DATA0扩展编程寄存器         |    扩展编程寄存器中将写入的值

EA2

EA1

EA0

ED4

ED3

ED2

ED1

ED0

0

0

0

MA4

MA3

MA2

MA1

MA0

0

0

1

MB4

MB3

MB2

MB1

MB0

0

1

0

MS2

MS1

MS0

MM1

MM0

1

0

0

AG

0

0

IG1

IG0

1

0

1

IG6

IG5

IG4

IG3

IG2

1

1

0

AT2

AT1

AT0

AL1

AL0

MA4:MA3:MA2:MA1:MA0(控制通道1的混频增益)

MB4:MB3:MB2:MB1:MB0(控制通道2的混频增益)

MS2:MS1:MS0(麦克风敏感度)

选择麦克风增益放大,只有当AGC(自动增益)使能,而不是在激活双差模式,这些设置才有效。

MM1:MM0(混频器模式选择) 

MM1

MM0

选择模式

0

0

双差模式

0

1

选择输入通道1,输入通道2切断

1

0

选择输入通道2,输入通道1切断

1

1

数字混频器模式(input 1×MA + input 2×MB)

AG(AGC使能) 0 禁用,手工设置增益(通过IG设置) 1 使能

IG6:IG5:IG4:IG3:IG2:IG1:IG0(输入通道2放大器增益)

仅当AG禁用且不在双差模式下有效。

AT2:AT1:AT0:AL1:AL0(自动增益控制时间常数)

AT2

AT1

AT0

启动时间

(ms)

衰减时间

(ms)

0

0

0

11

100

0

0

1

16

100

0

1

0

11

200

0

1

1

16

200

1

0

0

21

200

1

0

1

11

400

1

1

0

16

400

1

1

1

21

400

 

AL1:AL0(自动增益输出电平)

AL1

AL0

输出电平

(dB FS)

00

−9.0

00

01

−11.5

01

10

−15.0

10

11

−17.5

11

 

DATA1 控制寄存器(用于读出UDA1341里面的信息)

D5

D4

D3

D2

D1

D0

PL5

PL4

PL3

PL2

PL1

PL0

PL5:PL4:PL3:PL2:PL1:PL0 (峰值电平)

(2).WM8960

S5PV210与WM8960之间除了我们前面介绍过的IIS接口相连接外,还有一个IIC总线的连接。而IIC总线我已经在前面一章中讲过了,这里将不再阐述。

接下来,对于WM8960,我讲几个关键地方:(寄存器就不再详细列出了,有56个寄存器,太多,对于初始化WM8960,我也是参考被人的代码的)

注意1

从芯片手册上63页的IIC时序图中可以看出,设备地址是7位,寄存器地址也是7(很关键),数据是9位,因此我们在写寄存器的时候,要在发寄存器地址的时候,也要发1位的数据。

注意2

寄存器设置的时候,请大家参考代码,然后读WM8960手册的67页,那里列出了所有的寄存器,大家从第一个看到最后一个,很容易懂的,看对应寄存器设置了些什么。我就不在一一列出寄存器的意思了。用到的寄存器,在代码中有它的详细注释。以下就是初始化WM8960的代码(我是参考别人的)

void WM8960_init(void)

{

/* 复位,让其他所有的寄存器恢复到默认值 */ 

wm8960_write(WM8960_DEVICE_ADDR, 0xf, 0x0);

/* 打开电源,使用fast start-up模式 */

wm8960_write(WM8960_DEVICE_ADDR, 0x19, 1<<8 | 1<<7 | 1<<6);

/* 任然是打开电源 */

wm8960_write(WM8960_DEVICE_ADDR, 0x1a, 1<<8 | 1<<7 | 1<<6 | 1<<5 | 1<<4 | 1<<3);

/* 左右声道输出使能 */

wm8960_write(WM8960_DEVICE_ADDR, 0x2F, 1<<3 | 1<<2);

/* 设置时钟,使用的都是默认值 */

wm8960_write(WM8960_DEVICE_ADDR, 0x4, 0x0);

/* 关键是将R5寄存器的bit[3]清零,关闭静音功能 */

wm8960_write(WM8960_DEVICE_ADDR, 0x5, 0x0);

/* 设置通信协议方式:如数据是24位,即IIS,左右声道时钟电平是否反转 */

wm8960_write(WM8960_DEVICE_ADDR, 0x7, 0x2);

/* 设置左右声道输出的音量 */

wm8960_write(WM8960_DEVICE_ADDR, 0x2, 0xFF | 0x100);/* 控制左声道的 */

wm8960_write(WM8960_DEVICE_ADDR, 0x3, 0xFF | 0x100);/* 控制右声道的 */

wm8960_write(WM8960_DEVICE_ADDR, 0xa, 0xFF | 0x100);/* 控制左声道的 */

wm8960_write(WM8960_DEVICE_ADDR, 0xb, 0xFF | 0x100);/* 控制右声道的 */

/* 使能通道,否则会静音 */

wm8960_write(WM8960_DEVICE_ADDR, 0x22, 1<<8 | 1<<7);/* 控制左声道的 */

wm8960_write(WM8960_DEVICE_ADDR, 0x25, 1<<8 | 1<<7); /* 控制右声道的 */

}

注意3

该部分代码,要求将一个wav文件(WindowsXP.wav之类的文件)烧写到nand0x1000000地址处

注意4

测试方法是,在终端输入如下命令:(再已经烧写wav文件的前提下)

play n        (将实现将wav音频文件播放n)

参考代码我放在了"Tiny210学习日记_代码"目录下了,名为"15_iis"

注:

如有问题,请到韦东山LINUX视频讨论群里面,我们一起讨论学习,或者加我QQ317312379

原创粉丝点击