zoukankan      html  css  js  c++  java
  • 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结果,会一直变化的。而且由于声音的频率变化非常快,所以肉眼观察,基本难度很大。

  • 相关阅读:
    QSetting
    类中函数前、后、参数加const
    delete指针
    自定义数组类
    手动调用构造函数
    windows和linux平台下的通用时间测试函数
    多线程编程学习
    Android 利用ImageView显示图片
    特征描述算子-sift
    opencv边界扩展
  • 原文地址:https://www.cnblogs.com/429512065qhq/p/9683428.html
Copyright © 2011-2022 走看看