DSP28335做FFT傅里叶变换
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 <math.h>
#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<time;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<SAMPLENUMBER;i++ )
{
fWaveR[i]=INPUT[i];
fWaveI[i]=0.0f;
w[i]=0.0f;
}
FFT(fWaveR,fWaveI);
for ( i=0;i<SAMPLENUMBER;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<SAMPLENUMBER;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<SAMPLENUMBER;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<SAMPLENUMBER/2;i++ )
{
w[i]=sqrt(dataR[i]*dataR[i]+dataI[i]*dataI[i]);
}
} /* END FFT */
void InitForFFT()
{
int i;
for ( i=0;i<SAMPLENUMBER;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<SAMPLENUMBER;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<SAMPLENUMBER;i++ )
{
fWaveR[i]=INPUT[i];
fWaveI[i]=0.0f;
w[i]=0.0f;
}
FFT(fWaveR,fWaveI);
for ( i=0;i<SAMPLENUMBER;i++ )
{
DATA[i]=w[i];
}
}
else
{
Delay(1);
}
}
}
6. 观察一下FFT输出的结构是否OK
配置参数
7. 查看输出结果
8. 不过如果相对声音进行FFT运算的话,实际上声音的变化非常快,所以上图的FFT结果,会一直变化的。而且由于声音的频率变化非常快,所以肉眼观察,基本难度很大。