您的位置:首页 > 其它

FL2440无操作系统应用程序编写测试011——IIS_AUDIO

2011-12-05 12:54 337 查看
Subject:FL2440无操作系统应用程序编写测试011——IIS_AUDIO
Date: 5-Dec-2011

By: Calvinlee1984@163.com

1.数字音频基础

◆声音(Sound):声音是由材料振动产生的一种物理现像,通过空气等介质的传播,引起人的耳膜振动,并为人耳所感知。自然界的声音信号本质是一种机械振动,是一种在空气中随时间变化的压力信号,主要用振幅和频率来刻画。当一个物体振动时,会引起周围空气质点的振动,由于空气的可压缩性,在质点的相互作用下,周围空气会产生交替的压缩和膨胀过程,并向外传播;

◆声波(Sound wave):从物理学的角度来讲,声音实际上是通过空气等介质传播的一种连续的波,音速c≈340m/s,声音在真空中无法传播;



◆声音信号:由许多不同频率的分量信号组成的复合信号,声音信号是典型的连续信号,不仅在时间上是连续的,在幅度上也是连续的;

◆频宽:复合信号的频率范围;

◆音频信号(Audio):频宽为20Hz-20Khz的信号,可被人的耳朵感知,高于20Khz的声音称为超声;

◆数字音频:声音信号在计算机中用一系列的二进制数字表示方法,为了实现数字化,必须对信号在时间轴进行采样,在幅度轴上进行量化;

◆采样(Sampling):将声音信号在时间轴上离散化,即每隔一段时间抽取一个信号样本;

◆采样频率(FS):将模拟声音波形转换成数字音频时,每秒钟对声音波形进行采样的次数,采样频率越高所能描述的声波频率就越高,保真度也越高,但占用的信息数据量也就越大。常用的采样频率有8Khz,11.025Khz,22.05Khz,16Khz,37.8Khz,44.1Khz,48Khz;



◆量化(Quantization):将连续的信号幅度离散化,如果幅度的划分是等间隔的,称为线性量化,否则为非线性量化。量化过程是一个A/D转换过程,其中量化位数,不仅决定着声音数据经数字化后的失真度,更决定着声音数据数据量的大小;



◆量化误差/噪声:某个采样时间点的模拟值和最近的量化值之间的差;



◆奈奎斯特理论(Nyquist Theroem):采样频率大于或等于声音信号最高频率的两倍就能把以数字表达的声音还原成原来的声音,人耳的听觉频宽为20Hz-20Khz,所以采样频率高于40Khz时,可保证声音信号不失真;

◆声道数:指所使用的声音通道的个数,表明声音记录产生一个波形还是两个波形,也就是单声道或双声道。双声道也称立体声,比单声道听起来更为丰满,但它占用的存储空间是单声道的两倍;

◆数据速率:采样频率*量化位数*声道数,如采样频率为44.1Khz,量化位数为16bit,声道数为2,则数据速率为32fs,1411.2Khz

2.IIS总线

IIS(Inter-IC Sound bus)又称I2S,是Philps公司提出的串行数字音频总线协议。IIS是一种常用的音频设备接口,主要用于CD/MD/MP3等设备。IIS总线只处理声音数据,其他信号(如控制信号)必须单独传输。为了使芯片的引出管脚尽可能少,IIS只使用了三根串行总线,分别是:提供分时复用功能的数据线,字段(声道)选择线,时钟信号线。

S3C2440A IIS总线格式:

S3C2440A的IIS总线接口用来实现对外部8/16位立体音频数字信号编解码器电路的接口功能。支持IIS总线格式及MSB-Justified格式。


S3C2440A IIS接口工作方式:

◆正常传输方式:使用IISCON寄存器对FIFO进行控制,CPU通过轮询方式访问FIFO寄存器,以完成对FIFO缓存传输或接收的处理。当FIFO准备好发送数据,如果发送FIFO中不为空,FIFO准备好标志将被置为1。如果发送FIFO为空,FIFO准备好标志将置0。当接收FIFO装满,接收FIFO准备好标志位被置0。这些标志可以决定CPU读写FIFO的时机。本文IIS工作在此种方式下。

◆DMA模式:在该模式下,FIFO寄存器组的控制权掌握在DMA控制器上,当FIFO满时,由DMA控制器对FIFO中的数据进行处理。

◆传输/接收模式:IIS数据线将通过双通道DMA同时接收和发送音频数据。

3.控制框图



IISDO/IISDI:数字音频信号的输出/输入;

IISSCLK: 串行时钟,每一个时钟信号传送一位音频信号,因此,IISCLK频率=采样频率*量化位数*声道数

IISLRCK: 帧时钟,用于切换左右声道,因此,IISLCRK频率=采样频率

CDCLK: IIS只负责数字音频信号的传输,真正实现音频信号的播放、录音,需处理芯片(如UDA1341)支持,CDCLK为该芯片提供系统同步时钟,即编解码时钟,作为音频信号的ADC采样时钟,可选的CDCLK频率如下:



4.UDA1341TS介绍

UDA1341TS是Philips公司生产的音频数字信号编译码器,可将立体声模拟信号转化为数字信号,同样也能将数字信号转化成模拟信号,并可用PGA和AGC对模拟信号进行处理。对于数字信号,该芯片提供了DSP功能。控制框图如下:



UDA1341TS提供2组音频信号输入线,1组音频信号输出线,1组IIS总线接口信号线及1组L3总线。IIS总线接口信号线包括:

BCK: 位输入时钟

WS: 字选择输入时钟

DATAO/DATAI:数据输出/输入

SYSCLK: 音频系统时钟

UDA1341TS有一微控制器模式,在该模式下,微控制器通过L3总线对它的数字音频处理参数和系统控制参数进行配置。L3总线接口信号线包括:

L3DATA: 微控制器接口数据

L3MODE: 微控制器接口模式

L3CLOCK:微控制器接口时钟

微控制器接口模式有两种:地址模式和数据传输模式

◆地址模式的高6位永远是000101,低两位表示传输模式(状态模式/数据0模式/数据1模式),其中状态模式用于选择UDA1341TS的工作状态:



地址模式的时序:



数据传输模式:用于某确定的地址模式下的数据传送,其时序如下,





注:S3c2440A没有L3总线接口,因此用三个通用IO来实现L3总线的传输。

5.硬件原理图



由上图可以看出各信号的对应接线方式:

S3C2440A UDA1341TS

IISSCLK —— BCK

IISLRCK —— WS

IISSDO —— DATAI

IISSDI —— DATAO

CDCLK —— SYSCLK

GPB2 —— L3MODE

GPB3 —— L3DATA

GPB4 —— L3CLOCK

6.音频WindowsXP_Wav.h文件头(44字节)分析



偏移地址 字节数 数据类型 内容 备注

00H 4 char "RIFF"

04H 4 long int 03 b7 58H 文件总长-8=243544

08H 8 char "WAVEfmt "

10H 4 long int 10 00 00 00H 线性PCM编码

14H 2 int 01 00H int fmttag=0x01

16H 2 int 00 02H 声道数=2

18H 4 long int 56 22H 采样率=22050Hz

1CH 4 long int 01 58 88H 每秒播放字节数=88200Bytes

20H 2 int 00 04H 采样一次占字节数=4

22H 2 int 00 10H 量化数=16

24H 4 char "data"

28H 4 long int 03 b7 34H 采样数据字节数=文长-44=243508

2CH 到文尾 char 采样数据

注:每秒播放字节数 =声道数*采样率*量化数/8

采样一次占字节数=声道数*量化数/8

参考:http://www.cnblogs.com/pumax/archive/2010/10/01/1839760.html

7.UDA1341TS L3总线端口初始化及L3总线写函数

#define L3MODE (1<<2) //GPB2

#define L3DATA (1<<3) //GPB3

#define L3CLOCK (1<<4) //GPB4

//UDA131TS L3总线接口写入函数

//address为0地址模式,否则为数据传输模式

//data为传输数据

static void WriteL3(U8 address,U8 data){

int i, j;

if(!address){ //地址模式

//L3CLOCK=High,L3MODE=Low

rGPBDAT = rGPBDAT & ~(L3MODE|L3DATA|L3CLOCK )|L3CLOCK;

}else{ //数据传输模式

//L3CLOCK=High,L3MODE=High

rGPBDAT=rGPBDAT & ~(L3MODE|L3DATA|L3CLOCK)|(L3CLOCK|L3MODE); }

for(j = 0; j < 5; j++); //delay

//将字节数据按串行格式发送,低位在前,高位在后

for(i = 0; i < 8; i++){

if(data & 0x1){ //Bit[i]=1

rGPBDAT &= ~L3CLOCK; //L3CLOCK=Low

rGPBDAT |= L3DATA; //L3DATA =High

for(j = 0; j < 5; j++);

rGPBDAT |= L3CLOCK; //L3CLOCK=High

rGPBDAT |= L3DATA; //L3DATA =High

for(j = 0; j < 5; j++);

}else{ //Bit[i]=0

rGPBDAT &= ~L3CLOCK; //L3CLOCK=Low

rGPBDAT &= ~L3DATA; //L3DATA =High

for(j = 0; j < 5; j++);

rGPBDAT |= L3CLOCK; //L3CLOCK=High

rGPBDAT &= ~L3DATA; //L3DATA =Low

for(j = 0; j < 5; j++);

}

data >>= 1; //Next bit

}

}

//UDA1341TS L3 controller Initialize

static void UDA1341TS_L3_Init(void){

//Set GPB[4:2] as output and Disable pull-up function

rGPBCON = rGPBCON & ~(0x3f<<4) | (0x15<<4);

rGPBUP = rGPBUP & ~(0x7<<2) | (0x7<<2);

//配置UDA1341TS L3

//状态模式



WriteL3(0,0x14+2);

WriteL3(1,0x40); //0100_0000 Reset



WriteL3(0,0x14+2);

WriteL3(1,0x10); //0001_0000 System Clock 384fs,No DC filter,I2S-bus







WriteL3(0,0x14+2);

WriteL3(1,0xc1); //1100_0001 DAC Output gain 6dB,ADC off,DAT on





}

8.IIS寄存器设置

//IIS Port Initialize

static void IIS_Port_Init(void){

//Set GPE[4:0] as IIS Port and Disable pull-up function

rGPECON = rGPECON & ~(0x3ff) | 0x2aa;

rGPEUP = rGPEUP & ~(0x1f) | 0x1f;



//DMA禁止,在接受空闲状态,不产生IISLRCK信号,IIS预分频使能

rIISCON = (0<<5)|(0<<4)|(0<<3)|(1<<2)|(1<<1);



//主设备时钟PCLK,主设备模式,发送模式,IIS总线格式

//串行数据(量化位数)16位,主时钟是384fs,串行位时钟32fs

rIISMOD = (0<<9)|(0<<8)|(2<<6)|(0<<5)|(0<<4)|(1<<3)|(1<<2)|(1<<0);



//fs=22.050Khz,CODECLK=384fs=8.4672Mhz

//预分频N=PCLK/CODECLK-1)=33.8571/8.4672-1=2.9986,取N=3

rIISPSR = (3<<5)|3;



//发送FIFO正常,发送FIFO使能

rIISFCON = (0<<15)|(1<<13);



}

9.源代码分析 IIS.c

#define L3MODE (1<<2) //GPB2

#define L3DATA (1<<3) //GPB3

#define L3CLOCK (1<<4) //GPB4

//UDA131TS L3总线接口写入函数

//address为0地址模式,否则为数据传输模式

//data为传输数据

static void WriteL3(U8 address,U8 data){

int i, j;

if(!address){ //地址模式

//L3CLOCK=High,L3MODE=Low

rGPBDAT = rGPBDAT & ~(L3MODE|L3DATA|L3CLOCK )|L3CLOCK;

}else{ //数据传输模式

//L3CLOCK=High,L3MODE=High

rGPBDAT=rGPBDAT & ~(L3MODE|L3DATA|L3CLOCK)|(L3CLOCK|L3MODE); }

for(j = 0; j < 5; j++); //delay

//将字节数据按串行格式发送,低位在前,高位在后

for(i = 0; i < 8; i++){

if(data & 0x1){ //Bit[i]=1

rGPBDAT &= ~L3CLOCK; //L3CLOCK=Low

rGPBDAT |= L3DATA; //L3DATA =High

for(j = 0; j < 5; j++);

rGPBDAT |= L3CLOCK; //L3CLOCK=High

rGPBDAT |= L3DATA; //L3DATA =High

for(j = 0; j < 5; j++);

}else{ //Bit[i]=0

rGPBDAT &= ~L3CLOCK; //L3CLOCK=Low

rGPBDAT &= ~L3DATA; //L3DATA =High

for(j = 0; j < 5; j++);

rGPBDAT |= L3CLOCK; //L3CLOCK=High

rGPBDAT &= ~L3DATA; //L3DATA =Low

for(j = 0; j < 5; j++);

}

data >>= 1; //Next bit

}

}

//UDA1341TS L3 controller Initialize

static void UDA1341TS_L3_Init(void){

//Set GPB[4:2] as output and Disable pull-up function

rGPBCON = rGPBCON & ~(0x3f<<4) | (0x15<<4);

rGPBUP = rGPBUP & ~(0x7<<2) | (0x7<<2);

//配置UDA1341TS L3

//状态模式

WriteL3(0,0x14+2);

WriteL3(1,0x40); //0100_0000 Reset

WriteL3(0,0x14+2);

WriteL3(1,0x10); //0001_0000 System Clock 384fs,No DC filter,I2S-bus

WriteL3(0,0x14+2);

WriteL3(1,0xc1); //1100_0001 DAC Output gain 6dB,ADC off,DAT on

}

//IIS Port Initialize

static void IIS_Port_Init(void){

//Set GPE[4:0] as IIS Port and Disable pull-up function

rGPECON = rGPECON & ~(0x3ff) | 0x2aa;

rGPEUP = rGPEUP & ~(0x1f) | 0x1f;

//DMA禁止,在接受空闲状态,不产生IISLRCK信号,IIS预分频使能

rIISCON = (0<<5)|(0<<4)|(0<<3)|(1<<2)|(1<<1);

//主设备时钟PCLK,主设备模式,发送模式,IIS总线格式

//串行数据(量化位数)16位,主时钟是384fs,串行位时钟32fs

rIISMOD = (0<<9)|(0<<8)|(2<<6)|(0<<5)|(0<<4)|(1<<3)|(1<<2)|(1<<0);

//fs=22.050Khz,CODECLK=384fs=8.4672Mhz

//预分频N=PCLK/CODECLK-1)=33.8571/8.4672-1=2.9986,N=3

rIISPSR = (3<<5)|3;

//发送FIFO正常,发送FIFO使能

rIISFCON = (0<<15)|(1<<13);

}

//PlayWave

static void PlayWave(U8 buffer[], U32 length){

int i, count;

//IIS start

rIISCON |= 0x1;

for(count = 0; count <= length; count += 64){

while(rIISCON &(1<<7)); //wait until Transmit FIFO emtpy

//64 Bytes Transmit FIFO,16-width and 32-depth form

for(i = 0; i < 32; i++){

rIISFIFO = (buffer[i*2+count]) + (buffer[i*2+1+count]<<8);

}

}

//IIS close

rIISCON = 0x0;

}

void IIS_PlayMusic_Test(void){

U32 Save_rMPLLCON = rMPLLCON; //PCLK=50Mhz

UDA1341TS_L3_Init(); //UDA1341TS L3 controller Initialize

IIS_Port_Init(); //IIS Port Initialize

rMPLLCON = (150<<12)|(5<<4)|(1<<0); //PCLK= 33.8571Mhz

PlayWave(WindowsXP_Wav, 243552);

rMPLLCON= Save_rMPLLCON; //PCLK=50Mhz

}

10.测试程序及结果

#include "UART.h"

#include "IIS.h"

int Main(void)

{

UART0_Port_Init(115200); //UART端口初始化

UART0_Printf("Play Music...\n");

IIS_PlayMusic_Test(); //播放音频文件

UART0_Printf("End\n");

while(1){

;

}

return 0;

}

1)测试正常,耳机可听到声音输出。

2)将预分频N改为1(开始以为该音频文件采样频率为44.1Khz)声音较为尖锐

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: