DSP课程设计
DSP原理及应用课程设计一、设计题目——正弦波信号发生器
二、设计目的
1、掌握用汇编语言编写输出正弦波信号的程序
2、掌握正弦波信号的 DSP 实现原理和 C54X 编程技巧
3、进一步加深对CCS 的认识
4、能通过 CCS 的图形显示工具观察正弦信号波形三、实验设备
PC 兼容机一台,操作系统为 WindowsXP,安装Code Composer Studio 3.1软件。
四、设计原理
在通信、仪器和工业控制等领域的信号处理系统中常常会用到信号发生器来产生正弦波! 产生正弦波的方法一是查表法,二是泰勒级数展开法!查表法主要用于对精度要求不很高的场合,而泰勒级数展开法是一种比查表法更为有效的方法,它能精确地计算出一个角度的正弦和余弦值,且只需要较少的存储空间。本实验将利用泰勒级数展开法利用计算一个角度的正弦值和余弦值程序可实现正弦波。
(1)产生正弦波的算法:在高等数学中,正弦函数和余弦函数可以展开成泰勒级数,其表达式为:
3579xxxxsin(x),x,,,,,... 3!5!7!9!
2468xxxx cos(x),1,,,,,...2!4!6!8!
若要计算一个角度的正弦和余弦值,可取泰勒级数的前五项进行近似计算。
3579xxxxx,x,,,,,sin()...3!5!7!9!
2222xxxx(1(1(1(1)))),x,,,,,,,,23456789
2468xxxx cos(x),1,,,,,... 2!4!6!8!
2222xxxx,,,,, 1(1(1(1))) ,,,2345678
由这两个式子可推导出递推公式,即
sin(nx),2cos(x)sin[(n,1)x],sin[(n,2)x]
cos(nx),2cos(x)sin[(n,1)x],cos[(n,2)x]
由递推公式可以看出,在计算正弦和余弦值时,不仅需要已知
,而且还需要、和。 cos(x)sin(n,1)xsin(n,2)xcos(n,2)x
(2)正弦波的实现
1、计算一个角度的正弦值
利用泰勒级数的展开式,可计算一个角度x的正弦值,并采用子程序的调用方式。在调用前先在数据存储器d_xs单元中存放x的弧度值,计算结果存放在
d_sinx单元中。
实现计算一个角度的正弦值的程序片段如下: sinx:
.def d_xs,d_sinx
.data
table_s .word 01C7H ;C1=1/(8*9)
.word 030BH ;C2=1/(6*7)
.word 0666H ;C3=1/(4*5)
.word 1556H ;C4=1/(2*3)
d_coef_s .usect "coef_s",4
d_xs .usect "sin_vars",1
d_squr_xs .usect "sin_vars",1
d_temp_s .usect "sin_vars",1
d_sinx .usect "sin_vars",1
d_l_s .usect "sin_vars",1
.text
SSBX FRCT
STM #d_coef_s,AR5 ;move coeffs table_s
RPT #3
MVPD #table_s,*AR5+
STM #d_coef_s,AR3
STM #d_xs,AR2
STM #d_l_s,AR4
ST #7FFFH,d_l_s
SQUR *AR2+,A ;A=x^2
ST A,*AR2 ;(AR2)=x^2
||LD *AR4,B ;B=1
MASR *AR2+,*AR3+,B,A ;A=1-x^2/72,T=x^2
MPYA A ;A=T*A=x^2(1-x^2/72)
STH A,*AR2 ;(d_temp)=x^2(1-x^2/72)
MASR
*AR2-,*AR3+,B,A ;A=1-x^2/42(1-x^2/72);T=x^2(1-x^2/72) MPYA *AR2+ ;B=x^2(1-x^2/42(1-x^2/72))
ST
B,*AR2 ;(d_temp)=x^2(1-x^2/42(1-x^2/72))
||LD *AR4,B ;B=1
MASR
*AR2-,*AR3+,B,A ;A=1-x^2/20(1-x^2/42(1-x^2/72)) MPYA
*AR2+ ;B=x^2(1-x^2/20(1-x^2/42(1-x^2/72)))
ST B,*AR2 ;(d_temp)=B
||LD *AR4,B ;B=1
MASR
*AR2-,*AR3,B,A ;A=1-x^2/6(1-x^2/20(1-x^2/42(1-x^2/72))) MPYA d_xs ;B=x(1-x^2/6(1-x^2/20(1-x^2/42(1-x^2/72)))) STH B,d_sinx ;sin(theta)
RET
2、计算一个角度的余弦值
利用余弦函数展开的泰勒级数的前五项计算一个角度的余
弦值,可采用子程序的调用方式来实现。调用前先将x弧度值放在数据存储器d_xc单元中,计算结果存放在d_cosx单元中。
实现计算一个角度的余弦值的程序片段如下:
cosx:
.def d_xc,d_cosx
d_coef_c .usect "coef_c",4
.data
table_c .word 0249H ;C1=1/(7*8)
.word 0444H ;C2=1/(5*6)
.word 0AABH ;C3=1/(3*4)
.word 4000H ;C4=1/2
d_xc .usect "cos_vars",1
d_squr_xc .usect "cos_vars",1
d_temp_c .usect "cos_vars",1
d_cosx .usect "cos_vars",1
c_l_c .usect "cos_vars",1
.text
SSBX FRCT
STM #d_coef_c,AR5 ;move coeffs table_c
RPT #3
MVPD #table_c,*AR5+
STM #d_coef_c,AR3
STM #d_xc,AR2
STM #c_l_c,AR4
ST #7FFFH,c_l_c
SQUR *AR2+,A ;A=x^2
ST A,*AR2 ;(AR2)=x^2
||LD *AR4,B ;B=1
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 ;-1/2
NEG A
MPYA *AR2+ ;B=-x^2/2(1-x^2/12(1-x^2/30(1-x^2/56)))
MAR *AR2+
RETD
ADD *AR4,16,B ;B=-x^2/2(1-x^2/12(1-x^2/30(1-x^2/56)))
STH B,*AR2 ;cos(theta)
RET
3、正弦波的实现
利用计算一个角度的正弦值和余弦值程序可实现正弦波。其实现步骤如下: ,,第一步:利用sin_start和cos_start子程序,计算(间隔0~45
,为)的正弦和余弦值; 0.5
,,第二步:利用sin(2x)=2sin(x)cos(x)公式,计算的正弦0~90
,值(间隔为); 1
,,第三步:通过复制,获得的正弦值; 0~359
,,第四步:将的正弦值重复从PA口输出,便可得到正弦波。 0~359
产生正弦波的程序片段如下:
.mmregs
.def start
.def d_xs,d_sinx,d_xc,d_cosx,sinx,cosx
sin_x: .usect "sin_x",360 STACK: .usect "STACK",10H k_theta .set 286 ;theta=pi/360(0.5deg)
start:
.text
STM #STACK+10H,SP
STM k_theta,AR0
STM 0,AR1
STM #sin_x,AR6
STM #90,BRC
RPTB loop1-1
LDM AR1,A
LD #d_xs,DP
STL A,@d_xs
STL A,@d_xc
CALL sinx ;d_sinx=sin(x)
CALL cosx ;d_cosx=cos(x)
LD #d_sinx,DP
LD @d_sinx,16,A ;A=sin(x)
MPYA @d_cosx ;B=sin(x)*cos(x)
2*sin(x) STH B,1,*AR6+ ;AR6----
MAR *AR1+0
loop1: STM #sin_x+89, AR7 ;sin91(deg.)-sin179(deg.) STM #88,BRC
RPTB loop2-1
LD *AR7-,A
STL A,*AR6+
loop2: STM #179,BRC ;sin180(deg.)-sin359(deg.)
STM #sin_x,AR7
RPTB loop3-1
LD *AR7+,A
NEG A
STL A,*AR6+
loop3: STM #sin_x,AR6 ;generate sin wave STM #1,AR0
STM #360,BK
B loop3
产生正弦波链接命令文件的程序片段如下: 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
.data :> EPROM PAGE 0
STACK :> SPRAM PAGE 1
sin_vars :> DARAM1 PAGE 1
coef_s :> DARAM1 PAGE 1
cos_vars :> DARAM2 PAGE 1
coef_c :> DARAM2 PAGE 1
sin_x : align(512) {} > DARAM3 PAGE 1
.vectors :>VECS PAGE 0 }
五、设计内容
本实验需要使用C54X汇编语言产生正弦波,并通过 CCS的图形显示工具观察波形。实验分以下几步完成:
启动 CCS,操作如下:
1、建立新的工程文件:点击Project?New,保存文件名为sin.pjt。
Source File菜单命令,2、建立汇编源程序:点击File?New?
打开一个空白文档,将汇编源程序逐条输入后,单击Flie?Save菜单命令,文件类型保存为(*.asm),单击“保存”按钮,以上汇编程序被存盘。
3、建立连接命令文件:点击File?New?Source File菜单命令,打开一个空白文档,将链接命令文件逐条输入后,单击Flie?Save菜单命令,文件类型保存为(*.cmd),单击“保存”按钮,以上链接命令文件被存盘。
4、选择 Project 菜单中的Add File to Project 选项,将汇编源程序
sin.asm和链接定位sin.cmd文件依次添加到工程文件中。 5、选择 Project 菜单中的 Options 选项,并选择 build options
项来修改或添加编译、连接中使用的参数。选择Linker 窗口,在“Output Filename”栏中写入输出 OUT 文件的名字,如 sin.out,还可以设置生成的 map 文件名。
6、完成汇编,编译和链接,正确产生.out文件:点击Project
菜单中的Rebuild all,请注意在监视窗口显示的汇编,编译和链接的相关信息。如果没有错误,将产生sin.out文件;如果有错,在监视窗口以红色字体显示出错误行,用鼠标双击该行,光标跳将至源程序相应的出错行。修改错误后,重新汇编链接。 7、在 Project 选项中打开sin.pjt 文件,使用 Build 选项完成编译、连接。
8、使用 File 菜单中的 Load Program 将 OUT 文件装入。然后选择
Debug?Run,程序执行过程中可以使用 Debug ?Halt 暂停程序的执行。
9、选择 View -> Graph -> Time/Frequency菜单打开一个图形显示窗口。将“Start Address”项改为地址sin_x,将“Acquisition
Buffer Size”项设置为360,将“Display Data Size”项设置为360,将“DSP Data Type”改为“16-bit signed integer” 。
即将Graph Property Dialog对话框改为见下图:
这样,将在图形显示窗口中显示从sin_x(首地址)开始的360个点的 16 位有符号整数的图形。
六、总体方案设计
我们知道一个角度为x的正弦和余弦函数,都可以展开为泰勒级数,且其前五项可以近似看为:
3579xxxxx,x,,,,,sin()...3!5!7!9!
2222xxxx(1(1(1(1)))),x,,,,,,,,23456789
2468xxxx cos(x),1,,,,,... 2!4!6!8!
2222xxxx,,,,, 1(1(1(1))) ,,,2345678
这个程序的编程思想是这样的,正弦波的波形可以看为由无数点组成,这些点与x轴的每一个角度值相对应,那么我们可以利用 DSP处理器处理大量重复计算的优势来计算,x轴每一点对应的y 轴的值(在x轴取360个点来进行逼近),由于程序的编制采用小数形式,其弧度大于1的正弦值得不到,这就对正弦波的产生造成了障碍。可由于正弦波的特殊的对称形式给程序的编制找到了
,,的弧度为0.7854<1,即之间的任意正弦、余出口。0~sin()44
弦值可以利用汇编程序得到N又可以利用公式:sin2,,2sin,cos,
,,,得到之间的正弦值。而之间的正弦曲线与之间0~0~~,222
,,的正弦曲线通过这条轴左右对称,那么就可以得到的x,~,22正弦值,而的正弦曲线的相反数通过x,,这条轴与左0~,,~2,右对称。这样的正弦值也得到了。一个周期内完整的正弦,~2,
波就得到了。正弦波产生的流程图如下:
得到正弦值得到余弦值
Sin2a=2sinacosa
,的值得到0~2
,得到的值 ~,2
得到的值 ,~2,
得到的值 0~2,
循环输出数据
正弦波产生流程图
七、源程序
1、产生正弦波源程序sin.asm如下:
.mmregs
.def start
.def d_xs,d_sinx,d_xc,d_cosx,sinx,cosx
sin_x: .usect "sin_x",360 STACK: .usect "STACK",10H k_theta .set 286 ;theta=pi/360(0.5deg)
start:
.text
STM #STACK+10H,SP
STM k_theta,AR0
STM 0,AR1
STM #sin_x,AR6
STM #90,BRC
RPTB loop1-1
LDM AR1,A
LD #d_xs,DP
STL A,@d_xs
STL A,@d_xc
CALL sinx ;d_sinx=sin(x)
CALL cosx ;d_cosx=cos(x)
LD #d_sinx,DP
LD @d_sinx,16,A ;A=sin(x)
MPYA @d_cosx ;B=sin(x)*cos(x)
STH B,1,*AR6+ ;AR6----2*sin(x)
MAR *AR1+0
loop1: STM #sin_x+89, AR7 ;sin91(deg.)-sin179(deg.) STM #88,BRC
RPTB loop2-1
LD *AR7-,A
STL A,*AR6+
loop2: STM #179,BRC ;sin180(deg.)-sin359(deg.)
STM #sin_x,AR7
RPTB loop3-1
LD *AR7+,A
NEG A
STL A,*AR6+
loop3: STM #sin_x,AR6 ;generate sin wave
STM #1,AR0
STM #360,BK
B loop3
sinx:
.def d_xs,d_sinx
.data
table_s .word 01C7H ;C1=1/(8*9)
.word 030BH ;C2=1/(6*7)
.word 0666H ;C3=1/(4*5)
.word 1556H ;C4=1/(2*3) d_coef_s .usect "coef_s",4
d_xs .usect "sin_vars",1
d_squr_xs .usect "sin_vars",1
d_temp_s .usect "sin_vars",1
d_sinx .usect "sin_vars",1
d_l_s .usect "sin_vars",1
.text
SSBX FRCT
STM #d_coef_s,AR5 ;move coeffs table_s
RPT #3
MVPD #table_s,*AR5+
STM #d_coef_s,AR3
STM #d_xs,AR2
STM #d_l_s,AR4
ST #7FFFH,d_l_s
SQUR *AR2+,A ;A=x^2
ST A,*AR2 ;(AR2)=x^2
||LD *AR4,B ;B=1
MASR *AR2+,*AR3+,B,A ;A=1-x^2/72,T=x^2
MPYA A ;A=T*A=x^2(1-x^2/72)
STH A,*AR2 ;(d_temp)=x^2(1-x^2/72)
MASR *AR2-,*AR3+,B,A ;A=1-x^2/42(1-x^2/72);T=x^2(1-x^2/72)
MPYA *AR2+ ;B=x^2(1-x^2/42(1-x^2/72))
ST B,*AR2 ;(d_temp)=x^2(1-x^2/42(1-x^2/72))
||LD *AR4,B ;B=1
MASR *AR2-,*AR3+,B,A ;A=1-x^2/20(1-x^2/42(1-x^2/72))
MPYA *AR2+ ;B=x^2(1-x^2/20(1-x^2/42(1-x^2/72)))
ST B,*AR2 ;(d_temp)=B
||LD *AR4,B ;B=1
MASR *AR2-,*AR3,B,A ;A=1-x^2/6(1-x^2/20(1-x^2/42(1-x^2/72))) MPYA d_xs ;B=x(1-x^2/6(1-x^2/20(1-x^2/42(1-x^2/72))))
STH B,d_sinx ;sin(theta)
RET
cosx:
.def d_xc,d_cosx
d_coef_c .usect "coef_c",4
.data
table_c .word 0249H ;C1=1/(7*8)
.word 0444H ;C2=1/(5*6)
.word 0AABH ;C3=1/(3*4)
.word 4000H ;C4=1/2
d_xc .usect "cos_vars",1
d_squr_xc .usect "cos_vars",1
d_temp_c .usect "cos_vars",1
d_cosx .usect "cos_vars",1
c_l_c .usect "cos_vars",1
.text
SSBX FRCT
STM #d_coef_c,AR5 ;move coeffs table_c
RPT #3
MVPD #table_c,*AR5+
STM #d_coef_c,AR3
STM #d_xc,AR2
STM #c_l_c,AR4
ST #7FFFH,c_l_c
SQUR *AR2+,A ;A=x^2
ST A,*AR2 ;(AR2)=x^2
||LD *AR4,B ;B=1
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 ;-1/2
NEG A
MPYA *AR2+ ;B=-x^2/2(1-x^2/12(1-x^2/30(1-x^2/56)))
MAR *AR2+
RETD
ADD *AR4,16,B ;B=-x^2/2(1-x^2/12(1-x^2/30(1-x^2/56))) STH B,*AR2 ;cos(theta)
RET
.end
2、产生正弦波链接命令文件sin.cmd如下:
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
.data :> EPROM PAGE 0
STACK :> SPRAM PAGE 1
sin_vars :> DARAM1 PAGE 1
coef_s :> DARAM1 PAGE 1
cos_vars :> DARAM2 PAGE 1
coef_c :> DARAM2 PAGE 1
sin_x : align(512) {} > DARAM3 PAGE 1
.vectors :>VECS PAGE 0
}
八、实验结果及分析
实验结果见下图:
结果分析:通过不断的发现错误、改正错误和调试,最终得到了所希望的图象,即正弦波信号。
九、设计总结
每一次的付出,都会有收获。这次的课程设计持续了不到一周的时间,每天都在不断的调试,不断的出现问题,不断的解决问题。这次课程设计也增强了我的独立思考的能力,但是毕竟单枪匹马是势单力薄的,我不断的询问同学,同时也利用有限的资源来查找资料,以增加自己对用DSP的汇编语言编写程序来产生正弦波信号的认识。功夫不负苦心人,经历了一段时间后,我可以成功地得到正弦波信号。这次的课程设计使我对DSP的功能的认识有了进一步加深,并且掌握了用汇编语言编写输出正弦波信号的程序,学会了利用CCSTMS320C54x对基本的文
件的汇编、编译、链接和调试,还使我认识到细节决定成败,基础知识的重要性,以后我会把这次课程设计得到的经验和教训应用到实际生活中去,尽量避免同一个错误的再一次上演。
十、参考文献
1、邹彦《DSP原理及应用》电子工业出版社
2、C54x CCS.pdf