第 7章 汇编语言程序设计
? 7.1 程序流程控制
? 7.2 数据块传送
? 7.3 定点数的基本算术运算
? 7.4 长字运算和并行运算
? 7.5 FIR滤波器的 DSP实现
? 7.6 IIR数字滤波器的 DSP实现
? 7.7 FFT运算的 DSP实现
7.1 程序流程控制
? 7.1.1 程序存储器地址生成
? 7.1.2 条件操作
? 7.1.3 分支转移
? 7.1.4 调用与返回
? 7.1.5 重复操作
? 7.1.6 TMS320C54x中断系统
? 7.1.7 堆栈的使用
返回首页
7.1.1 程序存储器地址生成
? 程序存储器中存放指令代码、参数表和立即数。程序地址
产生逻辑( PAGEN),包括以下 5个寄存器(如图 7-1所
示):
? 程序计数器( PC);
? 重复计数器( RC);
? 块重复计数器( BRC);
? 块重复起始地址寄存器( RSA);
? 块重复结束地址寄存器( REA)。
图 7-1 程序地址产生逻辑( PAGEN) 寄存器
返回本节
7.1.2 条件操作 表 7-1 条件指令中的各种条件
表 7-2 多条件指令中的条件组合
第一组 第二组
A 类 B 类 A 类 B 类 C 类
EQ OV TC C BIO
NEQ NOV NTC NC NBIO
LT
LEQ
GT
GEQ
返回本节
7.1.3 分支转移
表 7-3 无条件分支转移指令
指令 说明 周期数(非延迟 /延迟)
B[D] 用指令中给出的地址加载 PC 4/2
BACC[D] 用指定累加器 ( A或 B) 的低 16位作为地址加载 PC 6/4
表 7-4 条件分支转移指令
指令 说明
周期数
(条件满足 /不满
足)
非延迟 延迟
BC[D] 如果指令中的条件满足, 就用指令中给出的地址加载 PC 5/3 3/3
BANZ[
D]
如果所选择的辅助寄存器不等于 0,就用指
令中给出的地址加载 PC( 用于循环 ) 4/2 2/2
表 7-5 远分支转移指令
指令 说明
周期数
(非
延迟 /延迟)
FB[D] 可以转移到由指令所给定的 23位地址 ( C5402为20位地址 ) 4/2
FBACC[
D]
可以转移到指定累加器所给定的 23位地址
( C5402为 20位地址 ) 6/4
返回本节
7.1.4 调用与返回
表 7-6 无条件调用与返回指令
表 7-7 条件调用与返回指令
表 7-8 远调用和远 返回指令
返回本节
7.1.5 重复操作
1,单条指令的重复操作
? RPT( 重复执行下一条指令 ) 和 RPTZ( 累加器
清 0后重复执行下一条指令 ) 可重复执行其后的
一条指令, 重复的次数是指令操作数加 1,这个
值保存在 16位的重复计数寄存器 ( RC) 中, 这
个值只能由重复指令 ( RPT或 RPTZ) 加载, 而
不能编程设置 RC寄存器中的值, 一次给定指令重
复执行的最大次数是 65536。
2,块重复操作指令
? 块重复指令 RPTB用于将一个码块重复执行 N+ 1
次, N是装入块重复计数器 ( BRC) 的值 。 一个
码块可以有一条或多条指令 。 单条重复指令执行
时关闭所有可屏蔽中断, 而块重复操作执行期间
可以响应中断 。
返回本节
7.1.6 TMS320C54x中断系统
1,中断类型
? C54x支持软件中断和硬件中断 。 软件中断由程序
指令产生 ( INTR,TRAP或 RESET) 。 硬件中断
由设备的一个信号产生, 包括两种类型,① 外部
硬件中断由外部中断口的信号触发; ② 内部硬件
中断由片内外设的信号触发 。 无论是硬件中断还
是软件中断, 都属于以下两种类型:
( 1) 可屏蔽中断 ( 2) 非屏蔽中断
表 7-9 C5402中断源的中断向量及
硬件中断优先权
2,中断标志寄存器 ( IFR) 和中断屏蔽寄存器
( IMR)
? 中断标志寄存器 ( IFR) 是存储器映象的 CPU寄
存器 。 如图 7-2所示为 C5402中断标志寄存器
( IFR) 结构图 。 中断屏蔽寄存器 ( IMR) 也是
存储器映象的 CPU寄存器, 用来屏蔽外部和内部
的可屏蔽中断, 其结构图同 IFR完全一致 。
图 7-2 中断标志寄存器( IFR) 结构图
3,中断响应过程 ( 如图 7-3所示 )
( 1) 接受中断请求 。
( 2) 响应中断 。
( 3) 执行中断服务程序 ( ISR) 。
接受中断请求
是可屏蔽中断吗?
IN TM = 0?
IM R 屏蔽位 = 1?
是硬件中断或
IN TR 指令中断吗?
响应中断, 发出 信号 IA C K
PC 保存到软件堆栈
执行中断服务程序
中断返回, 恢复 PC
继续执行主程序
IN TM 位置 1









7-
3







4,重新映象中断向量地址
? C54x的中断向量表是可重定位的, 即在 DSP复位
时, 中断向量表的起始地址固定为 0FF80H,复
位后, 此表的起始地址可由用户指定 。
? 中断向量可重新被映象到程序存储器的任何一个
128字页开始的地方 ( 除保留区域外 ) 。 中断向
量地址由 PMST中的中断向量指针 IPTR( 9位 )
和中断向量号 ( 0~ 31) 左移两位后组成 。 如图
7-4所示 。
中断向量号
左移两位后
中断向
量地址
图 7-4 中断向量地址的产生
返回本节
7.1.7 堆栈的使用
? 堆栈被用于保存中断程序、调用子程序的返回地
址,也用于保护和恢复用户指定的寄存器和数据,
还可用于程序调用时的参数传递。返回地址是由
DSP自动保存的。
? 用户编写的压栈指令和出栈指令将指定的内容压
入和弹出堆栈,SP总是指向最后压入堆栈的数据,
压栈之前 SP减 1,出栈之后 SP加 1。
? C54x支持软件堆栈, 在用户指定的存储区开辟一
块存储区作为堆栈存储器 。 堆栈的定义及初始化
步骤为:
1) 声明具有适当长度的未初始化段;
2) 将堆栈指针指向栈底;
3) 在链接命令文件 (,cmd) 中将堆栈段放入内部
数据存储区 。
返回本节
7.2 数据块传送
? C54x有 10条数据传送指令, 为:
? 数据存储器 ??数据存储器,MVDK Smem,dmad
MVKD dmad,Smem
MVDD Xmem,Ymem
? 数据存储器 ??MMR,MVDM dmad,MMR
MVMD MMR,dmad
MVMM mmr,mmr
返回首页
? 程序存储器 ??数据存储器:
MVPD Pmad,Smem
MVDP Smem,Pmad
READA Smem
WRITA Smem
1,编写汇编源程序为
.mmregs
.def _c_int00
.data
TBL,.word0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,1
7,18,19
.word 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1
PROM,.usect "PROM",20
.bss a,20
.bss x,20
.bss y,20
DATA,.usect "DATA",20
.text
_c_int00
b start
nop
nop
start:STM:
#a,AR1;a[20]={0,1,2,3,4,5,6,7,8,9,10,;11,12,13,14,15,16,17,18,19}
RPT #39 ;x[20]={1,1,1,1,1,1,1,1,1,1
MVPD TBL,*AR1+ ;1,1,1,1,1,1,1,1,1,1}
STM #x,AR2;将数据存储器中的数组 x[20]复制到数组 y[20]
STM #y,AR3
RPT #19
MVDD *AR2+,*AR3+
STM #a,AR1;将数据存储器中的 a[20]写入到程序存储器
PROM
LD #PROM,A
STM #19,AR3
LOOPP:WRITA *AR1+
ADD #1,A,A
BANZ LOOPP,*AR3-
LD #PROM-1,A ;读程序存储器 PROM中 20个数据存入数据
存储器 DATA
STM #DATA,AR1
ST #19,BRC
RPTB LOOP2
ADD #1,A,A
LOOP2,READA *AR1+ ; 该指令为单字指令
WAIT,NOP
B WAIT
2,建立汇编源程序
? 点击 CCS C5000 图标, 进入 CCS 环境, 再 点 击
File→ New→ Source File菜单命令, 打开一个空白文档,
将汇编源程序逐条输入 。
? 单击 File→ Save菜单命令, 出现如图 7-5所示的窗口, 选
择 D:\Program Files\ti \myprojcets\mymove子目录, 在
,文件名, 一栏中输入 mymove,并选择保存类型为
Assembly Source Files( *.asm), 单击, 保存, 按钮,
以上汇编程序被存盘 。
3,建立链接命令文件
? 点击 File→ New→ Source File菜单命令, 打开一个空白
文档, 逐条输入链接命令文件 。
mymove.obj
-o mymove.out
-m mymove.map
MEMORY
{PAGE 0,RAM,origin=1000h,length=800h
RAM1:
origin=2000h,length=300h
PAGE 1,DARAM1,origin=0100h,length=100h
DARAM2,origin=0200h,length=100h
}
SECTIONS
{
.data,>RAM PAGE 0
.text,>RAM PAGE 0
PROM, >RAM1 PAGE 0
.bss,>DARAM1 PAGE 1
DATA,>DARAM2 PAGE 1
}
? 点击 File→ Save 菜单命令, 如图 7 - 5 所示, 选择
D:\Program Files\ti\myprojcets\mymove 子 目录, 在
,文件名, 一栏中输入 mymove,并选择保存类型为 TI
Command Language File( *.cmd), 单击, 保存, 按
钮, 以上链接命令程序被存盘 。
4,创建一个新工程
? 在 Project 菜单中选择 New 项, 弹出 Project
Creation( 工程创建 ) 窗口, 如图 7-6所示 。 在
Project一栏键入 mymove,然后单击, 完成, 按
钮, CCS将创建一个名为 mymove.pjt的工程,
此文件保存了工程的设置信息及工程中的文件引
用情况 。
图 7-5 保存汇编源程序 图 7-6 工程创建窗口
5,将有关文件添加到工程中
? 从 Project菜单中选取 Add Files to Project命令,
选择文件 mymove.asm,双击将 mymove.asm
添加到工程中 。
? 点击 Project→ Add Files to Project菜单命令,
将 mymove.cmd添加到工程文件中 。
? 逐层打开如图 7-7所示 。 双击 mymove.asm打开文
件, 可以观察和修改 mymove.asm文件的内容 。
6,汇编, 编译和链接产生,out文件
? 点击 Project菜单中的 Rebuild All。 请注意在监
视窗口显示的汇编, 编译和链接的相关信息 。 如
果没有错误, 将产生 mymove.out文件;如果有
错, 在监视窗口以红色字体显示出错行, 用鼠标
双击该行, 光标跳将至源程序相应的出错行 。 修
改错误后, 重新汇编, 链接 。
7,加载并运行,out文件
? 执 行 菜 单 命 令 File→ Load Program,选择
mymove.out并打开, 将 Rebuild All生成的程序
加载到 DSP中 。 CCS将自动打开一个反汇编窗口,
显示加载程序的反汇编指令 。
? 点击 Debug→ Run菜单命令运行程序, 单步执行
程序则点击 Debug→ StepInto菜单命令, 或按 F8
键 。
8,观察运行结果
? 点击 View→ Memory菜单命令, 将出现如图 7-8
所示的选项窗口, 将 Address改为 0x0100,单击
OK按钮, 将在汇编窗口显示选定的数据空间的内
容 。
? 当结果数据错误时, 可检查源程序并进行修改 。
修改完毕, 可重新汇编, 链接, 再加载运行,out
文件, 直到结果正确 。
返回本节
7.3 定点数的基本算术运算
? 7.3.1 加法、减法和乘法运算
? 7.3.2 定点除法运算
返回首页
7.3.1 加法、减法和乘法运算
1,定点 DSP中数据表示方法
? 定点 DSP芯片的数值表示是基于 2的补码表示形
式 。 数的定标有 Q表示法和 S表示法, 表 7-10列出
了 16位数的 16种 Q表示和 S表示, 以及它们所能
表示的十进制数范围 。 16位中有一个符号位, Q
个小数位和 15-Q个整数位来表示一个数 。
表 7-10 Q表示,S表示及数值范围
图 7-9 DSP定点运算中小数的表示
2,16位定点加法和 16位定点减法
? C54x中提供了多条用于加法的指令, 如 ADD、
ADDC,ADDM和 ADDS。 其中, ADDS用于无
符号数的加法运算, ADDC用于带进位的加法运
算而 ADDM专用于立即数的加法 。
? C54x中提供了多条用于减法的指令, 如 SUB、
SUBB,SUBC和 SUBS。 其中, SUBS用于无符
号数的减法运算, SUBB用于带进位的减法运算,
而 SUBC为条件减法指令 。
3,16位定点整数乘法
? C54x中提供了大量的乘法运算指令, 其结果都是
32位, 放在累加器 A或 B中 。 乘数在 C54x的乘法
指令中很灵活, 可以是 T寄存器, 立即数, 存储
单元和累加器 A或 B的高 16位 。 在 C54x中, 一般
对数据的处理都当做有符号数, 如果是无符号数
相乘, 使用 MPYU指令, 这是一条专门用于无符
号数乘法运算的指令, 其他指令都是有符号数的
乘法 。
4,Q15定点小数乘法运算
? 两个 16位整数相乘, 乘积总是, 向左增长,, 这
就意味着多次相乘后乘积将会很快超出定点器件
的数据范围 。 而且要将 32位乘积保存到数据存储
器, 就要耗费两个机器周期以及两个字的程序和
RAM单元 。 然而, 两个 Q15的小数相乘, 乘积总
是, 向右增长,, 这就意味着超出定点器件数据
范围的将是不太感兴趣的部分 。
5,混合表示法
? 有些情况下, 运算过程中为了既满足数值的动态
范围又保证一定的精度, 必须采用 Q0与 Q15之间
的表示方法 。
? 在做加, 减运算时, 如果两个操作数的定标不一
样, 在运算前要进行小数点的调整, 为保证运算
精度, 需要使 Q值小的数调整为与另一个数的 Q
值一样大 。
返回本节
7.3.2 定点除法运算
? 在一般的 DSP中,没有专门的除法指令。同样,在 C54x
中也没有提供专门的除法指令。一般有两种方法来完成除
法。一种是用乘法来代替,除以某个数相当于乘以其倒数,
所以先求出其倒数,然后相乘。这种方法对于除以常数特
别适用。另一种方法是使用条件减法 SUBC指令,加上重
复指令 RPT #15,重复 16次减法完成无符号数除法运算。
两种不同情况下的除法程序。
1,|被除数 |<|除数 |,商为小数
2,|被除数 |≥|除数 |,商为整数
返回本节
7.4 长字运算和并行运算
? 7.4.1 长字运算
? 7.4.2 并行运算
返回首页
7.4.1 长字运算
? C54x可以利用长操作数 ( 32位 ) 进行长字运算 。
如下所示为长字指令:
DLD Lmem,dst ;dst=Lmem
DST src,Lmem ;Lmem=src
DADD Lmem,src[,dst] ;dst=src + Lmem
DSUB Lmem,src[,dst] ;dst=src – Lmem
DRSUB Lmem,src[,dst] ;dst=Lmem - src
返回本节
7.4.2 并行运算
? 并行运算,就是同时利用 D总线和 E总线。其中,
D总线用来执行加载或算术运算,E总线用来存放
先前的结果。在不引起硬件资源冲突的情况下,
C54x允许某些指令并行执行(即同时执行),以
提高执行速度。
? 并行指令有并行加载 ——存储指令、并行加载 —
—乘法指令、并行存储 ——乘法指令,以及并行
存储 ——加 /减法指令,所有并行指令都是单字单
周期指令。
返回本节
7.5 FIR滤波器的 DSP实现
? 7.5.1 线性缓冲区法
? 7.5.2 循环缓冲区法
? 7.5.3 系数对称 FIR滤波器的 DSP实现
返回首页
? 数字滤波是 DSP的最基本应用, 利用 MAC( 乘,
累加 ) 指令和循环寻址可以方便地完成滤波运算 。
两种常用的数字滤波器,FIR( 有限冲激响应 )
滤波器和 IIR( 无限冲激响应 ) 滤波器的 DSP实现 。
? 设 FIR滤波器的系数为 h(0),h(1),...,h(N-1),
X(n)表示滤波器在 n时刻的输入, 则 n时刻的输出
为:
? ?
?
?????????
1N
0i
)in(x)i(h)]1N(n[x)1N(h)1n(x)1(h)n(x)0(h)n(y ?
( 7-1)
? 其对应的滤波器传递函数为:
? 如图 7-10所示为横截型 ( 又称直接型或卷积型 )
FIR数字滤波器的结构图 。
i
1N
0i
z)i(h)z(H ?
?
?
??
x ( n ) Z -1 Z -1 Z -1
h ( 0 ) h ( 1 ) h ( 2 ) h ( N - 2 ) h ( N - 1 )
y ( n )
图 7-10 横截型 FIR数字滤波器的结构图
( 7-2)
? 线性缓冲区法又称延迟线法 。 其方法是:对于
n=N的 FIR滤波器, 在数据存储器中开辟一个 N单
元的缓冲区, 存放最新的 N个样本;滤波时从最
老的样本开始, 每读一个样本后, 将此样本向下
移位;读完最后一个样本后, 输入最新样本至缓
冲区的顶部 。
? 以上过程,可以用 N=6的线性缓冲区示意图来说
明,如图 7-11所示
7.5.1 线性缓冲区法
图 7-11 N=6的线性缓冲区示意图
返回本节
7.5.2 循环缓冲区法
? 图 7-12说明了使用循环寻址实现 FIR滤波器的方
法。对于 N级 FIR滤波器,在数据存储区开辟一个
称为滑窗的具有 N个单元的缓冲区,滑窗中存放
最新的 N个输入样本值。每次输入新的样本时,
新的样本将改写滑窗中最老的数据,其他数据则
不需要移动。
图 7-12 FIR滤波器循环缓冲区存储器图
? 【 例 7-12】 用循环缓冲区和双操作数寻址方法编
写实现 FIR滤波的程序 。
1,FIR滤波器设计
? 设计一个 FIR低通滤波器, 通带边界频率为
1500Hz,通带波纹小于 1dB; 阻带边界频率为
2000Hz,阻带衰减大于 40dB; 采样频率为
8000Hz。 FIR滤波器的设计可以用 MATLAB窗函
数法进行 。
2,产生滤波器输入信号的文件
? 按照通常的程序调试方法, 先用 Simulator逐步
调试各子程序模块, 再用硬件仿真器在实际系统
中与硬件仪器联调 。 使用 CCS的 Simulator进行
滤波器特性测试时, 需要输入时间信号 x(n)。 本
例设计一个采样频率 Fs为 8000Hz,输入信号频
率为 1000Hz和 2500Hz的合成信号, 通过设计的
低通滤波器将 2500Hz信号滤掉, 余下 1000Hz信
号 。
3,编写 FIR数字滤波器的汇编源程序
FIR数字滤波器汇编程序 fir.asm如下:
************一个 FIR 滤波器源程序
fir.asm*****************
.mmregs
.global start
.def start,_c_int00
INDEX,set 1
KS,set 256 ;输入样本数据个数
COEF_FIR,sect "COEF_FIR" ;FIR滤波器系数
? N,set 17;FIR滤波器阶数
.word 0,158,264,-290,-1406,-951,3187,9287,12272
.word9287,3187,-951,-1406,-290,264,158,0
.data
INPUT,copy "firin.inc" ;输入数据在数据区 0x2400
OUTPUT,space 1024;输出数据在数据区 0x2500
COEFTAB,usect "FIR_COEF",N
DATABUF,usect "FIR_BFR",N
BOS,usect "STACK",0Fh
TOS,usect "STACK",1
.text
.asg AR0,INDEX_P
?,asg AR4,DATA_P ;输入数据 x(n)循环缓冲区指针
?,asg AR5,COEF_P ;FIR系数表指针
?,asg AR6,INBUF_P ;模拟输入数据指针
?,asg AR7,OUTBUF_P ;FIR滤波器输出数据指针
? _c_int00
? b start
? nop
? nopstart,SSBx FRCT;小数乘法编程时, 设置 FRCT(小数方式 )位
? MVPD #COEF_FIR,*COEF_P+
? STM #INDEX,INDEX_P
? STM #DATABUF,DATA_P ;数据循环缓冲区清零
? RPTZA,#N-1
? STL A,*DATA_P+
? STM #(DATABUF+N-1),DATA_P;数据循环缓冲区指针指向 x[n-
(N-1)]
? STM #COEFTAB,COEF_P
? STM #COEFTAB,COEF_P ;将 FIR系数从程序存储器移到数据存储器
? RPT #N-1
? FIR_TASK:
? STM #INPUT,INBUF_P
? STM #OUTPUT,OUTBUF_P
STM #KS-1,BRC
RPTBD LOOP-1
STM #N,BK ;FIR循环缓冲区大小
LD *INBUF_P+,A ;装载输入数据
FIR_FILTER,;FIR滤波运算
STL A,*DATA_P+% ;用最新的样本值替代最旧的样本值
RPTZ A,N-1
MAC *DATA_P+0%,*COEF_P+0%,A
STH A,*OUTBUF_P+
LOOP:
EEND B EEND
.end
4,编写 FIR滤波器链接命令文件
? 对应以上汇编程序的链接命令文件 fir.cmd如下:
fir.obj
-m fir.map
-ofir.out
MEMORY
{
PAGE 0,ROM1(RIX),ORIGIN=0080H,LENGTH=100H
PAGE 1,INTRAM1(RW),ORIGIN=2400H,LENGTH=0200H
INTRAM2(RW),ORIGIN=2600H,LENGTH=0100H
INTRAM3(RW),ORIGIN=2700H,LENGTH=0100H
B2B(RW),ORIGIN=0070H,LENGTH=10H
}
SECTIONS
{
.text, {}>ROM1 PAGE 0
.data, {}>INTRAM1 PAGE 1
FIR_COEF,{}>INTRAM2 PAGE 1
FIR_BFR, {}>INTRAM3 PAGE 1
.stack, {}>B2B PAGE 1
}
5,CCS集成开发环境下上机操作过程
( 1) 在 CCS上建立 fir工程并运行 fir.out程序 。
( 2) 观察输入信号的波形及频谱 ( 如图 7-13~7-15
所示 ) 。
( 3) 观察输出信号的波形及频谱 ( 如图 7-16,7-
17所示 ) 。
图 7-13 Graph 属性设置窗口
图 7-14 输入信号的时域波形
图 7-15 输入信号的频谱图
图 7-16 滤波器输出信号
时域波形
图 7-17 滤波器输出
信号频谱图
返回本节
7.5.3 系数对称 FIR滤波器的 DSP实现
1,在数据存储器中开辟两个循环缓冲区:
? New 循 环缓冲 区中 存放 N/2=4 个 新数 据 ( 设
N=8) ; Old循环缓冲区中存放 4个老数据 。 循环
缓冲区的长度为 N/2。 缓冲区指针 AR2指向 New
缓冲区中最新的数据; AR3指向 Old 缓冲区中最
老的数据, 并在程序存储器中设置系数表, 如图
7-18所示 。
2.(AR2)+(AR3)→ AH( 累加器 A的高位 )
? (AR2)-1→AR 2,(AR3)-1→AR 3
3,将累加器 B清 0,重复执行以下操作 N/2次 ( i=0,
1,2,3),
? (AH)× 系数 ai+(B)→B, 系数指针 ( PAR) 加 1
? (AR2)+(AR3)→AH, AR2 和 AR3减 1
? 并保存或输出结果 ( 结果在 BH中 ) 。
4,修正数据指针
? 将 AR2和 AR3分别指向 New缓冲区中最新的数据
和 Old 缓冲区中最老的数据 。 用 New 缓冲区最老
的数据替代 Old 缓冲区中最老的数据, 如图 7-18
中箭头所示 。 Old 缓冲区指针减 1。
5,输入一个新的数据替代 New 缓冲区中最老的数

? 重复执行步骤 2~ 5。
返回本节
7.6 IIR数字滤波器的 DSP实现
? IIR数字滤波器的传递函数 H(z)为:
? 其对应的差分方程为:
? 例如, 对于直接形式的二阶 IIR数字滤波器, 其结
构如图 7-19所示, 编程时, 可以分别开辟四个缓冲
区, 存放输入, 输出变量和滤波器的系数, 如图 7-
20所示 。
?
?
?
?
?
?
?
?
N
1i
i
i
M
0i
i
i
za1
zb
)z(H
)in(ya)in(xb)n(y
N
1i
i
M
0i
i ???? ??
??
( 7-4)
( 7-3)
返回首页
图 7-19 直接形式的二阶 IIR数字滤波器
图 7-20 存放输入、输出变量和滤
波器系数的缓冲区
? 【 例 7-15】 设计一个三阶的切比雪夫 Ⅰ 型带通数字滤波器,
其采样频率 Fs =16kHz,其通频带 3.2kHz<f<4.8kHz,内
损耗不大于 1dB; f <2.4kHz和 f >5.6kHz为阻带, 其衰减
大于 20dB。
1,IIR滤波器的设计
? 在 MATLAB中设计 IIR滤波器, 程序为:
wp=[3.2,4.8];ws=[2.4,5.6];rp=1;rs=20
[n,wn]=cheb1ord(wp/8,ws/8,rp,rs)
[b,a]=cheby1(n,rp,wn)
? 设计结果为:
N=3
wn =0.4000 0.6000
b0=0.0114747 a0=1.000000
b1=0 a1=0
b2=-0.034424 a2=2.13779
b3=0 a3=0
b4=0.034424 a4=1.76935
b5=0 a5=0
b6=-0.0114747 a6=0.539758
2,产生滤波器输入信号的文件
? 使用 CCS的 Simulator进行滤波器特性的测试时, 需要输
入时间信号 x(n)。 #include <stdio.h>
#include <math.h>
void main()
{
int i;
double f[256];
FILE *fp;
if((fp=fopen("iirin.inc","wt"))==NULL)
{
printf("can't open file! \n");
return;
}
fprintf(fp,"INPUT,.sect %cINPUT %c\n",'"','"');
for(i=0;i<=255;i++)
{
f[i]=sin(2*3.14159*i*4000/16000)+sin(2
*3.14159*i*6500/16000);
fprintf(fp,",word
%1d\n",(long)(f[i]*32768/2));
}
fclose(fp);
}
? 该程序将产生名为 iirin.inc的输入信号程序, 内容如下:
INPUT,.sect "INPUT"
.word 0
.word 25486
.word -15136
.word -314
.word -11585
.word 19580
.word 6270
.word -30006
.word 16383
? 然后, 在 DSP汇编语言程序中通过,copy汇编命令将生成
的数据文件 iirin.inc复制到汇编程序中, 作为 IIR滤波器的
输入数据 。
3,直接型 IIR数字滤波器汇编源程序的编写
? 直接型 IIR数字滤波器汇编程序 diir.asm如下:
********直接型 IIR数字滤波器通用程序 **********
.title "diir.asm"
.mmregs
.global start
.def start,_c_int00
N,set 16
.copy "iirin.inc" ;输入信号 x(n)数据
table ;IIR滤波器系数
.word 63,0,-188,0,188,0,-63
.word 0,11675,0,9663,0,2948
.data
BN,usect "BN",N+1
AN,usect "AN",N+1
INBUF,usect "INBUF",256;输入缓冲区在数据区 0x2400
OUTPUT,usect "OUTPUT",256;输出缓冲区在数据区 0x2600
.text
.asg AR0,INDEX_P
.asg AR2,XN_P
.asg AR3,ACOFF_P
.asg AR4,YN_P
.asg AR5,BCOFF_P
_c_int00
b start
nop
nop
start,SSBX FRCT
SSBX OVM
SSBX SXM
STM #BN+N,AR1
RPT #N
MVPD #table,*AR1-; ; 将 bi由程序区存放到数据区
STM #AN+N-1,AR1
RPT #N-1
MVPD #table+N+1,*AR1- ; 将 ai由程序区存放到数据区
STM #OUTPUT,AR1
RPTZ A,#255
STL A,*AR1+ ; 输出数据缓冲区清零
STM #INBUF,AR1
RPT #255
MVPD #INPUT,*AR1+ ; 将输入数据由程序区
STM #OUTPUT,YN_P
STM #INBUF,XN_P
STM #N-1,INDEX_P
STM #255,BRC
RPTB LOOP-1
IIR,SUB A,A
STM #BN,BCOFF_P
STM #AN,ACOFF_P
RPT #N-1 ; 计算前向通道
MAC *XN_P+,*BCOFF_P+,A
MAC *XN_P,*BCOFF_P,A
MAR *XN_P-0 ; 将 AR2指针指向 x(n-N)
RPT #N-1; 计算反馈通道
MAC *YN_P+,*ACOFF_P+,A
STH A,*YN_P-0 ; 保存 y(n)
LOOP:
EEND B EEND
.end
4,IIR滤波器链接命令文件的编写
? 对应以上汇编程序的链接命令文件 diir.cmd如下:
diir.obj
-o diir.out
-m diir.map
MEMORY
{
PAGE 0,ROM,ORIGIN=0080H,LENGTH=1000H
PAGE 1,SPRAM,ORIGIN=0060H,LENGTH=0020H
DARAM,ORIGIN=0080H,LENGTH=1380H
RAM1,ORIGIN=2400H,LENGTH=0200H
RAM2,ORIGIN=2600H,LENGTH=0200H
}
SECTIONS
{
.text:>ROM PAGE 0
.data:>DARAM PAGE 1
BN,>DARAM PAGE 1
AN,>DARAM PAGE 1
INBUF:>RAM1 PAGE 1
OUTPUT,>RAM2 PAGE 1
}
返回本节
7.7 FFT运算的 DSP实现
? 7.7.1 基二实数 FFT运算的算法
? 7.7.2 FFT运算模拟信号的产生及输入
? 7.7.3 实序列 FFT汇编源程序及链接命令文件
? 7.7.4 观察信号时域波形及其频谱
返回首页
7.7.1 基二实数 FFT运算的算法
? 该算法主要分为以下四步 。
第一步, 输入数据的组合和位倒序
? 把输入序列作位倒序是为了在整个运算最后的输
出中得到的序列是自然顺序 。 如图 7-21所示 。
第二步, N点复数 FFT
? 在 DATA数据处理缓冲器里进行 N点复数 FFT运算 。
如图 7-22所示 。
第三步, 分离复数 FFT的输出为奇部分和偶部分
? 分离 FFT输出为 RP,RM,IP和 IM四个序列, 即
偶实数, 奇实数, 偶虚数和奇虚数四部分 。
第四步, 产生 2N点的复数 FFT输出序列
? 产生 2N=256个点的复数输出, 它与原始的 256个
点的实输入序列的 DFT一致 。 如图 7-24所示 。
返回本节
7.7.2 FFT运算模拟信号的产生及输入
? 产生模拟输入信号可以有两种方法, 第一种方法是用 C
语言程序产生 mdata.inc文件, 然后, 在 DSP汇编语言
程序中通过,copy汇编命令将生成的数据文件 mdata.inc
复制到汇编程序中, 如例 7-12和例 7-15,数据起始地址
标号为 INPUT,段名为 INPUT。 第二种方法是首先建立
与输入信号对应的数据流文件 mdata.dat,其数据格式
如下:
1651 1 0 1 0
0x1f400x1f40
……
?
返回本节
7.7.3 实序列 FFT汇编源程序及链接命令文件
? 【 例 7-16】 256点实序列 FFT的 DSP实现 。
? 256点实序列 FFT汇编源程序如下:
*************************************
*Radix-2,DIT,Real-input FFT Program *
* fft.asm *
*************************************
.mmregs
.global reset,start,sav_sin,sav_idx,sav_grp
.def start,_c_int00
.data
DATA,space 1024
.copy "mdata1.inc"; mdata1.inc为模拟输入信号数据, 起始地址标号 INPUT
N.set 128 ;复数点数
LOGN,set 7 ;蝶形级数
sav_grp,usect "tempv",3 ;定义组变量值
sav_sin,set sav_grp+1 ;定义旋转因子表
sav_idx,set sav_grp+2
OUTPUT,usect "OUTPUT",256 ;信号功率谱
BOS,usect "stack",0Fh ;定义堆栈
TOS,usect "stack",1
.copy "twiddle1.inc";正弦表系数由 twiddle1.inc文件给出, 起始地址标号 TWI1
.copy "twiddle2.inc";余弦表系数由 twiddle2.inc文件给出, 起始地址标号 TWI2
.text
_c_int00
b start
nop
nop
start:
STM #TOS,SP
LD #0,DP
SSBX FRCT
****************************************************
*************
返回本节
7.7.4 观察信号时域波形及其频谱
? 经程序计算得到的信号功率谱放在数据存储区
0 x2000开始的 256个单元中 。 在 CCS中选择
View→ Graph→ Time/Frequency命令, 选择程
序区 0x9000开始的 256个单元中, Display Type
分别选择为 FFT Magnitude和 Single Time,则
信号频谱图及其时域波形如图 7-25上半部分所示 。
将起始地址改为 0x2000,page选项改为 data,
Sampling Rate为 256,Display Type为 Single
Time,如图 7-25。
图 7-25 输入信号时域波形、频谱图及其功率谱
返回本节