基于DSP的正弦信号发生器的设计
发布时间:2011-07-05 20:48:18
发布时间:2011-07-05 20:48:18
基于DSP的正弦信号发生器的设计
1、绪论
1.1 课题背景
数字信号处理(Digital Signal Processing,简称DSP)是一门涉及许多学科而又广泛应用于许多领域的新兴学科。20世纪60年代以来,随着计算机和信息技术的飞速发展,数字信号处理技术应运而生并得到迅速的发展。数字信号处理是一种通过使用数学技巧执行转换或提取信息,来处理现实信号的方法,这些信号由数字序列表示。在过去的二十多年时间里,信号处理已经在通信等领域得到了极为广泛的应用。
长期以来,信号处理技术—直用于转换或产生模拟或数字信号。其中应用的最频繁的领域就是信号的滤波。此外,从数字通信、语音、音频和生物医学信号处理到检测仪器仪表和机器人技术等许多领域中,都广泛地应用了数字信号处理技术。数字信号处理己经发展成为一项成熟的技术,并且在许多应用领域逐步代替了传统的模拟信号处理系统。而本文中基于DSP技术设计的正弦波信号发生器已被广泛地应用于通信、仪器仪表和工业控制等领域的信号处理系统中。
1.2 课题内容
利用基于CCS开发环境中的C54x汇编语言来实现正弦信号发生装置。
2、 设计原理
一般情况,产生正弦波的方法有两种:查表法和泰勒级数展开法。查表法是使用比较普遍的方法,优点是处理速度快,调频调相容易,精度高,但需要的存储器容量很大。泰勒级数展开法需要的存储单元少,具有稳定性好,算法简单,易于编程等优点,而且展开的级数越多,失真度就越小。
本文采用了泰勒级数展开法。一个角度为θ的正弦和余弦函数,可以展开成泰勒级数,取其前5项进行近似得:
式中:为θ的弧度值, (是采样频率;f是所要发生的信号频率)
3、 设计方案
本设计采用TMS320C54X系列的DSP作为正弦信号发生器的核心控制芯片。
通过计算一个角度的正弦值和余弦值程序可实现正弦波,其步骤如下:
1.利用sinx和cosx子程序,计算0—45°(间 隔为0.5°)的正弦和余弦值
2.利用sin(2x)=2sin(x)cos(x)公式,计算0—90°的正弦值(间隔为1°)
3.通过复制,获得0—359°的正弦值
4.将0—359°的正弦值重复从PA口输出,遍可得到正弦波
整个系统相应的软件流程图如右图所示。
图1 程序流程图
4、程序设计
4.1 产生正弦波程序清单sin.asm
.title "sin.asm" //为汇编文件取名为“sin.asm”
.mmregs //定义存储器映像寄存器
.def _c_int00
.ref sinx,d_xs,d_sinx,cosx,d_xc,d_cosx //定义标号
sin_x: .usect "sin_x",360 //为"sin_x"保留360个存储空间
STACK: .usect "STACK",10 //为堆栈保留10个存储空间
k_theta .set 286 //theta=pi/360(0.5deg)
PA0 .set 0
_c_int00
.text //定义文本程序代码段
STM #STACK+10,SP //设置堆栈指针
STM k_theta,AR0 //AR0-->K_theta(increment)
STM 0,AR1 //(AR1)=X(rad)
STM #sin_x,AR6 //AR6→sin(x)
STM #90,BRC //form sin0(deg.)—sin90(deg)
RPTB loop1-1 //重复执行块语句(下条语句开始至
loop1-1)91次
LDM AR1,A
LD #d_xs,DP
STL A,@d_xs //(A)低16位→d_xs
STL A,@d_xc //(A)低16位→d_xc
CALL sinx //调用sinx程序
CALL cosx //调用cosx程序
LD #d_sinx,DP //DP←d_sinx
LD @d_sinx,16,A //A=sin(x)
MPYA @d_cosx //B= sin(x)*cos(x)
STH B,1,*AR6+ //AR6→2*sin(x)*cos(x)
MAR *AR1+0 //修改辅助寄存器AR1
loop1: STM #sin_x+89,AR7 //sin91(deg.)—sin179(deg.)
STM #88,BRC
RPTB loop2-1 //重复执行下条指令至loop2-1处90次
LD *AR7-,A //((AR7)) →A,然后AR7减去1
STL A,*AR6+ //(A) 低16位→AR6
loop2: STM #179,BRC //sin180(deg.)—sin359(deg.)
(BRC)=179,重复执行180次
STM #sin_x,AR7 //AR7指向sin_x首地址
RPTB loop3-1
LD *AR7+,A //((AR7)) →A,然后AR7加1
NEG A //累加器变负
STL A,*AR6+ //A低16位→AR6
loop3: STM #sin_x,AR6 //AR6指向sin_x
STM #1,AR0 //AR←01
STM #360,bk //BK←360
loop4: PORTW *AR6+0%,PA0 //PA0=*AR6+0%,向PA0输出数据
B loop4
sinx:
.def d_xs,d_sinx //定义标号d_xs,d_sinx
.data //定义数据代码段
table_s .word 01c7h //c1=1/(8*9)
.word 030bh //c1=1/(6*7)
.word 0666h //c1=1/(4*5)
.word 1556h //c1=1/(2*3)
d_coef_s .usect "coef_s",4 //为"coef_s"保留4个存储空间
d_xs .usect "sin_vars",1 //为d_xs中sin_vars保留1个存
储空间
d_squr_xs .usect "sin_vars",1 //为d_squr_xs中sin_vars保留1个存储空间
d_temp_s .usect "sin_vars",1 //为d_temp_s中sin_vars保留1个
存储空间
d_sinx .usect "sin_vars",1 //为d_sinx中sin_vars保留1个存储空间
c_l_s .usect "sin_vars",1 //为d_xs中sin_vars保留1个存储
空间
.text //定义代码开始段
SSBX FRCT //设置FRCT=1以解决冗余符号位
STM #d_coef_s,AR5 //AR5指向d_coef_s首地址
RPT #3 //重复下条指令4次
MVPD #table_s,*AR5+ //table_s中的数复制到AR5指向
的单元
STM #d_coef_s,AR3 //AR3指向d_coef_s首地址
STM #d_xs,AR2 //AR2指向d_xs首地址
STM #c_l_s,AR4 //AR4指向c_l_s首地址
ST #7FFFh,c_l_s //7FFFh →c_l_s
SQUR *AR2+,A //AR2指向累加器A中的数值求其平方
ST A,*AR2 //(A)左移16位→AR2
||LD *AR4,B //(AR4)左移16位→B
MASR *AR2+,*AR3+,B,A //从累加器A中减去(AR2)*(AR3)
MPYA A //操作数与累加器A中高位相乘
STH A,*AR2 //(A)高16位→AR2
MASR *AR2-,*AR3+,B,A //从累加器A中减去(AR2)*(AR3)
MPYA *AR2+ //AR2指向的数与累加器A的高16位相乘
ST B,*AR2 //(B)左移16位→AR2
||LD *AR4,B //(AR4)左移16位→B
MASR *AR2-,*AR3+,B,A //从累加器A中减去(AR2)*(AR3)
MPYA *AR2+ //与累加器A中高16位相乘
ST B,*AR2 //(B)左移16位→AR2
||LD *AR4,B //(AR4)左移16位→B
MASR *AR2-,*AR3+,B,A //从累加器A中减去(AR2)*(AR3)
MPYA d_xs //d_xs指向的操作数与累加器A中高16位相乘
STH B,d_sinx //(B)高16位→d_sinx
RET //返回
cosx:
.def d_xc,d_cosx //定义标号d_xc,d_cosx
d_coef_c .usect "coef_c",4 //为coef_c保留4个存储空间
.data //定义数据代码段
table_c .word 0249h //c1=1/(7*8)
.word 0444h //c1=1/(6*5)
.word 0aabh //c1=1/(3*4)
.word 4000h //c1=1/2
d_xc .usect "cos_vars",1 //为d_xc中cos_vars保存1个存储单元
d_squr_xc .usect "cos_vars",1 //为d_squr_xc中cos_vars保存1个
存储单元
d_temp_c .usect "cos_vars",1 //为d_temp_c中cos_vars保存1个存储单元
d_cosx .usect "cos_vars",1 //为d_cosx中cos_vars保存1个存储单元
c_l_c .usect "cos_vars",1 //为c_l_c中cos_vars保存1个存储单元
.text //定义文本代码段
SSBX FRCT //FRCT=1以清除冗余符号位
STM #d_coef_c,AR5 //AR5指向d_coef_c首地址
RPT #3 //重复下条指令4次
MVPD #table_c,*AR5+ //把table_c中的数复制到中AR5
STM #d_coef_c,AR3 //AR3指向d_coef_c首地址
STM #d_xc,AR2 //AR2 指向d_xc首地址
STM #c_l_c,AR4 //AR4指向c_l_c首地址
ST #7FFFh,c_l_c //7FFFh→c_l_c
SQUR *AR2+,A //求x的平方存放在累加器A中
ST A,*AR2 //(A)左移16位→AR2
||LD *AR4,B //(AR4)左移16位→B
MASR *AR2+,*AR3+,B,A //A=1-x^2/56,T=x^2
MPYA A //A=T*A=x^2(1-x^2/56)
STH A,*AR2 //(d_temp)= x^2(1-x^2/56)
MASR *AR2-,*AR3+,B,A //A=1-x^2/30(1-x^2/56)
T= x^2(1-x^2/56)
MPYA *AR2+ //B=x^2(1-x^2/30(1-x^2/56))
ST B,*AR2 //(d_temp)= x^2(1-x^2/30(1-x^2/56))
||LD *AR4,B //B=1
MASR *AR2-,*AR3+,B,A //A= 1-x^2/12(1-x^2/30(1-x^2/56))
SFTA A,-1,A
NEG A
MPYA *AR2+ //B=1-x^2/2(1-x^2/12(1-x^2/30(1-x^2/56)))
MAR *AR2+
RETD
ADD *AR4,16,B //B=1-x^2/2(1-x^2/12(1-x^2/30(1-x^2/56)))
STH B,*AR2 //cos(theta)
RET
.end
4.2 正弦波程序链接命令文件sin.cmd
.cmd文件描述输入文件和输出文件,说明系统中有哪些可用存储器、程序段、堆栈及复位向量和中断向量等安排在什么地方。其中MEMORY段就是用来规定目标存储器的模型,通过这条指令,可以定义系统中所包含的各种形式的存储器,以及它们占据的地址范围;SECTIONS段说明如何将输入段组合成输出段以及在可执行文件中定义输出段、规定输出段在存储器中的位置等。
MEMORY
{
PAGE 0:
EPROM: org = 0E000h, len = 1000h
VECS: org = 0FF80h, len = 0080h
PAGE 1:
SPRAM: org = 0060h, len = 0020h
DARAM1: org = 0080h, len = 0010h
DARAM2: org = 0090h, len = 0010h
DARAM3: org = 0200h, len = 0200h
}
SECTIONS
{
.text :>EPROM PAGE 0 //文本代码段其实地址为0E000h,长度为
1000h
.data :>EPROM PAGE 0 //数据代码段其实地址为0D000h
STACK :>SPRAM PAGE 1 //堆栈起始地址为0060h,长度为0020h
sin_vars :>DARAM1 PAGE 1 //标号为sin_vars段的起始地址为0080
长度为0010h
coef_s :>DARAM1 PAGE 1 //标号为coef_s段的起始地址为0070h
长度为0010h
cos_vars :>DARAM2 PAGE 1 //标号为cos_vars段的起始地址为0090h
长度为0010h
coef_c :>DARAM2 PAGE 1 //标号为coef_c段的起始地址为0080h
长度为0020h
sin_x : align(512) {} > DARAM3 PAGE 1
.vectors :>VECS PAGE 0
}
5、仿真与调试
5.1 CCS工程项目的调试
利用 CCS 集成开发环境,用户可以在一个开发环境下完成工程定义、程序 编辑、编译链接、调试和数据分析等工作环节。
⑴ 创建工程(project)文件
选择 Project→New,在“Project”文本框中键入将要创建的工程项目名,本例工程项目名为“sin”
⑵ 向工程中添加文件
选择 Project→Add Files to Project,将 sine.asm文件自动添加到 Project→Source 中。 用同样的方法 将 sine.cmd 文件添加到对应的目录中。
⑶ 构建工程,
工程所需文件编辑完成后,可以对该工程进行编译链接,产生可执行文件, 为调试做准备。
选择 Project→Build,系统提示没有出错信息后,系统自动生成一个可执行文件,sine.out 文件。
⑷ 载入可执行文件
选择 File→Load Program 载入编译链接好的可执行文件sine.out
⑸ 运行程序
选择 Debug→Run运行,可以通过查看内存表等方法,看到程序运行的结果。
5.2 仿真结果
选择 View→Graph→Time/Frequence
得到的正弦波形如下图所示:
输出结果显示,在CCS图形观察窗口得到了频率稳定,信号干扰小,波形失真度较小的正弦信号。
6、心得体会
通过这次的课程设计使我进一步加深了对于DSP这门课程的学习以及对于平时所学内容的实际应用。在设计中发现问题和同学互相讨论研究,并在编程过程中进一步提高自身的创作、创新水平,扎实基础,扩展所学。在输入程序时发现编程确实是要求很认真细心的,如果稍有差错就会导致整个程序的错误,也由此体现了DSP这门课程的严谨性。相信在以后的学习中一定会更好的应用所学内容的。