Cortex-M3 (NXP LPC1788)之IIS应用--UDA1380进行音频数据播放
时间:11-19
来源:互联网
点击:
LPC1788发送到I2S总线上的音频数据要通过音频解码芯片才能输出模拟音频信号。开发板上使用的是UDA1380,对它的寄存器的配置可以通过L3总线或者I2C总线进行,这里使用I2C总线进行控制,对于I2C总线的操作可以参考之前I2C的介绍。UDA1380的寄存器主要分成3类,系统控制、插值滤波(interpolation filter)、抽取滤波(decimator filter)。插值滤波和DAC转换有关,用于控制控制声音的输出参数。抽取滤波和ADC有关,用于控制对音频的采样。寄存器的地址和功能如图1所示。
图1:UDA1380寄存器地址和功能
根据图1的红色标记中的内容,可以知道两个滤波器的正常使用需要一个128fs的clock,这个时钟可以通过SYSCLK引脚或者WSI的信号获得。在硬件连接上,通过将LPC1788的MCLK输出的时钟,连接到UDA1380的SYSCLK引脚。因此,我们需要配置I2S的发送模式控制寄存器I2STXMODE,使能TX_REF在MCLK输出,使UDA1380内部产生一个滤波器需要的时钟。
程序中我们通过I2S发送一段音频数据,该数据是我从WAV格式的文件中去掉WAV头格式后得到的一个纯音频数据数组。该WAV音频为16位双通道 采样频率为44.1KHZ。LPC1788将该数组发送到I2S总线,UDA1380读取该数据进行声音的输出。程序如下
- #include"i2c.h"
- #include"audio.h"
- #definerI2SDAO(*(volatileunsigned*)(0x400A8000))
- #definerI2STXFIFO(*(volatileunsigned*)(0x400A8008))
- #definerI2STXRATE(*(volatileunsigned*)(0x400A8020))
- #definerI2STXBITRATE(*(volatileunsigned*)(0x400A8028))
- #definerI2STXMODE(*(volatileunsigned*)(0x400A8030))
- #definerI2SDMA1(*(volatileunsigned*)(0x400A8014))
- #definerI2SDMA2(*(volatileunsigned*)(0x400A8018))
- #definerI2SSTATE(*(volatileunsigned*)(0x400A8010))
- #definerI2SIRQ(*(volatileunsigned*)(0x400A801C))
- #definerI2SDAI(*(volatileunsigned*)(0x400A8004))
- #definerI2SRXFIFO(*(volatileunsigned*)(0x400A800C))
- #definerI2SRXRATE(*(volatileunsigned*)(0x400A8024))
- #definerI2SRXBITRATE(*(volatileunsigned*)(0x400A802C))
- #definerI2SRXMODE(*(volatileunsigned*)(0x400A8034))
- #definerIOCON_P0_07(*(volatileunsigned*)(0x4002C01C))
- #definerIOCON_P0_08(*(volatileunsigned*)(0x4002C020))
- #definerIOCON_P0_09(*(volatileunsigned*)(0x4002C024))
- #definerIOCON_P1_16(*(volatileunsigned*)(0x4002C0C0))
- #defineUDA1380_ADDRESS0x1A
- voidUda1380_WriteData(unsignedcharreg,unsignedshortintdata)
- {
- unsignedcharconfig[3];
- config[0]=reg;
- config[1]=(data>>8)&0xFF;//MS
- config[2]=data&0xFF;//LS
- I2C0_MasterTransfer(UDA1380_ADDRESS,config,sizeof(config),0,0);
- I2C0_MasterTransfer(UDA1380_ADDRESS,config,1,&config[1],2);//校验写入的数据是否正确
- if((config[1]<8|config[2])!=data)
- {
- while(1);//写入和读出的数据不一致
- }
- }
- voidUda1380_config()
- {
- I2C0_Init();
- Uda1380_WriteData(0x7F,0x0);//restoreL3-defaultvalues
- Uda1380_WriteData(0x01,0x0);//数据格式为标准的I2S格式
- Uda1380_WriteData(0x13,0x0);//配置音频的输出
- Uda1380_WriteData(0x14,0x0);
- Uda1380_WriteData(0x00,0x2|0x1<8|0x1<9);//使能DAC的时钟,选择使用SYSCLK产生128fs的时钟
- Uda1380_WriteData(0x02,0x1<15|0x1<13|0x1<10|0x1<8);//使能DAC电源
- }
- intmain(void)
- {
- unsignedintcount=0,i;
- unsignedcharflag=1;
- rIOCON_P0_07=(rIOCON_P0_07&(~0x3))|0x1;//I2S_TX_SCK
- rIOCON_P0_08=(rIOCON_P0_08&(~0x3))|0x1;//I2S_TX_WS
- rIOCON_P0_09=(rIOCON_P0_09&(~0x3))|0x1;//I2S_TX_SDA
- rIOCON_P1_16=(rIOCON_P1_16&(~0x3))|0x2;//I2SMCLK
- rPCONP|=0x1<27;
- rI2SDAO=(16-1)<6|0x1<4|0x1<3|0x1;//16位,立体音,禁止发送
- rI2STXMODE|=0x1<3;//使能MCLK输出,使TX_REF输出到UDA1380的SYSCLK引脚
- rI2STXRATE=0x1<8|0x1;//配置分数速率寄存器得到TX_REF=CCLK/(1/1)/2
- rI2STXBITRATE=CCLK/2/(44100*2*16)-1;//44.1KHZ采样16位
- for(i=0;i<0x1000000;i++);//延时等待UDA1380内部通过SYSCLK产生稳定的128fs提供插值滤波和抽取滤波使用
- Uda1380_config();
- rI2SDAO&=~(1<4);
- rI2SDAO&=~(1<3);
- rI2SDAO&=~(1<15);//启动I2S数据传输
- while(flag)
- {
- if(((rI2SSTATE>>16)&0xFF)<=4)//如果发送FIFO中的数据小于或等于4个字
- {
- for(i=0;i<8-(((rI2SSTATE>>16)&0xFF));i++)//将FIFO填充到8个字
- {
- rI2STXFIFO=*(unsignedint*)(audio+count);//转换成int类型的指针,从指针指向的位置读取32位数据
- count+=4;//读取一个字,相当于读取char类型数组中的4个元素
- if(count>=sizeof(audio))//数组中的数据发送完
- {
- flag=0;
- break;
- }
- }
- }
- }
- rI2SDAO|=0x1<3|0x1<4;//停止I2S传输
- return0;
- }
1,i2c.h中是上一篇介绍I2C总线中所用的函数,aduio.h中存放的是音频数据的数组,const unsigned char audio[]={0,0,0,0,0,......................
2,I2C总线每次发送的数据为1个字节,而UDA1380的寄存器为16为,因此我们先发送高字节然后再发送低字节,具体的
Cortex-M3LPC1788UDA1380音频数 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)