DSP28335做FFT傅里叶变换

1. 看了一下例程,居然没有FFT的例程,难道这个DSP28335不能做FFT吗?对了C2000系列是有C2000 ware这个库的。方便很多,不过目前不确定在C5000上运行的FFT能直接迁移到DSP28335上行不?测试了一下,是可以的,因为都是用的math.h,下面的一些正弦函数基本一样的

DSP28335做FFT傅里叶变换_第1张图片

2. 硬件简介,其中DSP28335和TLV320AIC23B之间使用I2C接口进行寄存器配置,通过MCBSP进行数据传输。

DSP28335做FFT傅里叶变换_第2张图片

 

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;i2;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

DSP28335做FFT傅里叶变换_第3张图片

配置参数

DSP28335做FFT傅里叶变换_第4张图片

7. 查看输出结果

DSP28335做FFT傅里叶变换_第5张图片

8. 不过如果相对声音进行FFT运算的话,实际上声音的变化非常快,所以上图的FFT结果,会一直变化的。而且由于声音的频率变化非常快,所以肉眼观察,基本难度很大。

 

转载于:https://www.cnblogs.com/429512065qhq/p/9683428.html

你可能感兴趣的:(DSP28335做FFT傅里叶变换)