Date: 5-Dec-2011
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)声音较为尖锐