1. 看了一下例程,居然没有FFT的例程,难道这个DSP28335不能做FFT吗?对了C2000系列是有C2000 ware这个库的。方便很多,不过目前不确定在C5000上运行的FFT能直接迁移到DSP28335上行不?测试了一下,是可以的,因为都是用的math.h,下面的一些正弦函数基本一样的
2. 硬件简介,其中DSP28335和TLV320AIC23B之间使用I2C接口进行寄存器配置,通过MCBSP进行数据传输。
3. 实际的硬件连接,左边的接耳机,右边的接电脑的音频输出(电脑的耳机输出)。
4. 相关代码,通过中断的方式,TLV320AIC23B,每次采集128个点,然后对这128个点,进行傅里叶变化。同时,DSP28335采集电脑的声音,然后再播放出来。
#include "DSP2833x_Device.h" // DSP2833x Headerfile Include File #include "DSP2833x_Examples.h" // DSP2833x Examples Include File #include#define PI 3.1415926 #define SAMPLENUMBER 128 /****************端口宏定义*****************/ #define LuYin GpioDataRegs.GPADAT.bit.GPIO12 #define LuYin_ST GpioDataRegs.GPADAT.bit.GPIO13 #define BoYin GpioDataRegs.GPADAT.bit.GPIO14 //标志位,用来确定是采集数据还是进行FFT unsigned char fft_or_sample_data = 0; //采集到了第几个数据,设定一个全局变量,不过还是先检测一下FFT是否能使用吧 unsigned int sample_data_index = 0; int INPUT[SAMPLENUMBER],DATA[SAMPLENUMBER]; float fWaveR[SAMPLENUMBER],fWaveI[SAMPLENUMBER],w[SAMPLENUMBER]; float sin_tab[SAMPLENUMBER],cos_tab[SAMPLENUMBER]; void InitForFFT(); void MakeWave(); void test_fft(void); void I2CA_Init(void); Uint16 AIC23Write(int Address,int Data); void Delay(int time); void delay(); interrupt void ISRMcbspSend(); void main(void) { InitSysCtrl(); // InitXintf16Gpio(); //zq InitMcbspaGpio(); //zq InitI2CGpio(); // AUDIOEN = 0; // Disable CPU interrupts DINT; InitPieCtrl(); // Disable CPU interrupts and clear all CPU interrupt flags: IER = 0x0000; IFR = 0x0000; InitPieVectTable(); I2CA_Init(); // Clear Counters // PassCount = 0; // FailCount = 0; AIC23Write(0x00,0x17); //AIC23Write(0x00,0x00); Delay(100); AIC23Write(0x02,0x17); //AIC23Write(0x02,0x00); Delay(100); AIC23Write(0x04,0x7f); Delay(100); AIC23Write(0x06,0x7f); Delay(100); AIC23Write(0x08,0x10); //AIC23Write(0x08,0x14); Delay(100); AIC23Write(0x0A,0x05); //AIC23Write(0x0A,0x00); Delay(100); AIC23Write(0x0C,0x00); Delay(100); AIC23Write(0x0E,0x53); //AIC23Write(0x0E,0x43); Delay(100); AIC23Write(0x10,0x2f); //AIC23Write(0x10,0x23); Delay(100); AIC23Write(0x12,0x01); Delay(100); //AIC23Init InitMcbspa(); // Initalize the Mcbsp-A EALLOW; // This is needed to write to EALLOW protected registers PieVectTable.MRINTA = &ISRMcbspSend; EDIS; // This is needed to disable write to EALLOW protected registers PieCtrlRegs.PIECTRL.bit.ENPIE = 1; // Enable the PIE block PieCtrlRegs.PIEIER6.bit.INTx5=1; // Enable PIE Group 6, INT 5 IER |= M_INT6; // Enable CPU INT6 EINT; // Enable Global interrupt INTM ERTM; // Enable Global realtime interrupt DBGM test_fft(); } // end of main void I2CA_Init(void) { // Initialize I2C I2caRegs.I2CSAR = 0x001A; // Slave address - EEPROM control code #if (CPU_FRQ_150MHZ) // Default - For 150MHz SYSCLKOUT I2caRegs.I2CPSC.all = 14; // Prescaler - need 7-12 Mhz on module clk (150/15 = 10MHz) #endif #if (CPU_FRQ_100MHZ) // For 100 MHz SYSCLKOUT I2caRegs.I2CPSC.all = 9; // Prescaler - need 7-12 Mhz on module clk (100/10 = 10MHz) #endif I2caRegs.I2CCLKL = 100; // NOTE: must be non zero I2caRegs.I2CCLKH = 100; // NOTE: must be non zero I2caRegs.I2CIER.all = 0x24; // Enable SCD & ARDY interrupts // I2caRegs.I2CMDR.all = 0x0020; // Take I2C out of reset I2caRegs.I2CMDR.all = 0x0420; // Take I2C out of reset //zq // Stop I2C when suspended I2caRegs.I2CFFTX.all = 0x6000; // Enable FIFO mode and TXFIFO I2caRegs.I2CFFRX.all = 0x2040; // Enable RXFIFO, clear RXFFINT, return; } Uint16 AIC23Write(int Address,int Data) { if (I2caRegs.I2CMDR.bit.STP == 1) { return I2C_STP_NOT_READY_ERROR; } // Setup slave address I2caRegs.I2CSAR = 0x1A; // Check if bus busy if (I2caRegs.I2CSTR.bit.BB == 1) { return I2C_BUS_BUSY_ERROR; } // Setup number of bytes to send // MsgBuffer + Address I2caRegs.I2CCNT = 2; I2caRegs.I2CDXR = Address; I2caRegs.I2CDXR = Data; // Send start as master transmitter I2caRegs.I2CMDR.all = 0x6E20; return I2C_SUCCESS; } void Delay(int time) { int i,j,k=0; for(i=0;i for(j=0;j<1024;j++) k++; } void delay(Uint32 k) { while(k--); } interrupt void ISRMcbspSend(void) { int temp1,temp2; temp1=McbspaRegs.DRR1.all; temp2=McbspaRegs.DRR2.all; McbspaRegs.DXR1.all = temp1; //放音 McbspaRegs.DXR2.all = temp2; PieCtrlRegs.PIEACK.all = 0x0020; if(fft_or_sample_data == 0) { //保存数据 INPUT[sample_data_index++] = (temp1 << 8) + temp2; if(sample_data_index == SAMPLENUMBER) { fft_or_sample_data = 1; } } // PieCtrlRegs.PIEIFR6.bit.INTx5 = 0; // ERTM; } void test_fft(void) { unsigned int i = 0; InitForFFT(); // MakeWave(); while(1) { if(fft_or_sample_data == 1) //假如标志位是1,那么进行FFT运算 { for ( i=0;i) { fWaveR[i]=INPUT[i]; fWaveI[i]=0.0f; w[i]=0.0f; } FFT(fWaveR,fWaveI); for ( i=0;i ) { DATA[i]=w[i]; } } else { Delay(1); } } } void FFT(float dataR[SAMPLENUMBER],float dataI[SAMPLENUMBER]) { int x0,x1,x2,x3,x4,x5,x6,xx; int i,j,k,b,p,L; float TR,TI,temp; /********** following code invert sequence ************/ for ( i=0;i ) { x0=x1=x2=x3=x4=x5=x6=0; x0=i&0x01; x1=(i/2)&0x01; x2=(i/4)&0x01; x3=(i/8)&0x01;x4=(i/16)&0x01; x5=(i/32)&0x01; x6=(i/64)&0x01; xx=x0*64+x1*32+x2*16+x3*8+x4*4+x5*2+x6; dataI[xx]=dataR[i]; } for ( i=0;i ) { dataR[i]=dataI[i]; dataI[i]=0; } /************** following code FFT *******************/ for ( L=1;L<=7;L++ ) { /* for(1) */ b=1; i=L-1; while ( i>0 ) { b=b*2; i--; } /* b= 2^(L-1) */ for ( j=0;j<=b-1;j++ ) /* for (2) */ { p=1; i=7-L; while ( i>0 ) /* p=pow(2,7-L)*j; */ { p=p*2; i--; } p=p*j; for ( k=j;k<128;k=k+2*b ) /* for (3) */ { TR=dataR[k]; TI=dataI[k]; temp=dataR[k+b]; dataR[k]=dataR[k]+dataR[k+b]*cos_tab[p]+dataI[k+b]*sin_tab[p]; dataI[k]=dataI[k]-dataR[k+b]*sin_tab[p]+dataI[k+b]*cos_tab[p]; dataR[k+b]=TR-dataR[k+b]*cos_tab[p]-dataI[k+b]*sin_tab[p]; dataI[k+b]=TI+temp*sin_tab[p]-dataI[k+b]*cos_tab[p]; } /* END for (3) */ } /* END for (2) */ } /* END for (1) */ for ( i=0;i 2;i++ ) { w[i]=sqrt(dataR[i]*dataR[i]+dataI[i]*dataI[i]); } } /* END FFT */ void InitForFFT() { int i; for ( i=0;i ) { sin_tab[i]=sin(PI*2*i/SAMPLENUMBER); cos_tab[i]=cos(PI*2*i/SAMPLENUMBER); } } void MakeWave() { int i; for ( i=0;i ) { INPUT[i]=sin(PI*2*i/SAMPLENUMBER*3)*1024; } }
5. 先检查FFT是否可用,按照下面的修改代码,可以单纯的测试FFT功能
void test_fft(void) { unsigned int i = 0; InitForFFT(); MakeWave(); while(1) { if(fft_or_sample_data == 1) //假如标志位是1,那么进行FFT运算 { for ( i=0;i) { fWaveR[i] =INPUT[i]; fWaveI[i]=0.0f; w[i]=0.0f; } FFT(fWaveR,fWaveI); for ( i=0;i) { DATA[i]=w[i]; } } else { Delay(1); } } }
6. 观察一下FFT输出的结构是否OK
配置参数
7. 查看输出结果
8. 不过如果相对声音进行FFT运算的话,实际上声音的变化非常快,所以上图的FFT结果,会一直变化的。而且由于声音的频率变化非常快,所以肉眼观察,基本难度很大。