|
FFT的程序代码 (1)主程序 #include "f2407_c.h" #include "math.h" #define N 32 // FFT变换的点数 extern void fft(void); extern void resave(void); interrupt void phantom(void); void sysinit(void); extern int input[2*N]; // 输入数据的存储数组 int indati[N]={0}; // ----------------------------------------------------------------------------------- // 128 点 FFT所需的数据 // 采样函数: x=1/4+1/4cos(3*2*pi*f*t)+1/4cos(6*2*pi*f*t)+1/4cos(9*2*pi*f*t); // f=50Hz // ----------------------------------------------------------------------------------- /* int indatr[N]={16394,15871,14425,12398, 10276 ,8584 , 7767 , 8088 ,9557 , 11913 , 14660 ,17155 , 18724 , 18802 , 17044 , 13411 , 8197 , 1995 , -4389 ,-10071, -14231 , -16255 ,-15844, -13057 ,-8309 , -2296, 4125 , 10079, 14819, 17843 , 18969, 18342 , 16394 ,13739 , 11055 , 8950 , 7848, 7921 , 9070 , 10961, 13110 , 14992 , 16159 , 16334 ,5479 , 13792 , 11675 , 9640 , 8197 , 7741, 8457, 10264 , 12815 , 15554 , 17812 ,18939 , 18429 , 16034 , 11825 , 6203 , -156, -6405, -11662 , -15165 , -16394 , -15165 ,-11662 , -6405 , -156 , 6203 , 11825 , 16034, 18429, 18939 , 17812 , 15554 , 12815 ,10264 , 8457 , 7741 , 8197, 9640 , 11675, 13792, 15479 , 16334 , 16159, 14992 ,13110 , 10961 , 9070 ,7921 , 7848 , 8950 , 11055 , 13739 , 16393 , 18342 , 18969 ,17843 , 14819 , 10079 ,4125 , -2296 , -8309 , -13057 , -15844 , -16255 , -14231 , -10071 ,-4389 , 1995 , 8197 , 13411 , 17044 , 18802 , 18724 , 17155 , 14660 , 11913 , 9557 ,8088 , 7767, 8584 , 10276 , 12398 , 14425 , 15871 , };*/ // ----------------------------------------------------------------------------------- // 32点FFT所需的数据 // 采样函数: x=1/4+1/4cos(3*2*pi*f*t)+1/4cos(6*2*pi*f*t)+1/4cos(9*2*pi*f*t); // f=50Hz ;pi=π; // ----------------------------------------------------------------------------------- /* int indatr[N]={16384, 10270, 9551 , 18713 , 8192 , -14222 , -8304 , 14810 , 16384 ,7843 , 13102 ,15469, 8192 , 12807 , 18418 , -0156 ,-16384 , -0156 , 18418 , 12807 , 8192 , 15469,13102 , 7843 , 16383 , 14810 , -8304 , -14222 , 8192 , 18713 , 9551 , 10270 , };*/ int indatr[N]={0x07ff, 0x07ff, 0x07ff , 0x07ff , 0x07ff , 0x07ff , 0x07ff , 0x07ff , 0x07ff ,0x07ff , 0x07ff ,0x07ff, 0x07ff , 0x07ff , 0x07ff , 0x07ff ,0x0F801 , 0x0F801 , 0x0F801 , 0x0F801 , 0x0F801 , 0x0F801,0x0F801 , 0x0F801, 0x0F801 , 0x0F801 , 0x0F801 , 0x0F801 , 0x0F801 , 0x0F801 , 0x0F801 , 0x0F801 , }; // ----------------------------------------------------------------------------------- // 64点 FFT所需的数据 // 采样函数: x=1/4+1/4cos(3*2*pi*f*t)+1/4cos(6*2*pi*f*t)+1/4cos(9*2*pi*f*t); // f=50Hz // ----------------------------------------------------------------------------------- /* int indatr[N]={16384 , 14416, 10270, 7762, 9551 , 14651 , 18713, 17034, 8192 , -4387 , -14222,-15834 , -8304 , 4123 , 14810 , 18957 , 16384 , 11049 , 7843 , 9064 , 13102 , 16149 ,15469 , 11668 , 8192 , 8452 , 12807 , 17801 , 18418 , 11818, -0156 , -11655 , -16384 , -11655 , -0156 , 11818 , 18418 , 17801, 12807 , 8452 , 8192, 11668 , 15469 , 16149 ,13102 , 9064 , 7843 , 11049 , 16383 , 18957 , 14810 , 4123 , -8304 , -15834 , -14222 ,-4387 , 8192 , 17034 , 18713 , 14651 , 9551 , 7762 , 10270 , 14416 , };*/ // --------------------------------------------------------------- // 128 点 FFT的sin 和 cos值存储表 // --------------------------------------------------------------- /* const int sintab[N]={0x07fff,0x0,0x07fd9,0x0f9b9,0x07f62,0x0f375,0x07e9d,0x0ed38, 0x07d8a,0x0e708,0x07c2a,0x0e0e7,0x07a7d,0x0dad8,0x07885,0x0d4e1, 0x07642,0x0cf05,0x073b6,0x0c946,0x070e3,0x0c3aa,0x06dca,0x0be32, 0x06A6C,0x0B8E4,0x066CE,0x0B3C1,0x062F1,0x0AECD,0x05ED6,0x0AA0C, 0x05A81,0x0A57F,0x055F4,0x0A12A,0x05133,0x09D0F,0x04C3F,0x09932, 0x0471C,0x09594,0x041CD,0x09237,0x03C56,0x08F1F,0x036B9,0x08C4B, 0x030FB,0x089C0,0x02B1E,0x0877D,0x02527,0x08584,0x01F19,0x083D7, 0x018F8,0x08277,0x012C7,0x08164,0x00C8B,0x0809F,0x00647,0x08029, 0x00000,0x08001,0x0F9B9,0x08029,0x0F375,0x0809F,0x0ED39,0x08164, 0x0E708,0x08277,0x0E0E7,0x083D7,0x0DAD9,0x08584,0x0D4E2,0x0877D, 0x0CF05,0x089C0,0x0C947,0x08C4B,0x0C3AA,0x08F1F,0x0BE33,0x09237, 0x0B8E4,0x09594,0x0B3C1,0x09932,0x0AECD,0x09D0F,0x0AA0C,0x0A12A, 0x0A57F,0x0A57F,0x0A12A,0x0AA0C,0x09D0F,0x0AECD,0x09932,0x0B3C1, 0x09594,0x0B8E4,0x09237,0x0BE33,0x08F1F,0x0C3AA,0x08C4B,0x0C947, 0x089C0,0x0CF05,0x0877D,0x0D4E2,0x08584,0x0DAD9,0x083D7,0x0E0E7, 0x08277,0x0E708,0x08164,0x0ED39,0x0809F,0x0F375,0x08029,0x0F9B9 };*/ // --------------------------------------------------------------- // 64点 FFT的sin 和 cos值存储表 // --------------------------------------------------------------- /* const int sintab[N]={ 0x7FFF,0x0000,0x7F61 ,0xF375, 0x7D89 , 0xE708 , 0x7A7C , 0xDAD9,0x7640, 0xCF05 ,0x70E1 ,0xC3AA ,0x6A6C , 0xB8E4 , 0x62F1 , 0xAECD , 0x5A81, 0xA57F, 0x5133, 0x9D0F, 0x471C , 0x9594, 0x3C56, 0x8F1F, 0x30FB, 0x89C0 ,0x2527, 0x8584 ,0x18F8 , 0x8277 , 0x0C8B , 0x809F, 0x0000 ,0x8001, 0xF375, 0x809F, 0xE708 , 0x8277 , 0xDAD9 , 0x8584, 0xCF05 ,0x89C0 ,0xC3AA, 0x8F1F, 0xB8E4 , 0x9594 , 0xAECD , 0x9D0F, 0xA57F, 0xA57F, 0x9D0F, 0xAECD, 0x9594 , 0xB8E4 , 0x8F1F , 0xC3AA, 0x89C0, 0xCF05, 0x8584 ,0xDAD9 ,0x8277 , 0xE708 , 0x809F , 0xF375, };*/ // --------------------------------------------------------------- // 32 点 FFT的sin 和 cos值存储表 // --------------------------------------------------------------- const int sintab[N]={ 0x7FFF,0x0000,0x7D89,0xE708,0x7640,0xCF05,0x6A6C,0xB8E4, 0x5A81,0xA57F,0x471C,0x9594,0x30FB,0x89C0,0x18F8,0x8277, 0x0000,0x8001,0xE708,0x8277,0xCF05,0x89C0,0xB8E4,0x9594, 0xA57F,0xA57F,0x9594,0xB8E4,0x89C0,0xCF05,0x8277,0xE708, }; extern int table128[]; extern int nom; // 当nom=1时, FFT 需要归一化处理 main() { int i; double x=0,y; nom=1; // 需要归一化处理 sysinit(); for(i=0;i<=255;i++) input=0; // 清除输入数据 resave(); // 把原始的输入数据反序排列 *PCDATDIR=(*PCDATDIR&0x0FF00)|0x01; fft( ); // 进行FFT运算 *PCDATDIR=*PCDATDIR&0x0FF00; } void interrupt phantom(void) { return; } void sysinit(void) { *SCSR1=0x81FE; *WDCR=0x0E8; *IFR=0x0FF; *IMR=0x0; WSGR=0; *MCRB=0; *PCDATDIR=0x100; } (2)反序排列子程序 .def _resave // 基2时间抽取的128点FFT算法需要定义的各量 // N .set 128 // 基2时间抽取的64点FFT算法需要定义的各量 // N .set 64 // 基2时间抽取的32点FFT算法需要定义的各量 N .set 32 .global _resave .global _input .global _indatr .global _indati _resave: //------------------------------------------------------------------- // 与C语言兼容的代码部分 // ------------------------------------------------------------------- POPD *+ SAR AR0,*+ SAR AR1,* LAR AR0,*+,AR3 // ------------------------------------------------------------------ // 反序排列程序部分 //------------------------------------------------------------------ LAR AR2,#_input LAR AR3,#_indatr LAR AR0,#N LAR AR4,#(N-1) RESAV1 LACC *+,0,AR2 SACL *BR0+,AR4 BANZ RESAV1,*-,AR3 //------------------------------------------------------------------- // 与C语言兼容的程序代码部分 //------------------------------------------------------------------- MAR *,AR1 SBRK #2 LAR AR0,*- PSHD * RET (3) FFT应用子程序 // ------------------------------------------------------------------------------------------------- // 函数名: void fft(void) // 功能:实现32、64或128采样点的快速傅立叶变换 // 入口条件: // _sintab 存放FFT运算中用到的sin和cosin函数值 // _input 存放FFT运算中用到的数据,包括实部和虚部,按二进制反序排列 // 注意:由于“*BR0+”间接寻址方式对_input的地址有特殊的要求, // 所以最好将数组_input放置在一个独立的块中,如B1块。 // _nom 当_nom=0时,本函数将不对运算结果进行归一化。反之,将对每 // 一步运算结果进行归一化处理,避免溢出,但是,它会使运算精度降低。 // N 常数,参与FFT运输的点数,用户可根据需要选择,例如,需要进行128点 // FFT时,请在本函数中做出如下选择: // N .set 128 // M .set 7 // 依此类推。 // 出口条件: // _input 存放FFT的运算结果 // 本函数可供C调用,请用户在C主程序中作以下声明: // extern void fft(void); // const int sintab[N]={...}; N为128、64或32 // extern int _input[2*N]; // extern int nom; //-------------------------------------------------------------------------------------------------- .def _ fft // 基2时间抽取的128点FFT算法需要定义的各量 // N .set 128 // 点数 // M .set 7 // N=2**M // 基2时间抽取的64点FFT算法需要定义的各量 // N .set 64 // 点数 // M .set 6 // N=2**M // 基2时间抽取的32点FFT算法需要定义的各量 N .set 32 // 点数 M .set 5 // N=2**M _input .usect ".data0",2*N // 输入数据 // .bss _sintab,N // SIN和COSIN函数的存储表 .bss _nom,1 // 当 _nom=1时, FFT需要归一化处理,为0时则不需要 .global _fft .global _sintab .global _input .global _nom .text _fft: // -------------------------------------- // 与C语言兼容的代码部分 // -------------------------------------- POPD *+ // 存储返回地址ADDRESS SAR AR6,*+ // 存储 AR6 SAR AR7,*+ // 存储 AR7 SAR AR0,*+ // 存储 AR0 SAR AR1,* // 堆栈分布情况:ADDRESS/AR6/AR7/AR0/AR1 // ARP=AR1, AR1:AR1 LAR AR0,#08h LAR AR3,*0+,AR3 // AR3:FP, SP=SP+size(size=frame的长度) // ARP=AR3 LAR AR2,* // AR2:AR1 LAR AR7,#_nom // AR7 指向 _nom // ----------------------------------------- // 初始化一些寄存器 // ----------------------------------------- SPLK #(N-1),*+ SPLK #(M-1),*+ // 堆栈分布情况:ADDRESS/AR6/AR7 // /AR0/N/M/Y(其中Y为没有确定的量) // ARP=AR3, AR2:N, AR3:Y SPLK #1,*+,AR2 // ID=1,ARP=AR2 // 堆栈分布情况:ADDRESS/AR6/AR7/AR0/ // N/M/ID/Y ARP=AR2, AR2:N, AR3: // ----------------------------------------- // FFT运算处理部分 // ----------------------------------------- SETC OVM // 使能溢出模式 SETC SXM // 符号扩展使能 SPM 1 // PREG寄存器的输出左移一位, // 自动将两个Q15相乘后化为Q15的格式 LACC *+,AR3 ADD #1 SACL *+,1,AR2 // IW=2*(N+1) // 堆栈分布情况:ADDRESS/AR6/AR7 // /AR0/N/M/ID/IW/Y // ARP:AR2, AR2:M, AR3:Y, LAR AR5,*+ // AR5=M,ARP:AR2, AR2:ID, // AR3:Y, AR5=M LOOP3 LAR AR6,#_input // AR6:input-->Ri ,ARP:AR2, // AR2:ID, AR3:Y, AR5=M, AR6:input LACC *,1 SACL *+ // ID=ID*2,ARP:AR2,AR2:IW, // AR3:Y, AR5=M, AR6:input LACC *,15 SACH * // IW=IW/2 LACC *-,15,AR3 SACH *+,AR2 // C2=IW/2 // 堆栈分布情况:ADDRESS/AR6/AR7/AR0/N/M/ID/IW/C2/Y // ARP:AR2, AR2:ID, AR3:Y, AR5=M, AR6:input LAR AR0,* // AR0=ID LOOP2 LAR AR4,#_sintab // AR4:sintab // ARP:AR2,AR0=ID,AR2:ID, AR3:Y, AR4:sintab, AR5=M, AR6:input LACC *+,15,AR3 SACH *+,AR6 // C1=ID/2=1 // 堆栈分布情况:ADDRESS/AR6/AR7/AR0/N/M/ID/IW/C2/C1/Y // ARP:AR6, AR0=ID, AR2:IW, AR3:Y, AR4:sintab, AR5=M, AR6:input MAR *0+,AR4 // ARP:AR4,AR0=ID,AR2:IW,AR3:Y,AR4:sintab,AR5=M,AR6=AR6+ID-->Rj LOOP1 LACC #0 LT *+,AR6 // TREG=COSαlk MPY *+,AR4 // Rj* COSαlk,ARP=AR4,AR4:SINαlk,AR6:Ij LT *,AR6 MPYA *-,AR3 // ACC=ACC+Rj*COSαlk, PREG=Ij*SINαlk // ARP=AR3, AR4:SINαlk, AR6: Rj SPAC // ACC=ACC-Ij*SINαlk SACH *+,AR4 // XT=Rj*COSαlk-Ij*SINαlk // 堆栈分布情况:ADDRESS/AR6/AR7/AR0/N/M/ID/IW/C2/C1/XT/Y // ARP:AR4, AR0=ID, AR2:IW, AR3:Y, AR4:SINX, AR5=M, AR6:Q.X LACC #0 LT *-,AR6 MPY *+,AR4 // Rj*SINαlk,ARP=AR4,AR4:COSαlk,AR6:Ij LT *,AR6 MPYA *-,AR3 // ACC=ACC+Rj*SINαlk, PREG=Ij*COSαlk // ARP=AR3, AR4:COSαlk, AR6:Rj APAC SACH *-,AR7 // YT=Rj*SINαlk+Ij*COSαlk // 堆栈分布情况:ADDRESS/AR6/AR7/AR0/N/M/ID/IW/C2/C1/XT/YT // ARP:AR7, AR0=ID, AR2:IW, AR3:XT, AR4:COSX, AR5=M, AR6:Q.X LACC *,AR6 BCND D2,NEQ // 当_nom不为0时,需要在运算过程中进 // 行归一化操作 // ---------------------------------------- // 不进行归一化操作程序部分 // ---------------------------------------- MAR *0- // AR6=AR6-ID-->Ri LACC *,AR3 ADD *,AR6 SACL *0+,AR3 // Ri=Ri+XT // ARP:AR3, AR0=ID, AR2:IW, AR3:XT, AR4:COSαlk, AR5=M, AR6:Rj SUB *+,1,AR6 SACL *+ // Rj= Ri+XT -XT*2=Ri-XT, AR6:Ij, AR3:YT // ARP:AR6, AR0=ID, AR2:IW, AR3:YT, AR4:COSαlk , AR5=M, AR6:Ij MAR *0- // AR6:Ii LACC *,AR3 ADD *-,AR6 SACL *0+,AR3 // Ii= Ii +YT, AR6:Ij // ARP:AR3, AR0=ID, AR2:IW, AR3:XT, AR4:COSαlk, AR5=M, AR6:Ij SUB *,1,AR6 SACL *+,0,AR2 // Ij= Ii +YT -YT*2=Ii-YT // STACK:ADDRESS/AR6/AR7/AR0/N/M/ID/IW/C2/C1/XT/YT // ARP:AR2,AR0=ID,AR2:IW,AR3:XT,AR4:COSαlk,AR5=M,AR6:NEXT Rj B D // AR6 指向下一个Rj // --------------------------------------- // 归一化处理程序部分 // --------------------------------------- D2 MAR *0- // AR6-->Ri LAC *,15,AR3 ADD *,15,AR6 SACH *0+,AR3 // Ri =( Ri +XT)/2 // ARP:AR3, AR0=ID, AR2:IW, AR3:XT, AR4:COSαlk, AR5=M, AR6:Rj SUB *+,16,AR6 SACH *+ // Rj=Ri-XT, AR6:Ij, AR3:YT // ARP:AR6, AR0=ID, AR2:IW, AR3:YT, AR4:COSαlk, AR5=M, AR6:Ij MAR *0- // AR6:Ii LACC *,15,AR3 ADD *,15,AR6 SACH *0+,AR3 // Ii=(Ii+YT)/2, AR6:Ij // ARP:AR3, AR0=ID, AR2:IW, AR3:YT, AR4:COSαlk, AR5=M, AR6:Ij SUB *-,16,AR6 SACH *+,0,AR2 // Ij=Ii-YT // STACK:ADDRESS/AR6/AR7/AR0/N/M/ID/IW/C2/C1/XT/YT // ARP:AR2,AR0=ID,AR2:IW,AR3:XT,AR4:COSαlk,AR5=M,AR6:下一个Rj D LAR AR0,*-,AR4 // AR0=IW // ARP=AR4, AR0=IW, AR2:ID, AR3:XT, AR4:COSαlk, AR5=M,AR6:下一个Rj MAR *0+,AR2 // AR4=AR4+IW-->下一个COSαlk LAR AR0,* // AR0=ID ADRK #3 // AR2:C1 // ARP=AR2, AR0=ID, AR2:C1, AR3:XT, AR4: 下一个COSαlk, AR5=M, AR6:Rj LACC * SUB #1 SACL *- // C1=C1-1 // ARP=AR2, AR0=ID, AR2:C2, AR3:XT, AR4:COSαlk, AR5=M, AR6:Rj BCND LOOP4,LEQ // 跳转至LOOP4, IF C1<0 MAR *-,AR4 // AR2:IW // ARP=AR4, AR0=ID, AR2:IW, AR3:XT, AR4: 下一个COSαlk, AR5=M, AR6:Rj B LOOP1 LOOP4 LACC * SUB #1 SACL *-,AR3 MAR *-,AR2 // ARP=AR2, AR0=ID, AR2:IW, AR3:C1, AR4: 下一个COSαlk, AR5=M, AR6:Ri MAR *- BCND LOOP2,GT MAR *,AR3 MAR *-,AR5 // ARP=AR5, AR0=ID, AR2:IW, AR3:C2, AR4下一个COSαlk, AR5=M, AR6:Ri BANZ LOOP3,*-,AR2 // ------------------------------------ // 与C语言兼容的代码部分 // ------------------------------------ CLRC OVM SPM 0 MAR *,AR1 SBRK #09 LAR AR0,*- LAR AR7,*- LAR AR6,*- PSHD * RET
TMS320LF2407上实现快速傅里叶变换(FFT):点击下载
|