用2812进行FFT变换

    技术2022-05-12  27

    开发板采用ICETEK-F2812-A FFT 计算采用TI的FFT 程序,信号发生器产生正弦波信号,输入ACD0,AD采样率为3KHz, 注意:2812输入的电压:0-3V,信号发生器的正弦波信号应有一个整的offset。 2812的主程序: 实际的FFT 运算程序: #include "DSP281x_Device.h"     // DSP281x Headerfile Include File #include "DSP281x_Examples.h"   // DSP281x Examples Include File /* for test fft */ #include "fft.h" // Prototype statements for functions found within this file. interrupt void adc_isr(void); // Global variables used in this example: Uint16 LoopCount; Uint16 ConversionCount; Uint16 Voltage1[1024]; Uint16 Voltage2[1024]; #define N 1024                         //FFT Length #pragma DATA_SECTION(ipcb, "FFT ipcb"); #pragma DATA_SECTION(mag,"FFT mag"); RFFT 32 fft=RFFT 32_1024P_DEFAULTS; long ipcb[N+2];                        //In place computation buffer long mag[N/2+1];                        //Magnitude buffer //const long win[N/2]=HAMMING128;        //Window coefficient array   RFFT 32_ACQ acq=FFT RACQ_DEFAULTS;    //Instance the module main() {          int i;    InitSysCtrl();//初始化cpu         DINT;//关中断    InitPieCtrl();//初始化pie寄存器     /* Initialize acquisition module                    */    acq.buffptr=ipcb;    acq.tempptr=ipcb;    acq.size=N;    acq.count=N;    acq.acqflag=1; /* Initialize FFT module                            */    fft.ipcbptr=ipcb;    fft.magptr=mag;    fft.init(&fft);          IER = 0x0000;//禁止所有的中断    IFR = 0x0000;    InitPieVectTable();//初始化pie中断向量表       // Interrupts that are used in this example are re-mapped to // ISR functions found within this file.           EALLOW;  // This is needed to write to EALLOW protected register    PieVectTable.ADCINT = &adc_isr;    EDIS;    // This is needed to disable write to EALLOW protected registers    AdcRegs.ADCTRL1.bit.RESET = 1;        // Reset the ADC module     asm(" RPT #10 || NOP");                // Must wait 12-cycles (worst-case) for ADC reset to take effect    AdcRegs.ADCTRL3.all = 0x00C8;        // first power-up ref and bandgap circuits        AdcRegs.ADCTRL3.bit.ADCBGRFDN = 0x3;    // Power up bandgap/reference circuitry    AdcRegs.ADCTRL3.bit.ADCPWDN = 1;        // Power up rest of ADC // Enable ADCINT in PIE    PieCtrlRegs.PIEIER1.bit.INTx6 = 1;    IER |= M_INT1; // Enable CPU Interrupt 1    EINT;          // Enable Global interrupt INTM    ERTM;          // Enable Global realtime interrupt DBGM    LoopCount = 0;    ConversionCount = 1;      // Configure ADC    AdcRegs.ADCMAXCONV.all = 0x0001;       // Setup 2 conv's on SEQ1    AdcRegs.ADCCHSELSEQ1.bit.CONV00 = 0x0; // Setup ADCINA3 as 1st SEQ1 conv.    AdcRegs.ADCCHSELSEQ1.bit.CONV01 = 0x1; // Setup ADCINA2 as 2nd SEQ1 conv.    AdcRegs.ADCTRL2.bit.EVA_SOC_SEQ1 = 1;  // Enable EVASOC to start SEQ1    AdcRegs.ADCTRL2.bit.INT_ENA_SEQ1 = 1;  // Enable SEQ1 interrupt (every EOS) // Configure EVA // Assumes EVA Clock is already enabled in InitSysCtrl();    EvaRegs.T1CMPR = 0x0080;               // Setup T1 compare value    EvaRegs.T1PR = 0x61a8;                 // Setup period register    EvaRegs.GPTCONA.bit.T1TOADC = 1;       // Enable EVASOC in EVA    EvaRegs.T1CON.all = 0x1042;            // Enable timer 1 compare (upcount mode) // Wait for ADC interrupt    while(1)    {       //LoopCount++;       if (acq.acqflag==0)     // If the samples are acquired            {               DINT;         //RFFT 32_brev(ipcb,ipcb,N);         //RFFT 32_brev(ipcb,ipcb,N);  // Input samples in Real Part                 fft.calc(&fft);          fft.split(&fft);          fft.mag(&fft);          for(i=0;i<N;i++)          {                             mag=sqrt(mag);          }          acq.acqflag=1;      // Enable the next acquisition               EINT;       }    } } interrupt void  adc_isr(void) {   Voltage1[ConversionCount] = AdcRegs.ADCRESULT0>>4;     acq.input=((unsigned long)Voltage1[ConversionCount])<<16;   acq.update(&acq);     // ipcb[ConversionCount]=((unsigned long)Voltage1[ConversionCount])<<16;   Voltage2[ConversionCount] = AdcRegs.ADCRESULT1 >>4;   // If 40 conversions have been logged, start over   if(ConversionCount == 1023)   {      ConversionCount = 0;       // acq.acqflag=0;   }   else ConversionCount++;   // Reinitialize for next ADC sequence   AdcRegs.ADCTRL2.bit.RST_SEQ1 = 1;         // Reset SEQ1   AdcRegs.ADCST.bit.INT_SEQ1_CLR = 1;       // Clear INT SEQ1 bit   PieCtrlRegs.PIEACK.all = PIEACK_GROUP1;   // Acknowledge interrupt to PIE     return; } /* //########################################################################### // // FILE:    F2812_EzDSP_RAM_lnk.cmd // // TITLE:   Linker Command File For F2812 eZdsp examples that run out of RAM //          This linker file assumes the user is booting up in Jump to H0 mode // //########################################################################### // //  Ver | dd mmm yyyy | Who  | Description of changes // =====|=============|======|=============================================== //  1.00| 11 Sep 2003 | L.H. | Changes since previous version (v.58 Alpha) //      |             |      | Added BEGIN section to the start of H0 //      |             |      | Removed .bss, .const and .sysmem //      |             |      |    These are for a small memory model.  All examples //      |             |      |    use the large model. //      |             |      | Added .esysmem section //      |             |      | Changed ramfuncs section to load and run from RAM //      |             |      |    (previously this was type DSECT) //      |             |      | Moved peripheral register files to DSP28_Headers_BIOS.cmd //      |             |      |    and DSP28_Headers_nonBIOS.cmd //      |             |      | Added CSM_RSVD memory section in FLASHA - this region //      |             |      |    should be programmed with all 0x0000 when using the CSM // -----|-------------|------|----------------------------------------------- //########################################################################### */ /* ====================================================== // For Code Composer Studio V2.2 and later // --------------------------------------- // In addition to this memory linker command file, // add the header linker command file directly to the project. // The header linker command file is required to link the // peripheral structures to the proper locations within // the memory map. // // The header linker files are found in <base>/DSP281x_Headers/cmd //    // For BIOS applications add:      DSP281x_Headers_nonBIOS.cmd // For nonBIOS applications add:   DSP281x_Headers_nonBIOS.cmd     ========================================================= */ /* ====================================================== // For Code Composer Studio prior to V2.2 // -------------------------------------- // 1) Use one of the following -l statements to include the // header linker command file in the project. The header linker // file is required to link the peripheral structures to the proper // locations within the memory map                                    */ /* Uncomment this line to include file only for non-BIOS applications */ /* -l DSP281x_Headers_nonBIOS.cmd */ /* Uncomment this line to include file only for BIOS applications */ /* -l DSP281x_Headers_BIOS.cmd */ /* 2) In your project add the path to <base>/DSP281x_headers/cmd to the    library search path under project->build options, linker tab,    library search path (-i). /*========================================================= */ -l rts2800.lib -w -stack 400h -heap 100 MEMORY { PAGE 0 :    /* For this example, H0 is split between PAGE 0 and PAGE 1 */      /* BEGIN is used for the "boot to HO" bootloader mode      */    /* RESET is loaded with the reset vector only if           */    /* the boot is from XINTF Zone 7.  Otherwise reset vector  */    /* is fetched from boot ROM. See .reset section below      */        //RAMM0      : origin = 0x000000, length = 0x000400    //RAMM0      : origin = 0x3f6000, length = 0x001000    BEGIN      : origin = 0x3F8000, length = 0x000002    /*BEGIN      : origin = 0x3F7FF6, length = 0x000002*/                 PRAMH0     : origin = 0x3f8002, length = 0x000FFE    PRAMH1     : origin = 0x80000, length = 0x0FFFF        /* 64K external RAM */    RESET       : origin = 0x3FFFC0, length = 0x000002     /* part of boot ROM (MP/MCn=0) or XINTF zone 7 (MP/MCn=1) */    VECTORS     : origin = 0x3FFFC2, length = 0x00003E     /* part of boot ROM (MP/MCn=0) or XINTF zone 7 (MP/MCn=1) */             PAGE 1 :    /* For this example, H0 is split between PAGE 0 and PAGE 1 */    L0L1RAM (RW) : origin = 0x008000, length = 0x2000    RAMM1    : origin = 0x000400, length = 0x000400    DRAMH0   : origin = 0x3f9000, length = 0x001000          }     SECTIONS {    /* Setup for "boot to H0" mode:       The codestart section (found in DSP28_CodeStartBranch.asm)       re-directs execution to the start of user code.         Place this section at the start of H0  */        codestart        : > BEGIN,       PAGE = 0    ramfuncs         : > PRAMH0       PAGE = 0      .text            : > PRAMH0,      PAGE = 0    .cinit           : > PRAMH0,      PAGE = 0    .pinit           : > PRAMH0,      PAGE = 0    .switch          : > PRAMH0,      PAGE = 0    .reset           : > RESET,       PAGE = 0, TYPE = DSECT /* not used, */             FFT tf    >    PRAMH0,      PAGE = 0    DLOG         >    PRAMH0,     PAGE =    0    FFT ipcb    ALIGN(2048)  : { } >    PRAMH1 PAGE 0      FFT mag   >    PRAMH1     PAGE 0    SINTBL    : > L0L1RAM, PAGE =    1                             .stack           : > RAMM1,       PAGE = 1    .ebss            : > DRAMH0,      PAGE = 1    .econst          : > DRAMH0,      PAGE = 1          .esysmem         : > DRAMH0,      PAGE = 1    .const           : > DRAMH0,      PAGE = 1          .sysmem          : > DRAMH0,      PAGE = 1    .cio             : > DRAMH0,      PAGE = 1       } FFT ipcb, FFT mag 的配置必须注意。 aca.updata 可以把ipcb 输入数据与输出数据定义为同一数据,来节省内存 在开始FFT 计算时需要 DINT 屏蔽A/D采集中断,结束FFT 计算后EINT,以保证 再没有DINT A/D采集时,的截图:A/D采集不连续, (原文件名:FFT .jpg) 引用图片 输入信号正弦Vpp 500mV,直流偏置500mV。此时输入的信号:0.5+0.5sin(2*pi*50*t)V 此时,ADC0输入的波形:2812ADC 为12位 (原文件名:FFT .jpg) 引用图片 FFT 的图形:对ADC直接FFT 变换:数据演算: FFT 的magtude为357578 变化为电压值 357578/(n/2)/4095*3=0.5115V  ,n=1024 (原文件名:FFT .jpg) 引用图片 调用2812的FFT 子程序进行变换: 数据验算 mag 格式为Q30格式,mag=sqrt(0.00726813)*3*2=0.51152V f=17*3000/1024=49.8Hz Ti的FFT 程序已经考虑到定点数的溢出问题,在每级的缩放系数为2,所以不用再除以N了, (原文件名:FFT .jpg) 引用图片最终的计算结果合实际值有一点差别。


    最新回复(0)