版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第7章C语言编程与混合编程7.1
C语言编程7.2
C程序编译7.3
C语言与汇编语言混合编程
7.1
C语言编程
7.1.1
C54x支持的基本数据类型
C54xDSP的基本数据类型如表7.1所示,字长为16位或32位。7.1.2常量与变量
常量名和变量名都以字母或下划线开头,最多可以有100个字符,不能使用C语言的关键字来命名常量名和变量名。常量在编译后直接嵌入代码中。变量名经C编译器编译后,代表一个变量的内存地址,并自动在变量名前加下划线(_),
如变量“a”经编译后,在内存单元显示为“_a”。这样的好处就是C语言定义的变量和汇编文件定义的变量可以重名且不会混淆,还有一个好处就是汇编文件可以调用C
语言定义的变量和函数(C语言定义的函数名在编译后也在函数名前加“_”),以实现混合编程。
符号的常量名通常用大写字母表示,变量名用小写字母表示,以示区别。变量名常采用著名的匈牙利命名规则,当然,变量较少时,也可以简单地命名变量。7.1.3运算符与表达式
将常量或变量用运算符连在一起就构成了表达式,再在句末加上分号(;)即成为语句。
(1)赋值运算符:=。对DSP寄存器进行赋值时,先将寄存器定义为指针,然后与C语言变量赋值类似地进行赋值。如中断屏蔽寄存器(IMR)的地址为0地址,其定义和赋值如下:
#define IMR *(int*)0x0
IMR=0;对外部端口进行赋值时,先用关键字ioport和端口地址定义端口名,然后也是与C语言变量赋值类似地进行赋
值,其定义和赋值如下:
ioportunsignedintport8000;//定义一个外部端口,地址为0x8000
port8000=0;
(2)算术运算符:+(加)、-(减)、*(乘)、/(除)、%(取模)。在C54xDSP中,取模运算按分子的符号确定取值的符号,如10%-3=1;-10%3=-1等。类似地,C54xDSP也支持组合运算符,如+=、-=、*=、/=、%=及++、--等。
在表达式中,只能使用小括号改变运算的优先顺序。
(3)关系运算符:==(等于)、![KG-*2]=(不等于)、>(大于)、>=(大于等于)、<(小于)、<=(小于等于)。
作为关系运算表达式的输入,0为假,非0为真;作为运算结果,0表示假,1表示真。
(4)位运算符:&(按位与)、|(按位或)、∧(按位异或)、~(取反)、<<(左移)、>>(右移)。
(5)逻辑运算符:&&(逻辑与)、‖(逻辑或)、!(逻辑非)。
(6)三元运算符:“?:”,它有三个参加运算的元素,而且有返回值,其使用格式为
(express)?(val1):(val2);[HT5]
如果express的值为真,则返回表达式val1的值,否则返回val2的值。这条语句也可用if语句代替,可不必记忆。
运算符的优先级自高到低为逻辑非、算术运算符、关系运算符、逻辑运算符&&或‖、赋值运算符。7.1.4函数及调用规则
一个C语言编写的函数就是一个功能模块,多个函数可以组成更大的功能模块。main函数包括除中断函数外的其他全部函数的功能,DSP程序总从main函数开始执行。为了能正确执行main函数,需要一个C语言运行环境。通过适当设置TMS320C54xC/C++编译器,DSP项目中会自动添加相应的C语言初始化代码,以适合main函数的执行。
1.全局变量和局部变量
在主函数体中定义的变量或主函数体外的变量为全局变量,在编译时有固定的存储地址;而在其他函数体中定义的变量称为局部变量,存储单元是在堆栈中分配局部变量的,称为局部帧。一旦函数执行完毕,局部帧必须被收回,局部变量就消失了,所以局部变量的作用域仅限于函数体内部。
2.参数传递
如果函数存在参数传递,则调用者将第一个参数(最左边)载入累加器A,而将剩下的参数以逆序压入堆栈,最右边的先压栈,最左边的参数最后一个压栈,即在最低的地址。
这些压入堆栈的参数称为局部帧,参数传递就是将实参的值复制到形参的值的过程。若参数为实浮点数或长整型数,则是低字先入栈,高字后入栈。若参数中有结构形式,则调用函数会给结构分配空间,其地址通过累加器A传递给被调用函数。一旦函数执行完毕,局部帧被收回,形参则消失。
3.函数返回
若函数返回一个值,则被调用函数将返回值载入累加器A中,再从A复制到实参中;如果是返回一个结构体,则将结构体的内容复制到累加器A所指向的存储空间;如果没有返回值,则A被置0,然后撤销局部帧和恢复函数中所有保护的寄
存器。
4.main函数
main函数主要由程序初始化代码、硬件初始化代码以及定时扫描代码等组成。main函数往往是死循环函数,定义死循环的语句有for(;;)或while(1)等。
5.中断函数
中断函数利用关键字interrupt来定义。如定义一个名称为time的中断函数如下:
interruptvoidtime();
{
…
}
用C语言编写的中断函数,其执行效率不高。因为当系统调用中断函数时,会将所有CPU寄存器的内容压栈保护,中断返回时,系统又会将这些CPU寄存器的内容出栈恢复。7.1.5
C语言库函数
在C5000DSP的C语言编程中,有很多现成的库函数可以调用。假设CCS默认安装在c:\ti目录下,则c:\ti\c5400\cgtools\include和c:\ti\c5500\cgtools\include两个目录下的文件即为C/C++库函数文件。这里对C库文件进行介绍,C++库文件从略。在c:\ti\c5400\cgtools\include目录下的C语言头文件(.h)有19个,它们分别是access.h、assert.h、ctype.h、errno.h、file.h、float.h、intrindefs.h、iso646.h、limits.h、
linkage.h、math.h、setjmp.h、stdarg.h、stddef.h、stdio.h、stdlib.h、string.h、time.h、unaccess.h。
头文件中的函数实现存储在c:\ti\c5400\cgtools\lib\rts.src文件中,打开文件即可以看到具体的实现代码。
(1)math.h:浮点数学函数。它包含下列函数:
sin(正弦)、cos(余弦)、tan(正切)、asin(反正弦)、acos(反余弦)、atan(反正切)、atan2(两数商的反正切)、sinh(双曲正弦)、cosh(双曲余弦)、tanh(双曲正切)、ceil(向上取整)、floor(向下取整)、fmod(两数商的浮点型余数)、fabs(绝对值)、exp(以e为底的指数)、frexp(返回一个数的尾数和以2为底的指数)、ldexp(已知尾数和以2为底的指数,求幂)、log(自然对数)、log10(以10为底的对数)、modf(分解成有符号整数部分和有符号小数部分)、pow(计算x的y次方)、sqrt(开平方)。
(2)stdlib.h:通用函数。它包含下列函数:
abort(非正常程序中止)、abs(求整数绝对值)、labs(长整数绝对值)、atof(字符串转换为浮点数)、atoi(字符串转换为整数型)、atol(字符串转换为长整型)、div(整型除法)、ldiv(长整型除法)、ltoa(长整数转换为字符串)、rand(产生伪随机整数)、srand(复位随机数产生器)、strtod(字符串转换为浮点值)、strtol(字符串转换为长整型值)、strtoul(字符串转换为无符号长整型值)。
(3)ctype.h:字符转换。它包含下列函数:
isalnum(是否是字母或数字)、isalpha(是否是字母)、iscntrl(是否是控制字符)、isdigit(是否是数字)、isgraph(是否是除空格外的可打印字符)、islower(是否是小写字母)、
isprint[JP](是否是可打印字符(包括空格))、ispunct(是否是标点符号)、isspace(是否是空格、制表符、回车符、换页符或换行符)、isupper(是否是大写字母)、isxdigit(是否是十六进制数)、isascii(是否是ASCII码字符)、toupper(转换成大写字母)、tolower(转换成小写字母)、toascii(转换成一个合法的ASCII码值)。
(4)其他头文件。它包括下列函数:
assert.h(诊断信息)、errno.h(出错报告)、file.h(低级I/O函数)、float.h、limits.h(取值范围限制)、setjmp.h(非局部跳转)、stdarg.h(可变参数)、stddef.h(标准定义)、stdio.h(输入/输出函数)、string.h(字符串函数)、time.h(时间函数)。7.1.6
DSPLIB汇编库函数
CCS开发环境还为C5400和C5500提供了通用数字信号处理算法库(DSPLIB库)。这些库函数用汇编语言编写,编译效率高,多数为16位数据格式,执行速度快,采用C函数格式直接调用或略加修改后调用,可大大加快项目的开发速度。如果采用默认安装的CCS软件,则DSPLIB库在c:\ti\c5400\dsplib目录下。在此目录下的\include\dsplib.h头文件中列出了DSPLIB库函数的原型,其源程序在c:\ti\c5400\dsplib\54xdsp.src文件或54x_src文件夹中,主要有以下相关函数。
(1)实数或复数FFT算法函数。
cfft8~cfft1024:16位数据的复数FFT算法,点数在8~1024点之间,取2的整数次幂。
rfft8~rfft1024:16位数据的实数FFT算法,点数同上。
cfft8~cfft1024:16位数据的复数IFFT算法,点数同上。
rfft8~rfft1024:16位数据的实数IFFT算法,点数同上。
cfft32_8~cfft32_1024:32位数据的复数FFT算法,点数
同上。
cifft32_8~cifft32_1024:32位数据的复数IFFT算法,
点数同上。
unpacki_16~unpacki_1024:IFFT算法解包装(unpack)
算法,也就是将一个N/2点的复数IFFT变成N点的实数IFFT算法,点数在16~1024点之间,取2的整数次幂。
cbrev、cbrev32:16位、32位的复数倒位序程序。
(2)数字滤波和卷积函数。
convol:计算2个实序列的卷积。
fir:fir滤波函数。
firs:系数对称的fir滤波函数。
cfir:复数fir滤波函数。
iircas4:使用直接II型结构计算二阶IIR级联滤波,其算法如下:
d(n)=x(n)-a1d(n-1)-a2d(n-2)
(7.1)
y(n)=d(n)+b1d(n-1)-b2d(n-2)(7.2)
iircas5:使用直接II型结构计算二阶IIR级联滤波,其算法如下:
d(n)=x(n)-a1d(n-1)-a2d(n-2)(7.3)
y(n)=b0d(n)+b1d(n-1)-b2d(n-2)(7.4)
iir32:32位数据的二阶IIR级联滤波。
firdec:带抽取的fir滤波,允许分段连续滤波。
firinterp:带内插的fir滤波,允许分段连续滤波。
(3)自适应滤波函数。
dlms:带延迟的自适应LMSfir滤波算法。
(4)相关函数。
acorr_raw、acorr_bias、acorr_unbias:
计算自相关及有偏、无偏处理,仅输出自相关序列的半边,而corr函数输出自相关的全部序列值。
(5)数学函数。
add:向量加法。
sub:向量减法。
neg、neg32:16位、32位数据向量取相反数。
ldiv16:Q31除以Q15的长除法。
recip16:Q15格式浮点数倒数运算。
expn:利用泰勒级数计算一个向量以e为底的指数值。
logn:利用泰勒级数计算一个向量的自然对数值。
log_2、log_10:利用泰勒级数计算一个向量以2为底、以10为底的对数值。
sqrt_16:开平方。
maxidx、minidx:返回一个向量最大值、最小值的索引。maxval、minval:计算一个向量的最大值、最小值。
rand16:向量随机数产生器。
rand16init:初始化向量随机数产生器。
mul32:Q31数与Q31数向量乘法,结果为Q31数据。
pow:求平方。
(6)三角函数。
sine:使用泰勒级数计算一个向量的正弦。
(7)矩阵运算函数。
mmul:矩阵乘法。
mtrans:矩阵转置。
(8)其他杂函数,如数据格式转换等。
fltoq15:浮点数转化为Q15格式数。
q15tofl:Q15格式数转化为浮点数。
在c:\ti\docs\pdf下的spra480b.pdf文档中,详细说明了这些函数的用法。在c:\ti\c5400\dsplib\EXAMPLES文件夹中还列出了这些函数的应用示例,阅读这些函数和应用示例将大大提高对算法的编程和应用能力。
7.2
C程序编译
C语言开发的程序具有可移植性好的特点,除底层的硬件控制和对时间有严格要求的函数外,一般尽可能用C语言开发,以加快DSP的开发速度,同时使程序的修改和移植也变得非常容易。
C语言代码通过C编译器先转化为汇编程序,然后由汇编器编译转化为机器执行码。在将C语言编译成汇编程序时,有一些固定的规则,学习这些规则对优化代码和混合编程都非常有好处。7.2.1
C编译器生成的段
C54x有两种存储器:程序存储器和数据存储器,程序存储器包含可执行代码,数据存储器包含外部变量、静态变量和系统堆栈等。C编译器对C语言进行编译后,生成若干个
可以进行重新定位的代码和数据块。除了生成3个基本的段.text、.data、.bss外,还有.cinit、.const、.stack、.sysmem段等。这些段分为两类:已初始化段和未初始化段。已初始化段主要包含可执行代码和数据表,C编译器共创建4种已初始化段。
(1).text段:包含可执行代码、字符串及编译器产生的
常数。
(2).cinit段:包含初始化变量和常数表。
(3).const段:包含字符串和用const定义的常量。
(4).switch段:包含用.switch语句建立的表格。未初始化段用于为变量或函数执行分配存储空间,但没有初始化,程序利用这些空间在运行时创建和存储变量,C编译器共创建3种未初始化段。
(1).bss段:为全局变量和静态变量分配存储空间。在
程序启动后,C语言初始化引导程序将数据从.cinit段复制到
.bss段。
(2).stack段:为C语言堆栈分配存储空间,用于传递变量、分配局部变量和保护函数现场等。
(3).sysmem段:为动态存储器函数malloc、calloc和realloc分配存储器空间。若C语言没有用到这些函数,编译器就不创建这个模块。
其中堆栈段主要完成以下功能:保护函数的返回地址、分配局部变量、传递函数变量、保护调用函数现场及其他一些临时结果。C编译器定义的堆栈大小默认为1K字,也可以在连接命令行加上一个stack选项重新定义堆栈大小。C编译器用堆栈指针(SP)指向堆栈的顶部。通常,.text、.cinit和.switch段必须映射到程序存储器的PAGE0页,具体存储器可以是ROM或RAM;.const段必须映射到数据存储器的PAGE1页,具体存储器可以是ROM或RAM;而.bss、.stack和.sysmem段必须映射到数据存储器的PAGE1页,具体存储器只能是RAM。7.2.2
C编译器的寄存器规则
在C语言环境中,不同的寄存器有不同的使用规则。在混合编程时,如果遵守这些规则,可有效地提高编程效率和程序的执行效率。
寄存器在使用上分两类:进入保存和调用保存。进入保存是由被调用函数负责保存,调用函数自由使用;调用保存是由调用函数分组保存,被调用函数自由使用。寄存器的使用和保护规则如表7.2所示。从表7.2中可以看出,被调用函数需保护AR1、AR6和AR7,其余寄存器由调用函数保护,所以调用函数只可自由地使用AR1、AR6、AR7。要使用其他寄存器,需在调用函数前压栈保护。调用函数执行完毕后再恢复为原来的值,而被调用函数则相反。SP无论是在调用函数还是被调用函数中,都不允许自由使用,但可以用汇编指令“FRAME#k”来管理。7.2.3
C程序的系统初始化
C程序在运行之前,必须创建C语言的运行环境,创建过程由C初始化程序完成,其函数名为c_int00。
这个函数包含在rts.lib的运行支持库中,rts.lib库中函数的源代码都包含在rts.src中。要调用c_int00函数,只需在链接器使用“lrts.lib”选项即可,也可手动将其加入到项目中。c_int00初始化C语言运行环境时主要完成以下工作:
(1)为系统堆栈定义.stack段,并初始化堆栈指针。
(2)将.cinit段的初始化数据复制到.bss段中,对全局变量和静态变量进行初始化。
(3)调用main()函数,开始运行程序。
7.3
C语言与汇编语言混合编程
C语言是一种通用编程语言,适用于对时间要求不高的场合。但如果运算时间非常紧张,C编译器则很难充分利用DSP独特的硬件结构来提高执行效率,如充分利用循环寻址、位反转寻址等。另外,C语言对底层的硬件操作比较困难,甚至无法实现,而用汇编语言编程则比较容易,如初始化McBSP接口等。因此,采用C语言与汇编语言混合编程能充分发挥两者的优势,达到最佳的效果。7.3.1混合编程方式
(1)独立编写C程序和汇编程序,只要两者的接口满足函数调用要求,就不会相互影响。如FFT程序一般先用汇编语言编写,然后在C程序中调用。只要调用函数和FFT函数都满足函数调用规则就能实现混合编程,达到优势互补的目的。(2)直接在C程序的相应位置插入汇编语句。这类汇编语句一般是对硬件进行操作,要求不能对C环境造成影响。如下面一条语句是在C程序中设置开中断:
asm(″ RSBXINTM″); //开中断7.3.2
C程序访问汇编变量
C文件定义的变量名在编译时均在名称前加一下划线“_”,以区别汇编文件定义的变量名,C文件中定义的函数名也如此。这样即使两种文件的变量名和函数名相同,也不
会产生冲突。变量名和函数名经编译后都代表变量的存储地址和函数的入口地址,由此可推出C文件与汇编文件相互访问的方法。要使C文件能访问汇编变量和函数,则需要在汇编文件定义这些变量名和函数名时,在其名称前加下划线“_”,而在C文件引用时不要加下划线,具体实现方式如下:
(1)在汇编文件.bss段定义汇编全局变量。
①用.bss段定义变量,并在变量前加一下划线;
②用.global命令声明外部变量;
③在C文件中声明外部变量。例7.1
C程序访问汇编变量。
①汇编文件定义:
.global_input;声明全局变量,名称必须包含“_”
.bss_input,1
②C文件引用:
externintinput//声明外部变量及数量类型,变量名要去掉“_”input=ioport0002;//读外部端口0x0002到input中
(2)访问汇编常数表。
①用.sect段定义常数表,并在变量前加一下划线;
②用.global命令声明外部变量;
③在C文件中声明外部指针。
声明的指针像C文件定义的指针一样使用。例7.2
C程序访问汇编常数表。
①汇编文件定义:
.global_sine;声明全局变量,名称必须包含“_”
.sect″sine_table″
_sine:
.word0x0,0x5a82,0x7fff,0x5a82,0x0,0xa57f,0x8002,0xa57f
;8点正弦表②C文件引用:
externintsine[]//声明外部指针及数量类型,变量名要去掉“_”
for(i=0;i<8;i++)
x=sine[i];
(3)访问汇编常数。
①用.set定义常数,并在变量前加一下划线;
②用.global命令将其声明为外部变量;
③在C文件中用#define声明常数。常数名前去掉“_”,但在其前加“&”,表示取地址。汇编文件定义的常数像C文件定义的常数一样使用。例7.3
C程序访问汇编常数。
①汇编文件定义:
.global_table_size,_sine
_table_size .set8//汇编文件定义的常数
_sine:
.word0x0,0x5a82,0x7fff,0x5a82,0x0,0xa57f,0x8002,0xa57f
;8点正弦表②C文件引用:
externintsine[]
#defineTABLE_SIZE(int)(&table_size)//C文件引用汇编常数
for(i=0;i<TABLE_SIZE;i++)
x=
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 初中数学教研组工作总结-15篇
- 2025年水利管理及技术咨询服务项目申请报告模范
- 2025年测高仪项目提案报告模范
- 2025年数控裁板锯项目提案报告模稿
- 保安个人述职报告集合15篇
- 2024冶金工程质保期合同担保协议2篇
- 去广告公司实习报告范文集合七篇
- 保险公司实习报告范文集锦八篇
- 初二生物教学计划范文合集五篇
- 小学生考试没考好检讨书
- “大综合一体化”行政执法改革工作自查报告
- DB5110∕T 37-2021 地理标志产品 资中冬尖加工技术规范
- (3)110KV配电装置安装单位工程质量验收评定表1
- 课程设计之年产90000吨丙酮水连续精馏塔的设计
- 赞比亚矿产资源及矿业开发前景分析
- 餐饮前台餐具与杂件清单
- 河南省建设工程安全监督备案申请表
- 海拔高度与气压、空气密度、重力加速度对照表
- 道路平交口计算公式
- 铁路隧道安全风险评估
- 静压桩施工记录表
评论
0/150
提交评论