54DSP十天速成Word格式.docx
《54DSP十天速成Word格式.docx》由会员分享,可在线阅读,更多相关《54DSP十天速成Word格式.docx(29页珍藏版)》请在冰点文库上搜索。
*用两级减一计数器来延时。
调整AR1和AR2的大小LED闪烁的频率不同
Delay:
STM
#999,AR1
循环次数1000
LOOP1:
#4999,
AR2
循环次数5000
LOOP2:
BANZ
LOOP2,*AR2-
如果AR2不等于0,AR2减1,再判断
LOOP1,*AR1-
如果AR1不等于0,AR1减1,跳转到LOOP1
RET
.end
*注意这种延时方法并不精确,需要精确定时必须用定时器。
*按此法延时的近似公式为:
4*(AR2+1)*(AR1+1)*时钟周期
*当DSP工作在50MHz(时钟周期20ns),AR1=999,
AR2=4999时
*延时约为400ms,则LED闪烁的周期为800ms,频率1.25Hz
设计指导:
1.源代码书写格式
源代码的书写有一定的格式,初学者往往容易忽视。
简单归纳如下:
1.每一行代码分为三个区:
标号区、指令区和注释区。
标号区必须顶格写,主要是定义变量、常量、程序标签时的名称。
指令区位于标号区之后,以空格或TAB格开。
如果没有标号,也必须在指令前面加上空格或TAB,不能顶格。
注释区在标号区、程序区之后,以分号开始。
注释区前面可以没有标号区或程序区。
另外还有专门的注释行,以*打头,必须顶格开始。
2.一般区分大小写,除非加编译参数忽略大小写。
3.标点符号有时不注意会打成中文全角字符导致错误。
书写格式的要求在很多DSP书里都没有提,初学者往往只把书上的代码输入进去,编译时得到错误的提示,而不知所措。
其中最容易犯的错误指令顶格写,不过一般经提示后不会犯第二次。
有些格式CCS并没有做要求,但注意养成良好的代码书写风格,增加代码的可读性。
以上两个例子的书写风格可作参考,但不是硬性规定:
1.标号区占3个TAB的间隔,即12个字符
2.指令中的指令码占两个TAB间隔,然后是操作数。
3.每一行的尾注能对齐的尽量对齐
4.标明一段程序功能的注释以*号打头顶格写,如果功能说明的注释较多,用分格线框起来。
此外其它编程语言的编程风格也可以借用过来,比如标示符命名规则、程序说明的要求等。
如果项目组有规定,则按规定执行。
本书的代码尽量保持一定的风格,不过读者可以发现前面的代码注释较多,后面随着学习的深入,一般不会对每一条指令加注释,只注明程序段的功能。
另外代码贴到word里后,格式有些错位,无法一一纠正。
2.链接配置文件
一个完整的DSP程序至少包含三个部分:
程序代码、中断向量表、链接配置文件(*.cmd)。
这里介绍一下链接配置文件文件,对本次试验影响不大的中断向量表将在后文介绍。
连接配置文件的确定了程序链接成最终可执行代码时的选项,其中有很多条目,实现不同方面的选项,其中最常用的也是必须的有两条:
1.存贮器的分配
2.标明程序入口。
以本次实验为例,下面的简单的链接配置文件就够用了:
/*
TestXF.cmd
*/
-e
/*程序入口,必须在程序中定义相应的标号*/
MEMORY
{
page
0:
PRAM:
org=0100h
len=0F00h
/*定义程序存贮区,起始0100H,长度0F00H*/
}
SECTIONS{
.text:
>
PRAM
0
/*将.text段映射到page0的param区*/
由于每个程序都需要一个链接配置文件,可以编写一个满足通常需要的链接配置文件。
作为本手册通用的链接配置文件如下,可以满足本书大部分程序的需要。
在未特别指明的情况下使用这个通用的链接配置文件:
5402.cmd
-m
map.map
/*生成存储器映射报告文件
PAGE
VECT:
org=0080h
len=0080h
/*中断向量表*/
PARAM:
org=100h
/*代码区*/
1:
DARAM:
org=1000h
len=1000h
/*数据区*/
SECTIONS
:
PARAM
/*代码段*/
.vectors
VECT
STACK
DARAM
1
/*堆栈*/
.bss
/*未命名段*/
.data
/*数据段*/
更多参考:
1.关于代码书写格式:
SPRU102:
TMS320C54x
Assembly
Language
Tools
User'
s
Guide,3.5
Source
Statement
Format
2.关于链接配置文件:
Guide,7.5
Linker
Command
Files,7.7
The
Directive,7.8
Directive
练习:
1、试一下不按规定格式书写代码会产生什么样的编译错误。
2、试一下将链接配置文件中的MEMORY,SECTIONS改成小写会出现什么样的编译错误。
3.修改程序1.2中AR1,AR2的值,观察LED闪烁频率
实验二
基本运算
<本节选自为HK-DSP实验箱写的实验指导书,有待整理>
DSP指令数量最多的是:
算术指令、逻辑指令和数据加载与传送指令。
数据加载与传送指令由于处处要用,所以不单独列为实验。
算术与逻辑指令也是数量繁多,无法一一举例,这里简单举一个加法和除法的例子,乘法和乘加指令在FIR用得比较多,稍后一并介绍。
其它指令有兴趣可以对照指令表的说明,试验一下各指令运行的结果。
实验2.1
加减法计算
************************************************
*计算z=x+y-w。
.mmregs
CodeStart
Data_DP:
数据段指针
x:
.word
10
初始化变量
y:
26
w:
23
z:
0
.text
LD
#Data_DP,DP
装载数据指针DP
#STACK+10H,SP
SUMB:
x,A
A=x
ADD
y,A
A=A+y
SUB
w,A
A=A-w
STL
A,z
z=A
END:
END
计算结果数据存储器地址存储内容十进制
x1010H000aH10
y1011H001aH26
w1012H0017H23
z1013H000dH13
技巧提示:
试验算术指令由于不需要外部资源,可以不需要仿真器和实验箱。
同学们可以平时自己用软件仿真,多多实验。
但是复杂的算法最好还是在线仿真,因为程序是流水线执行,软件仿真有时与实际硬件执行结果有所不同。
实验2.2
除法计算
DSP并没有除法指令,回想一下我们用在稿纸上演算除法列的竖式,实际是一种移位减法,DSP中也是通过做多次减法的办法来做除法。
下面例子是把用除以10的办法二进制数转成BCD码例子:
*********************************
*16进制转BCD码
.global
.data
1234
待转换的数字
除数
0Fh,0Fh,0Fh,0Fh,0Fh;
结果区,每位BCD存一个字,
初始化为F因为实验板的数码管不显示F
#x,DP
设置DP
被除数
#z,AR1
结果区指针
loop:
#15
执行完16次减法后,A的高16位是余数
SUBC
低16位是商
STH
A,*AR1+
余数保存到Z
AND
#0FFFFH,A
掩盖掉高16位,保留商值
BC
loop,ANEQ
继续做除法直到商为0
end:
end
练习其他算术指令
其它参考:
spru172c:
DSP
Reference
Set
Volume
2:
Mnemonic
Instruction
Set,2.1
Arithmetic
Operations
这个资料对每个指令都有详细说明。
也可以在Help中的TMS320C54x
Set中查询或搜索相关指令。
实验三
中断
中断的概念应该不陌生,指的是当某个事件发生时,暂停当前的操作,转向中断服务程序,执行完后再返回继续原来的操作。
这使得DSP能够处理多个任务。
DSP有许多中断源,可以设置中断控制寄存器来确定响应哪些中断而不理会哪些中断。
本实验介绍最常用的定时器中断和外部中断的使用方法,并介绍中断向量表和中断向量指针。
实验3.1
定时器中断:
方波发生器
学习定时器中断的设计方法
回顾一下实验一控制LED的闪烁实际就是一个简单的方波发生器。
但不足的是延时的方法定时不精确,另外还有一个缺点是在执行延时的过程中DSP就无法执行其它指令,这时就可以用定时器来改进。
使用定时器首先要对它初始化,基本步骤如下:
1.关掉中断
2.停止定时器运行。
3.设定时器的定时长度
4.允许定时器中断
5.运行定时器
6.打开中断
现以简单的方波程序为例:
==============================================
fangbo1.asm
利用定时器Timer0在XF脚产生周期2ms的的方波
.title
"
fangbo1.asm"
codestart
TINT0_ISR
Timer0中断服务程序
.usect
STACK"
10H
分配堆栈空间
设定定时器0控制寄存器的内容
K_TCR_SOFT
.set
0B<
<
11
TCR第11位soft=0
K_TCR_FREE
TCR第10位free=0
K_TCR_PSC
6
TCR第9-6位,可设TDDR一样,也可不设自动加载
K_TCR_TRB
1B<
5
TCR第5位TRB=1此位置1,PSC会自动加载的
K_TCR_TSS
4
TCR第4位TSS=0
K_TCR_TDDR
1001B<
TCR第3-0位TDDR=1001B
K_TCR
K_TCR_SOFT|K_TCR_FREE|K_TCR_PSC|K_TCR_TRB|K_TCR_TSS|K_TCR_TDDR
K_TCR_STOP
TSS=1时计数器停止
DATA_DP:
数据区指针
XF_Flag:
当前XF的电平标志,如果XF_Flag=1,则XF=1
================================================
主程序:
#STACK+10H,SP
设堆栈指针SP
#DATA_DP,DP
设数据地址DP
#XF_Flag,AR2
AR指向XF标志
改变中断向量表位置
K_IPTR
0080h
指向0080H,默认是FF80
LDM
PMST,A
#7FH,A
保留低7位,清掉高位
OR
#K_IPTR,A
STLM
A,PMST
*初始化定时器0
*f=50MHz,定时2ms时:
*根据定时器长度计算公式:
Tt=T*(1+TDDR)*(1+PRD)
*给定TDDR=9,PRD=9999,CLKOUT主频f=40MHz,T=25ns
*Tt=20ns*(1+9)*(1+9999)=2000us=2ms
*f=100Mhz,定时最大是:
10ns*2^4*2^16=10ms,
PERIOD
9999
定义计数周期
K_TCR_STOP,TCR
停止计数器0
#PERIOD,TIM
可设成跟PRD一样,也可不设自动加载
#PERIOD,PRD
设定计数周期
#K_TCR,TCR
开始Timer0
stm
#0008h,IMR
允许Timer0中断
#0008h,IFR
清除挂起的中断
rsbx
intm
开中断
nop
end
Timer0中断服务程序:
TIN0_ISR
TINT0_ISR:
PSHM
ST0
本中断程序影响TC,位于ST0中
判断当前XF状态并作电平变化
BITF
*AR2,#1
IF
XF_Flag=1
then
TC=1
else
TC=0
ResetXF,TC
XF=0
XF=1
setXF:
置XF为高电平
ST
#1,*AR2
相应修改标志
Next
ResetXF:
#0,*AR2
Next:
POPM
ST0
RETE
有时定时的长度不能满足需要,比如DSP工作频率50Mhz时,定时最大值是:
20ns*2^4*2^16=20ms。
如果需要更长的定时,就要在定时器中断子程序中再加一个计数器,直到产生一定次数的定时中断后再执行相应的操作。
程序只需要稍作修改,见附盘的fangbo2.asm
寄存器的不同位通常有不同的含义,初始化时单独设定寄存器的每一位可以增加程序可读性,容易让其它人看懂具体每一位设置的含义,并且易于修改。
如果代码太长可以自己写一个初始化的子程序,需要时修改一下调定时再调用。
当然如果对寄存器各个位的含义相当熟悉,直接整个初始化也行。
可以自行选择这些不同的编程风格。
1.中断向量表
中断向量表是DSP程序的重要组成部分,当有中断发生并且处于允许状态时,程序指针跳转到中断向量表中对应的中断地址。
由于中断服务程序一般较长,通常中断向量表存放的是一个跳转指令,指向实际的中断服务程序。
下面是5402中断向量表的一个范例,可以作为模板,使用时稍作修改就行:
*****************************************************************
*5402Vectors.asm
*完整的5402中断向量表示例
*5402共有30个中断向量,每个向量占4个字的空间。
*使用向量一般用一条跳转指令转到相应中断服务子程序,其余空位用NOP填充
*未使用的向量直接用RETE返回,是为了防止意外进入未用中断。
.sect
.vectors"
开始命名段.vecotrs
引用程序入口的全局符号定义
。
引用其它中断程序入口的全局符号定义
.align
0x80
中断向量表必须对齐128字的页边界
RESET:
Reset中断向量,跳转到程序入口
用NOP填充表中其余空字
B指令占了两个字,所以要填两个NOP
NMI:
不可屏蔽中断
软件中断
SINT17
.space
4*16
软件中断使用较少,简单起见用0填充
SINT18
4*16
SINT19
SINT20
SINT21
SINT22
SINT23
SINT24
SINT25
SINT26
SINT27
SINT28
SINT29
SINT30
INT0:
外部中断INT0
INT1:
外部中断INT1
INT2:
外部中断INT2
TINT:
Timer0中断
BRINT0:
McBSP
#0
接收中断
BXINT0:
发送中断
DMAC0:
无定义(默认)DMA0中断
TINT1:
Timer1中断(默认)或DMA1中断.
INT3:
外部中断3
HPINT:
HPI中断
BRINT1:
#1接收中断(默认)或DMA2中断
BXINT1:
#1发送中断(默认)或DMA3中断
DMAC4:
DMA4中断
DMAC5:
DMA5中断
在本实验中只要把在开头加上中断子程序标号的引用,并在中断表的TINT部分换成跳转指令就行了:
*******************************************************
*vectors.asm
for
引用Timer0中断子程序
<节省篇幅,中间省略>
receive
interrupt
节省篇幅,下略>
只有第一个中断(Reset中断)是每个程序都应该有的,在不需要其它中断的情况下,可以只用这一部分,后面可以省略。
如果只需要部分中断也可以按需设置,但必须保证所用中断在中断向量表的位置不变。
不熟悉中断向量表的情况下最好还是用这个完整中断向量表样例。
另外C5400系列中不同型号DSP的中断向量数量和在中断向量表中的位置有所不同,程序移植时需要查相应datasheet确认。
2.中断向量指针
中断向量表的位置并没有强制的位置,可以在内部存贮器,也可以在外部存贮器。
但有一个要求:
中断量表必须放在80H字长存贮块的起始处,即中断向量表的首地址的低7位必须全为0。
的寄存器PMST的高9位是中断向量表的指针IPTR。
其上电时默认是在FF80H处,这是为了运行固化在内部ROM的上电加载程序(见实验八的程序加载