FFT算法的DSP实现

合集下载
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

FFT 算法的DSP 实现
对于离散傅里叶变换(DFT)的数字计算,FFT是一种有效的方法。

一般假定输入序列是复数。

当实际输入是实数时,利用对称性质可以使计算DFT 非常有效。

一个优化的实数FFT算法是一个组合以后的算法。

原始的2N个点的实输入序列组合成一个N 点的复序列,之后对复序列进行N 点的FFT 运算,最后再由N 点的复数输出拆散成2N点的复数序列,这 2 N点的复数序列与原始的2N点的实数输入序列的DFT输出一致。

使用这种方法,在组合输入和拆散输出的操作中,FFT 运算量减半。

这样利用实数FFT 算法来计算实输入序列的DFT的速度几乎是一般FFT算法的两倍。

下面用这种方法来实现一个256 点实数FFT(2N=256 )运算。

1. 实数FFT 运算序列的存储分配
如何利用有限的DSP 系统资源,合理的安排好算法使用的存储器是一个比较重要的问题。

本文中,程序代码安排在0x3000 开始的存储器中,其中0x3000~0x3080 存放中断向量表,FFT程序使用的正弦表和余弦表数据(.data段)安排在OxcOO开始的地方,变量(.bss段定义)存放在0x80 开始的地址中。

另外,本文中256 点实数FFT 程序的数据缓冲位
Ox23OO~Ox23ff , FFT 变换后功率谱的计算结果存放在Ox22OO~Ox22ff 中。

连续定位.cmd 文件程序如下:
MEMORY {
PAGE O: IPROG: origin = Ox3O8O,len=Ox1F8O
VECT: lorigin=Ox3OOO,len=Ox8O
EPROG: origin=Ox38OOO,len=Ox8OOO
PAGE 1:
USERREGS: origin=Ox6O,len=Ox1c
BIOSREGS: origin=Ox7c,len=Ox4
IDATA: origin=Ox8O,len=OxB8O
}
SECTIONS
{
EDATA: origin=OxCOO,len=Ox14OO
{
.vectors: { } > VECT PAGE O
.sysregs:
.trcinit:
.gblinit: { } > BIOSREGS PAGE 1 { } > IPROG PAGE O { } > IPROG PAGE O
.bios:
frt:
{ } > IPROG PAGE O { } > IPROG PAGE O
.text: { } > IPROG PAGE O
.cinit: { } > IPROG PAGE O
.pinit: { } > IPROG PAGE O
.sysinit: { } > IPROG PAGE O
.data: .bss: .far:
.const: { } > EDATA PAGE 1 { } > IDATA PAGE 1 { } > IDATA PAGE 1 { } > IDATA PAGE 1
.switch: { } > IDATA PAGE 1 .sysmem: { } > IDATA PAGE1
•cio:{ } > IDATA PAGE1
.MEM$obj: { } > IDATA PAGE1
.sysheap: { } > IDATA PAGE1
}
2.基2实数FFT运算的算法
该算法主要分为以下四步进行:
1)输入数据的组合和位排序
首先,原始输入的2N=256个点的实数序列复制放到标记有“ d_input_addr "的相邻单元,
当成N=128点的复数序列d[n],其中奇数地址是d[n]实部,偶数地址是d[n]的虚部,这个过程叫做组合(n为序列变量,N为常量)。

然后,把输入序列作位倒序,是为了在整个运算最后的输出中得到的序列是自然顺序,复数序列经过位倒序,存储在数据处理缓冲其中,标记为"”_data ”
如图一所示,输入实数序列为a[n], n=0,1,2,3, , ,255。

分离a[n]成两个序列,如图二所示,原始的输入序列是从地址0x2300到0x23FF,其余德从0x2200到0x22FF的是经过为倒序之后的组合序列:n=0,1, 2,3,,,127。

d[n]表示复合FFT的输入,r[n]表示实部,i[n]表示虚部:
d[n]=r[n]+j i[n]
程序设计中,在用 C54x 进行位倒序组合时,使用位倒序寻址方式可以大大提高程序执 行的速度和使
用存储器的效率。

在这种寻址方式中,AR0存放的整数N 是FFT 点数的一半,
一个辅助寄存器指向一个数据存放的单元。

当使用位倒序寻址把 AR0加到辅助寄存器中时,
地址以位倒序的方式产生,即进位是从左到右,而不是从右到左。

例如,当
AR0=0x0060 ,
AR2=0x0040时,通过指令: MAR AR2+0B
就可以得到 AR2位倒序寻址后的值为 0x0010。

下面是0x0060(1100000)与0x0040(1000000)以位倒序方式相加的过程:
1100000 + 1000000 0010000
实现256点数据位倒序存储的具体程序段如下: :AR2( REORDERED_DATA )
:装入第一个位倒序数据指针
bit_rev:
STM #d 」n put_addr, ORIGINAL_INPUT STM #fft_data, DATA_PROC_BUF
MVMM
DATA_PROC_BUF , :在 AR3(ORIGINAL_INPUT) :放入输入地址
:在 AR7( DATA_PROC_BUF ) :放入处理后输出的地址
REORDERED DA
STM STM RPTB MVDD
MVDD
#K_FFT_SINE-1, BRC
#K_FFT_SINE, AR0 bit_rev_e nd *ORIGINAL_INPUT+, *REORDERED_DATA+
:将原始输入缓冲中的数据放入到位倒序 :缓冲中去之后,输入缓冲( AR3 )指针 :力口 1,位倒序缓冲(AR2 )指针也加1
*REORDERED_DATA+
:将原始输入缓冲中的数据放入到位倒序 :缓冲中去之后,输入缓冲( AR3 )指针 :减1,位倒序缓冲(AR2 )指针加1, :以保证位倒序寻址正确
:按位倒序寻址方式修改
AR3
*ORIGINAL_INPUT+,
MAR *ORIGINAL_INPUT+0B bit rev end
:AR0的值是输入数据数目的一半 =128
注意,在上面的程序中,输入缓冲指针 AR3 (即ORIGINAL_INPUT )在操作时先加1再
减1,是因为我们把输入数据相邻的两个字看成一个复数,在用寄存器间接寻址移动了一 个复数(两个字的数据)之后,对AR3进行位倒序寻址之前要把 AR3的值恢复到这个复数 的首字的地址,这样才能保证位倒序寻址的正确。

2) N 点复数FFT 运算
在数据处理器里进行 N 点复数FFT 运算。

由于在FFT 运算中要用到旋转因子 W N ,它 是一个复数。

我们把它分为正弦和余弦部分,用
Q15格式将它们存储在两个分离的表中。

每个表中有128项,对应从0°〜1800。

因为采用循环寻址地址来对表寻址, 128=27 <28,
因此每张表排队的开始地址就必须是 8个LSB 位为0的地址。

按照系统的存储器配置,把
正弦表第一项"sine_table ”放在 0x0D00的位置,余弦表第一项" cos-table ”放在 OxOEOO 的位
置。

根据公式
N-1
D(k)八 d[n]W 「
k=0,1,, ,N-1
n=0
利用蝶形结对d[n]进行N=128点复数FFT 运算,其中
nk
」(2-/N)nk
2
■■
W N =e
cos( n k) — js in(
nk)
N N
0x0D00开始的正弦表和以 第一级是计算2点的FFT 蝶 32点、64点、128点的蝶形
D[K]=F{d[ n]}=R[k]+jl[k]
其中,R[k]、 I[k]分别是D[K]的实部和虚部。

FFT 完成以后,结果序列 D[K]就存储到数据处理缓冲器的上半部分,如图三所示,下
半部分仍然保留原始的输入序列 a[n],这半部分将在第三步中被改写。

这样原始的 a[ n]序列
的所有DFT 的信息都在D(k)中了,第三步中需要做的就是把 D(k)变为最终的2N=256点复
合序列,A[k]=F{a(n)}。

所需的正弦值和余弦值分别以 Q15的格式存储于内存区以 0x0E00开始的余弦表中。

把128点的复数FFT 分为七级来算, 形结,第二级是计算 4点的FFT 蝶形结,然后是8点、16点、 结计算。

最后所有的结果表示为
注意,在实际的DSP的编程中为了节约程序运行时间,提高代码的效率,往往要用到并行程序指令。

比如:
ST B, *AR3
II LD *AR3+, B
并行指令的执行效果是,使原本分开要两个指令周期才能执行完的两条指令在一个指令周期中就能执行完。

上述指令时将B移位(ASM-16)所决定的位数,存于AR3所指定的存
储单元中,同时并行执行,将AR3所指的单元中的值装入到累加器B的高位中。

由于指令
的src和dst都是Acc、B,所以存入*AR3中的值是这条指令执行以前的值。

这一步中,实现FFT计算的具体程序如下:
Fft:
;计算FFT的第一步,两点的FFT
•asg AR1, GROUP_COUNTER ;定义FFT计算的组指针
•asg AR2, PX ;AR2为指向参加蝶形运算第一个
;数据的指针
•asg AR3, QX ;AR2为指向参加蝶形运算第二个
;数据的指针
•asg AR4, WR ;定义AR4为指向余弦表的指针
•asg AR5, WT ;定义AR5为指向正弦表的指针
•asg AR6, BUTTERFL Y_COUNTER ;定义AR6为指向蝶形结的指针
•asg AR7, DATA_PROC_BUF ;定义在第一步中的数据处理缓冲指

•asg AR7, STAGE_COUNTER ;定义剩下几步中的数据处理缓冲指针
pshm st0
pshm ar0
pshm bk ;保存坏境变量
SSBX SXM ;开启符合扩展模式
STM #K_ZERO_BK, BK ;让BK=0 使*ARn+O%=*ARn+o
LD #-1, ASM ;为避免溢出在每一步输出时右移一位
MVMM DATA_PROC_BUF, PX ;PX 指向参加蝶形结运算的第一个数
;的实部(PR)
LD *PX, 16, A ;AH: =PR
STM #fft_data+K_DATA_IDX_1, QX ;指向参加蝶形运算的第二个数的实
;部(QR)
STM #K_FFT_SIZE/2-1, BRC ;设置块循环计数器
RPTBD STAGELEND-1 ;语句重复执行的范围到地址
; STAGELEND-1 处STM #K_DATA_IDX_1+1, AR0 ;延迟执行的两字节的指令(该指令
;不重复执行)
SUB *QX, 16, A, B ; BH: =PR-QR
ADD *QX, 16, A ; AH: =PR+QR
STH A, ASM, *PX+ ; PR': =(PR+QR)/2
STB, *QX+ ; QR': =(PR-QR)/2
II LD *PX, A ; AH: =PI
SUB *QX, 16, A, B ; BH:=PI-QI
ADD * QX, 16, A ; AH:=PI+QI
STH A, ASM, *PX+0% ; PI':=(PI+QI)/2
ST B, *QX+0% ; QI':=( PI-QI )/2
I LD *PX, A ; AH: =next PR
stagelend:
;计算FFT 的第二步,四点的FFT MVMM DATA_PROC_BUF, PX ; PX 指向参加蝶形运算第一个数据的
;实部(PR)
STM #fft_data+K_DATA_IDX_2, QX ; QX 指向参加蝶形运算第二个数据的
;实部(QR)
STM #K_FFT_SIZE/4-1, BRC ;设置块循环计数器
LD *PX, 16, A ; AH: =PR
RPTBD STAGEL2END-1 ;语句重复执行的范围到地址
; STAGEL1END-1 处STM #K_DA TA_IDX_2+1, AR0 ;初始化AR0 以被循环寻址以下是第
;一个蝶形
;运算过程
SUB *QX, 16, A, B ; BH: =PR-QR
ADD *QX, 16, A ; AH:= PR+QR
STH A, ASM, *PX+ ; PR':= (PR+QR)/2 ST B, *QX+ ; QR':= (PR-QR)/2
I LD *PX, A ; AH:=PI
SUB *QX, 16, A, B ; BH:=PI-QI
ADD *QX, 16, A ; AH:=PI+QI
STH A, ASM, *PX+ ; PI':= (PI+QI)/2
STH B, A SM, *QX+ ; QI':= (PI-QI)/2
;以下是第二个蝶形运算过程
MAR *QX+ ;QX中的地址加一
ADD *PX, *QX, A ;AH:= PR+QI
SUB *PX, *QX-, B ;BH: =PR-QI
STH A, ASM, *PX+ ;QR ':=
(PR+QI)/2
SUB *PX, *QX, A ;AH:=PI+QR
ST B, *QX ;QR ':= (PR-
QI)/2
II LD *QX, B ;BH:=OR
ST A, *PX ;PI':= (PI-QR)/2
I ADD *PX+0%, A ;AH:= PI+QR
ST A, *QX+0% ;QIR ':= (PI+QR)/2
I LD *PX, A ;AH:=PR
Stage2end:
;stage 3 thru stage logN-1: 从第三个蝶
;形到第六个蝶形的过程如下STM #K_TWID_TBL_SIZE, BK ;BK= 旋转因子表格的大小值
ST #K_TWID_IDX_3, d_twid_idx ;初始化旋转表格索引值
STW #K_TWID_IDX_3, AR0 ;AR0= 旋转表格初始索引值
STW #COS_TABLE, WR ;初始化WR 指针
STW #SINE_TABLE, WI ;初始化WI 指针
STW #K_LOGN-2-1, STAGE_COUNTER ;初始化步骤指针
ST #K_FFT_SIZE/8-1, d_grps_cnt ;初始化组指针
STM #K_FL Y_COUNT_3-1, BUTTERFL Y_ COUNTER
;初始化蝶形指针
ST #K_DA TA_IDX_3, d_data_idx ;初始化输入数据的索引
Stage: ;以下是每一步的运算过程STM #fft_data, PX
;PX 指向参加蝶形运算第一个数据
;的实部(PR )
LD d_data_idx, A
ADD *(PX), A
STLM A, QX ;QX 指向参加蝶形运算第二个数
据;的实部(QR)MVDK
d_grps_cnt, GROUP_COUNTER ;AR1 是组个数计数器group: ;以下是每一组的运算过程
MVMD BUTTERFLY_COUNTER, BRC ;将每一组中的蝶形的个数装入BRC
RPTBD
butterflyend-1 ;重复执行至butterflyend-1 处LD *WR, T
MPY *QX+, A ;A:=QR*W R I QX*QI
MAC *WI+0%, *QX-, A ;A:=QR*WR+QI*WI
ADD *PX, 16, A, B ;B:=( QR*WR+QI*WI)+PR
;I QX 指向QR
ST B, *PX ;PR':=( (QR*WR+QI*WI)+PR)/2
I SUB *PX+ B ;B:=PR-( QR*WR+QI*WI)
ST B, *QX ;QR ':=(PR-( QR*WR+QI*WI))/2
I MPY *QX+, A ;A:=QR*WI [T=WT]
QX 指向QI
MAS *QX, *WR+0%, A ; A:= QR*WI+QI*WR ADD *PX, 16, A
, B
; B:= (QR*WI+QI*WR)+PI
ST B, *QX+ ; QI ':=((QR*WI-QI*WR)+PI)/2
;I QX 指向 QR
; B:=PI- (QR*WI-QI*WR) ; T:=WR
; PI ':=(PI- (QR*WI-QI*WR))/2
;I PX 指向 PR
; A:=QR*WR I QX 指向 QI
;更新指针以准备下一组蝶形的运算 ;保存 AR0
;ARO 中装入在该步运算中每一组所 ;用的蝶形的数目
;增加PX 准备进行下一组的运算 ;增加QX 准备进行下一组的运算 ;当组计数器减一后不等于零时,延 ; 迟跳转至 group 处 ;恢复ARO (一字节)
;修改QX 以适应下一组的运算更新指
;针和其他索引数据以便进入下一个 ;步骤的运算
LD d_data_idx, A SUB #1, A, B; B=A-1
STLM B, BUTTERFLY_COUNTER STL A, 1, d_data_idx LD d_grps_cnt, A STL A, -1, d_grps_cnt LD d_twid_idx, A
STL A, -1, d_twid_idx
BANZD stage, *STAGE_COUNTER_ MVDK d_twid_idx, AR0 POPM bk POPM ar0 POPM st0 Fft_end:
RET 3) 分离复数FFT 的输出为奇部分和偶部分
分离FFT 输出为相关的四个序列: RP RM IP 和IM ,即偶实数、奇实数、偶虚数和奇 虚数四部分,以便第四部形成最终结果。

利用信号分析的理论我们把 D(K)通过下面的公式分为偶实数 RP[K]、奇实数RM[K]、偶
虚数 IP[K] 和奇虚数 IM[K]:
RP[K]=RP[N-K]=0.5*(R[K]+R[N-K]) RM[K]=-RM[N-K]=0.5*( R[K]-R[N-K])
II SUB *PX, B LD *WR, T ST B, *PX+ I MPY *QX+, A
butterflyend:
PSHM AR0
MVDK d_data_idx, AR0
MAR *PX+0 MAR *QX+0
BANZS group, *GROUP_COUNTER- POPM AR0 MAR *QX-
;修改蝶形个数计算器 ;下一步计算的数据索引翻倍 ;下一步计算的组数目减少一半 ;下一步计算的旋转因索引减少一半
;恢复环境变量
IP[K]=IP[N-K]=0.5*(l[K]+l[N-K])
IM[K]=-IM[N-K]=0.5*( I[K]-I[N-K])
RP[O]=R[O]
IP[0]=I[0]
RM[0]=IM[0]=RM[N/2]=IM[N/2]=0
RP[N/2]=R[N/2]
IP[N/2]=I[N/2]
图四显示了第三步完成以后存储器中的数据情况,RP[K]和IP[K]存储在上半部分,
RM[K]
和IM[K]存储在下半部分。

这一过程的程序代码如下删除两个字
unpack
•asg AR2, XP_K
.asg AR3, XP_Nmi nusk
.asg AR6, XM_K
.asg AR7, XM_Nmi nusk
STM #fft_data+2, XP_K ;AR2 指向R[K] (temp RP[K])STM #fft_ data+2*K_FFT_SIZE-2, XP_Nmi nusk
;AR 指向R[N-K] (temp RP[N-K])STM #fft_ data+2*K_FFT_SIZE=3, XM_Nmi nusk
;AR7 指向temp RM[N-K] STM #fft_ data+4*K_FFT_SIZE-1, XM_K ;AR6 指向temp RM[K]
STM #-2+K_FFT_SIZE/2, BRC ;设置块循环计数器
RPTBD phase3e nd-1 ;以下指令到phase3end-1处一直重复
;执行BRC中规定的次数STM #3, AR0 ;设置AR0以备下面程序寻址使用
ADD *XP_K, *XP_ Nmi nusk, A ;A:=R[K]+R[N-K]=2*RP[K]
SUB *XP_K, *XP_ Nmi nu sk, B ;B:=R[K]+R[N-K]=2*RM[K]
STH A, ASM, *XP_K+ ;在AR[K]处存储RP[K]
STH A, ASM, *XP_ Nmi nu sk+ ;在AR[N-K]处存储RP[N-K]=RP[K] STH B, ASM, *XP_K- ;在AI[2N-K]处存储RM[K]
NEG B ;B:=R[N-K]-R[K]=2*RM[N-K]
STH B, ASM, *XM_ Nmi nu sk- ;在AI[N+K]处存储RM[N-K]
ADD *XP_K, *XP_ Nmi nusk, A ;A:=I[K]+I[N-K]=2*IP[K]
SUB *XP_K, *XP_ Nmi nu sk, B ;B:=I[K]-I[N-K]=2*IM[K]
STH A, ASM, *XP_K+ ;在AI[K]处存储IP[K]
STH A, ASM, *XP_ Nmi nu sk-0 ;在AI[N-K]处存储IP[N-K]=IP[K]
STH B, ASM, *XM_K- ;在AR[2N-K]处存储IM[K]
NEG B ;B:=I[N-K]-I[K]=2*IM[N-K]
STH B, ASM, *XM_ Nmi nu sk+0 ;在AR[N+K]处存储IM[N-K]
phase3end:
4)产生最后的N=256点的复数FFT结果
产生2N=256个点的复数输出,它与原始的256个点的实输入序列的DFT一致。

输出驻留在数据缓冲器中。

①通过下面的公式由RP[K]、RM[K]、IP[K]和IM[K]四个序列可以计算出a[n]的DFT:
AR[k]=AR[2N-k]=RP[k]+C0S(k 二/N)*IP[k]-sin (k 二/N)*RM[k]
AI[k]=-AI[2N-k]=IM[k]-C0S(k 二/N)*RM[k]-sin (k 二/N)*IP[k]
AR[O]=RP[O]+IP[O]
AI[O]=IM[O]-RM[O]
AR[N]=R[O]-I[O]
AI[N]=0
其中:
A[k]=A[2N-k]= AR[k]+j AI[k]=F{a( n)} 即是a[n]的DFT结果
②实数FFT输出按照实数/虚数的自然顺序填满整个4N=512个字节的数据处理缓冲
这一段程序可以和上面的步骤3的程序合成一个子程序u n p ac k,这一步的程序代码如下: ST #0, *XM_k- ;RM[N/2]=0
ST #0, * XM_k ;IM[N/2]=0
.asg AR2, AX_k ;计算AR[0],AI[0] ,AR[N],AI[N] .asg AR4, IP_0
.asg AR5, AX_N
STM #fft_data, AX_k ;AR2指向AR[0] (temp RP[0])
STM #fft_data+1, IP_0 ;AR4指向AI[0] (temp IP[0]) STM #fft_data+2*K_FFT_SIZE+1, AX_N ;AR5指向AI[N]
ADD *AX_k, *IP_0, A ;A:=RP[0]+IP[0]
SUB *AX_k, *IP_0, B ;B:=RP[0]-IP[0]
STH A, ASM, *AX_k+ ;AR[0]=(RP[0]+IP[0])/2
ST #0, *AX_k ;AI[0]=0
MVDD *AX_k+, *AX_N- ;AI[N]=0
STH B, ASM, * AX_N ;AR[N]= (RP[0]-IP[0])/2
;计算最后的输出值AR[k],AI[k]
.asg AR3, AX_2Nmi nusk
.asg AR4, cos
.asg AR5, SIN
STM #fft_data+4*K_FFT_SIZE-1, AX_2Nmi nusk
;AR3指向AI[2N-1] (temp RM[1])
STM #cos_table+K_TWID_TBL_SIZE/K_FFT_SIZE, COS
;AR4指向cos(k* 二/N)
STM #si ne_table+K_TWID_TBL_SIZE/K_FFT_SIZE, SIN
;AR5指向sin(k* 二/N)
STM #K_FFT_SIZE-2, BRC
RPTBD phase4e nd-4
STM #K_TWID_TBL_SIZE/K_FFT_SIZE, ARO
;AR0中存入旋转因子表的大小以备循环
;寻址时使用
LD *AX_k+, 16, A ;A:= RP[k] II 修改AR2指向IP[k] MACR *COS, *AX_k, A ;A:= A+ cos(k* 二/N)* IP[k]
MASR *SIN, *AX_2Nmi nusk-, A ;A:= A-SIN(k* 二/N)* RM[k]
;AR3指向IM[k]
I修改
LD *AX_2Nmin usk+, 16, B ;B:= IM[k] I 修改AR3指向RM[k] MASR *SIN+0%, *AX_k-, B ;B:= B-SIN(k* 二/N)* IP[k] I 修改
;AR2指向RP[k]
MASR *COS+0%, *AX_2Nmi nusk, B ;B:= B-COS(k* 二/N)* RM[k]
STH A, ASM, *AX_k+ ;AR[k]=A/2
STH B, ASM, * AX_ k+ ;AI[k]=B/2
NEG B ;B:= -B
STH B, ASM, *AX_2Nmi nu sk- ;AI[2N-K]=-AI[k]=B/2
STH A, ASM, *AX_2Nmi nu sk- ;AR[2N-K]=-AR[k]=A/2
POWER_END:
RET
③计算所求信号的功率
由于最后所得的FFT数据是一个复数,为了能够方便的在虚拟频谱仪上观察该信号的特征,我们通常对所得的FFT数据进行处理一取其实部和虚部的平方和,即求得该信号的功率。

Power:
.asg AR2, AX
.asg AR3, OUTPUT_BUF
PSHM STO ;保存寄存器的值
PSHM ARO
PSHM BK
STM #d_output_addr, OUTPUT_BUF ;AR3指向输出缓冲地址
STM #K_FFT_SIZE*2-1, BRC ;块循环计数器设置为255
RPTBD power_e nd-4 ;带延迟方式的重复执行指令
STM #fft_data, AX ;AR2 指向AR[0]
SQUR *AX+, A ;A:= AR2
SQURA *AX+, A ;A:= AR2+AI2
STH A, 7, *OUTPUT_BUF ;将A中的数据存入输出缓冲中
ANDM #7FFFh, *OUTPUT_BUF+ ;避免输出数据过大在虚拟示波
;器中显示错误
POPM BK ;保存各个寄存器值
POPM ARO
POPM STO
power _ _en d:
RET
以上程序完成256点的实数FFT ,在CCS 环境下运行和调试,并通过 具观察结果,如上图所示。

1 I¥*4
CCS 的图形显示工。

相关文档
最新文档