采用TMS320F2812进行FFT变换
FFT结果的物理意义 : 可以参考本论坛链接:http://www.ourdev.cn/bbs/bbs_content.jsp?bbs_sn=3944963&bbs_page_no=1&search_mode=1&search_text=FFT&bbs_id=9999
开发板采用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;
Uint16 Voltage2;
#define N 1024 //FFT Length
#pragma DATA_SECTION(ipcb, "FFTipcb");
#pragma DATA_SECTION(mag,"FFTmag");
RFFT32 fft=RFFT32_1024P_DEFAULTS;
long ipcb; //In place computation buffer
long mag; //Magnitude buffer
//const long win=HAMMING128; //Window coefficient array
RFFT32_ACQ acq=FFTRACQ_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;
//RFFT32_brev(ipcb,ipcb,N);
//RFFT32_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 voidadc_isr(void)
{
Voltage1 = AdcRegs.ADCRESULT0>>4;
acq.input=((unsigned long)Voltage1)<<16;
acq.update(&acq);
// ipcb=((unsigned long)Voltage1)<<16;
Voltage2 = 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, */
FFTtf > PRAMH0, PAGE = 0
DLOG > PRAMH0, PAGE = 0
FFTipcb ALIGN(2048): { } > PRAMH1 PAGE 0
FFTmag > 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
}
FFTipcb, FFTmag 的配置必须注意。
aca.updata
可以把ipcb 输入数据与输出数据定义为同一数据,来节省内存
在开始FFT计算时需要
DINT 屏蔽A/D采集中断,结束FFT计算后EINT,以保证
再没有DINT A/D采集时,的截图:A/D采集不连续,
http://cache.amobbs.com/bbs_upload782111/files_30/ourdev_565269YBPPPV.jpg
(原文件名:FFT.jpg)
输入信号正弦Vpp 500mV,直流偏置500mV。此时输入的信号:0.5+0.5sin(2*pi*50*t)V
此时,ADC0输入的波形:2812ADC 为12位
http://cache.amobbs.com/bbs_upload782111/files_30/ourdev_565270OSF9DA.jpg
(原文件名:FFT.jpg)
FFT的图形:对ADC直接FFT变换:数据演算:
FFT的magtude为357578 变化为电压值 357578/(n/2)/4095*3=0.5115V,n=1024
http://cache.amobbs.com/bbs_upload782111/files_30/ourdev_565271OMTWG8.jpg
(原文件名:FFT.jpg)
调用2812的FFT子程序进行变换: 数据验算 mag 格式为Q30格式,mag=sqrt(0.00726813)*3*2=0.51152V
f=17*3000/1024=49.8Hz
Ti的FFT程序已经考虑到定点数的溢出问题,在每级的缩放系数为2,所以不用再除以N了,
http://cache.amobbs.com/bbs_upload782111/files_30/ourdev_565273PVGP52.jpg
(原文件名:FFT.jpg)
最终的计算结果合实际值有一点差别。 很好,mark;就是2812有点贵。 现在的2812还要500元,没有买,还得等一等。 2812 最低时才80一片,现在居然500。
其实,仔细算算做项目也不在乎那几个钱,就怕缺货。
观望中。 mark 回复【2楼】greenwoods
-----------------------------------------------------------------------
请教一下,我用了你的程序做实验,FFT.H用的是TI自带的那个吗?还要不要添加什么文件?
我的开发板和你一样的
链接的时候有错误,如下,不知道是什么原因?
"C:\CCStudio_v3.3\C2000\cgtools\bin\cl2000" -@"Debug.lkf"
<Linking>
undefined first referenced
symbol in file
--------- ----------------
_CFFT32_calc C:\CCStudio_v3.3\MyProjects\fft_icetek\Debug\ADC.obj
_RFFT32_split C:\CCStudio_v3.3\MyProjects\fft_icetek\Debug\ADC.obj
_RFFT32_acq C:\CCStudio_v3.3\MyProjects\fft_icetek\Debug\ADC.obj
_RFFT32_mag C:\CCStudio_v3.3\MyProjects\fft_icetek\Debug\ADC.obj
_CFFT32_init C:\CCStudio_v3.3\MyProjects\fft_icetek\Debug\ADC.obj
_RFFT32_win C:\CCStudio_v3.3\MyProjects\fft_icetek\Debug\ADC.obj
>> error: symbol referencing errors - './Debug/adc.out' not built
>> Compilation failure
Build Complete,
2 Errors, 0 Warnings, 0 Remarks. 没有目标代码,需要加进 fft库。 谢谢楼上的指导,可以运行了 楼上的兄弟们,我也是按照楼主那样做的,现在就是不知道mag[]出来的数据时什么格式?楼主的公式:数据验算 mag 格式为Q30格式,mag=sqrt(0.00726813)*3*2=0.51152V 应该全部是这样的吧: mag=sqrt(0.00726813)*3K/512=sqrt(0.00726813)*3*2=0.51152V ,不知道我这样验算对不???我用这个公式算出来的不对应。希望楼上的兄弟们帮忙啊!小弟先谢谢大家了~ 我也不清楚 楼主最后一步用FFT子程序到底是怎么算的,图形也显示的不对,怎么看自己的MAG格式是多少,在图形的设置选项怎么设置
mag=sqrt(0.00726813)*3*2=0.51152V ,这个式子也不理解
http://cache.amobbs.com/bbs_upload782111/files_31/ourdev_568307.jpg
(原文件名:1.jpg) 问下LZ有没有继续做下去,做相位、谐波什么的,我用一些插值算法校正出来的结果中,相位还是跟输入差的太多 回复【2楼】greenwoods
-----------------------------------------------------------------------
greenwoods
可以的话联系我一下,谢谢!
QQ264501976 楼主现身,,,qq 157298746 加我?? mark mark MARK 标记 学习FFT 谢谢分享 哈,最近弄到几片2812,改天试试。 请问各位师兄师姐们 FFt库函数是怎么加载到F2812里的?小弟正要用 亟待你们的帮助啊 mark MARK http://cache.amobbs.com/bbs_upload782111/files_38/ourdev_632437FPK267.JPG
2812 + FFT 库用于产品中 (原文件名:123123123.JPG) mark,DSP,FFT mark mark MARK. 回复【楼主位】greenwoods
-----------------------------------------------------------------------
不错!留着待用 mark 好的文章,收藏了~ mark 太好的东西了 mark 回复【21楼】lylatyou 张伯伦
-----------------------------------------------------------------------
哇!用的这么爽! mark 请问,你们知道2812计算一周波64点的FFT变换需要耗时多少吗?
谢谢 mark fft 正在学习急需啊 给我一片ROM,外加数据选择器,我能用数字序列实现FFT。 学习。。。。。。 楼主能否吧整个2812的工程传上来,谢谢 楼主,能否吧你的工程传上来,这段时间,正好,想用2812做一下FFT,在TI的官网上也没有找到FFT的软件包 自己试一试吧,不确定是不是原来的文件,只有原来的开发板A/D采样工程文件:在此基础上修改,外加TI 的FFT程序。仔细看看TI的FFT程序说明。
很好的资料,必须mark.
正在学习,mark一下,谢谢! greenwoods 发表于 2012-11-5 15:44 static/image/common/back.gif
自己试一试吧,不确定是不是原来的文件,只有原来的开发板A/D采样工程文件:在此基础上修改,外加TI 的FFT ...
LZ热心人,感谢分享! 朋友,你好!我看了你关于“采用TMS320F2812进行FFT变换” 的帖子,下载了附件,在ccs3.3上运行,结果编译时出错了,好像是缺少文件,想能和你探讨下,希望得到你的回复,谢谢!可以加我qq:407043680 不错,学习一下
楼主你好,我想问下怎么设置2812的adc的采样率,在程序的哪里可以设置,急求,谢谢 fc23fcevff23 发表于 2012-7-27 14:46
给我一片ROM,外加数据选择器,我能用数字序列实现FFT。
怎么实现?有算法吗? 2812 AD不行
页:
[1]