本源代码在Ubuntu9.10环境下用arm-linux-gcc 4.3.2编译通过,并在勤研2440开发板上验证过可以播放采样频率为22050HZ的音频WAV文件 #include "def.h" #include "iis.h" #include "s3c24xx.h" #define L3M (1<<2) #define L3D (1<<3) #define L3C (1<<4) unsigned char *Buf = (unsigned char *)0x31000000; //data chunk size unsigned int size = 0; //sampling frequency unsigned int fs = 0; //------------------------------------------------------------- // S3C2440A IIS Configuration // GPB4 = L3CLOCK, GPB3 = L3DATA, GPB2 = L3MODE // GPE0 = I2SLRCK, GPE1 = I2SSCLK, GPE3 = I2SSDI, GPE4 = I2SSDO, GPE2 = CDCLK //------------------------------------------------------------- void Play_WAV(void) { Printf("[ IIS test using WM8976 CODEC ]/r/n"); IIS_PortSetting(); Init8976(); //set INT_DMA2 interrput service is available INTMSK &= ~(1 << 19); fs = *(Buf + 0x18) | *(Buf + 0x19)<<8 | *(Buf + 0x1a)<<16 | *(Buf + 0x1b)<<24; if(fs == 44100) //11.2896MHz (256fs) { // IISPSR = (3<<5) + 3; } else if(fs == 22050) //5.6448MHz (256fs) { IISPSR = (8<<5) + 8; size = *(Buf + 0x28) | *(Buf + 0x29)<<8 | *(Buf + 0x2a)<<16 | *(Buf + 0x2b)<<24; DISRC2 = (int)(Buf + 0x2c); } Printf("Sample Size = 0x%x/r/n", size/2); Printf("Sampling Frequency = %d Hz/r/n", fs); Printf("/r/n[ Nowing play the wav file ...]/r/n"); //init IIS IISCON = (1<<5) + (1<<2) + (1<<1); //Tx DMA service request Enable[5], Rx Idle[2], IIS prescaler Enable[1]; IISMOD = (0<<9) + (0<<8) + (2<<6) + (0<<5) + (0<<4) + (1<<3) + (0<<2) + (1<<0); IISFCON = (1<<15) + (1<<13); //Tx FIFO access mode DMA[15], Tx FIFO Enable[13] //init DMA2 DISRCC2 = (0<<1) + (0<<0); //the source is in the AHB, increment DIDST2 = (U32)IISFIFO; //IISFIFO DIDSTC2 = (1<<1) + (1<<0); //the destination is in the APB, fixed //Handshake[31], Sync PCLK[30], CURR_TC Interrupt enable[29],Unit Transfer[28],Single Service Mode[27] //I2SSDO[26:24], DMA Source[23], Auto Reload[22], Half-Word[21:20], TC[19:0] DCON2 = (1<<31)+(0<<30)+(1<<29)+(0<<28)+(0<<27)+(0<<24)+(1<<23)+(1<<22)+(1<<20)+(size/2); //No-Stop[2], DMA channel is turned on[1], No-Trigger in S/W request mode[0] DMASKTRIG2 = (0<<2)+(1<<1)+(0<<0); //IIS Interface Start IISCON |= 0x1; } void IIS_PortSetting(void) { //------------------------------------------------------ // Port E Group //Ports: GPE0 GPE1 GPE2 GPE3 GPE4 //Signal: I2SLRCK I2SSCLK CDCLK I2SSDI I2SSDO // [1:0] [3:2] [5:4] [7:6] [9:8] //Binary: 10 10 10 10 10 //------------------------------------------------------ GPEUP = GPEUP | (0x1f); GPECON = GPECON & ~(0x3ff) | (0x2aa); } void Init8976(void) { //---------------------------------------- // Port B Group //Ports: GPB2 GPB3 GPB4 //Signal: L3MODE L3DATA L3CLOCK //Setting: OUTPUT OUTPUT OUTPUT // [9:8] [7:6] [5:4] //Binary: 01 01 01 //---------------------------------------- GPBUP = GPBUP | (0x7<<2); //disable GPB[4:2] pull up function GPBCON = GPBCON & ~(0x3f<<4) | (0x15<<4); GPBDAT = GPBDAT & ~(L3M|L3D|L3C) | (L3M|L3C); //L3Mode=H, L3Clock=H WriteL3Data((0x3<<1)+1,0xef);//RMIXEN,LMIXEN,DACENR,DACENL WriteL3Data((0x1<<1)+0,0x1f);//biasen,BUFIOEN.VMIDSEL=11b WriteL3Data((0x2<<1)+1,0x80);//ROUT1EN LOUT1EN WriteL3Data((0x6<<1)+0,0x0);//SYSCLK=MCLK WriteL3Data((0x4<<1)+0,0x10);//16bit WriteL3Data((0x2B<<1)+0,0x10);//BTL OUTPUT WriteL3Data((0x9<<1)+0,0x50);//Jack detect enable WriteL3Data((0xD<<1)+0,0x21);//Jack detect WriteL3Data((0x7<<1)+0,0x01);//Jack detect } void WriteL3Data(unsigned char regaddr, unsigned char data) { int i, j; //start condition: L3M = High L3C = High GPBDAT |= L3M; GPBDAT |= L3C; GPBDAT |= L3M; GPBDAT |= L3C; for(i=0; i<100; i++); //delay //control register address for(j=0; j<8; j++) { if(regaddr & 0x80) { GPBDAT &= ~L3C; GPBDAT |= L3D; for(i=0; i<10; i++); //delay GPBDAT |= L3C; for(i=0; i<10; i++); //delay } else { GPBDAT &= ~L3C; GPBDAT &= ~L3D; for(i=0; i<10; i++); //delay GPBDAT |= L3C; for(i=0; i<10; i++); //delay } regaddr = regaddr << 1; } //control register data bits for(j=0; j<8; j++) { if(data & 0x80) { GPBDAT &= ~L3C; GPBDAT |= L3D; for(i=0; i<10; i++); //delay GPBDAT |= L3C; for(i=0; i<10; i++); //delay } else { GPBDAT &= ~L3C; GPBDAT &= ~L3D; for(i=0; i<10; i++); //delay GPBDAT |= L3C; for(i=0; i<10; i++); //delay } data = data << 1; } GPBDAT &= ~L3M; for(i=0; i<1000; i++); GPBDAT |= L3M; GPBDAT |= L3C; } void DMA2_Done(void) { SRCPND |= (1<<19); INTPND = (1<<19); IISCON = 0x0; //IIS Interface stop DMASKTRIG2 = (1<<2); //DMA2 stop IISFCON = 0x0; //FIFO flush INTMSK = INTMSK | (1<<19); }