《DSP的C语言编程.pdf》由会员分享,可在线阅读,更多相关《DSP的C语言编程.pdf(62页珍藏版)》请在taowenge.com淘文阁网|工程机械CAD图纸|机械工程制图|CAD装配图下载|SolidWorks_CaTia_CAD_UG_PROE_设计图分享下载上搜索。
1、第15章DSP的C语言编程第15章DSP的C语言编程15.1 DSP C语言简介15.1 DSP C语言简介DSP生产厂商及第三方为DSP软件开发提供了DSP生产厂商及第三方为DSP软件开发提供了C编译器C编译器,使得利用高级语言实现DSP程序的开发成为可能。在TI公司的DSP,使得利用高级语言实现DSP程序的开发成为可能。在TI公司的DSP软件开发平台CCS中软件开发平台CCS中,又提供了,又提供了优化的C编译器优化的C编译器,可以对C语言程序进行优化编译,提高程序效率,目前,可以对C语言程序进行优化编译,提高程序效率,目前在某些应用中C语言优化编译的结果可以达到手工编写的汇编语言效率的90
2、%以上在某些应用中C语言优化编译的结果可以达到手工编写的汇编语言效率的90%以上。DSP生产厂商和相关公司也在。DSP生产厂商和相关公司也在不断对C优化不断对C优化编译器进行改进编译器进行改进设计,相信日后设计,相信日后C语言程序优化编译的效果C语言程序优化编译的效果会有会有进一步的改善进一步的改善。TMS320C2000系列TMS320C2000系列提供有提供有优化的C编译器优化的C编译器,它支持,它支持ANSIANSI(American National Standards Institute,(American National Standards Institute,美国国家标准委员会
3、美国国家标准委员会)开发的C语言标准,该C语言标准是使用最广泛的C语言标准,)开发的C语言标准,该C语言标准是使用最广泛的C语言标准,ANSI标准ANSI标准具有一些受目标处理器、运行期环境或主机环境影响的C语言特性,从有效性或实现上的考虑,这些特征在各种标准的C编译器之间可能有不同。具有一些受目标处理器、运行期环境或主机环境影响的C语言特性,从有效性或实现上的考虑,这些特征在各种标准的C编译器之间可能有不同。15.2 DSP C语言特性15.2 DSP C语言特性15.2.1 TMS320C2000 C语言的特征15.2.1 TMS320C2000 C语言的特征(1)标识符和常数(1)标识符
4、和常数所有标识符的所有标识符的前100个字符有意义前100个字符有意义,区分大小写区分大小写。源(主机)和执行(目标)源(主机)和执行(目标)字符集为ASCII码字符集为ASCII码,不存在多字节字符不存在多字节字符。具有具有多个字符的多个字符的字符字符常数按序列中最后一个字符来编码常数按序列中最后一个字符来编码,例如:,例如:abcabc=c c(2)数据转换(2)数据转换浮点到整数的转换浮点到整数的转换取整数部分取整数部分。指针和整数可以自由转换。指针和整数可以自由转换。(3)表达式(3)表达式当当两个有符号整数相除两个有符号整数相除时,若其中一个为负,则其商为负,时,若其中一个为负,则其
5、商为负,余数的符号与分子的符号相同余数的符号与分子的符号相同。斜杠(/)斜杠(/)用来用来求商求商,百分号(%)百分号(%)用来用来求余数求余数。例如:。例如:10/-3=-3,-10/3=-3,10%-3=1,-10%3=-110/-3=-3,-10/3=-3,10%-3=1,-10%3=-1(4)声明(4)声明寄存器变量寄存器变量对所有char,short,int和指针类型有效。对所有char,short,int和指针类型有效。interrupt关键字interrupt关键字仅可用于没有参量的void函数。仅可用于没有参量的void函数。(5)预处理(5)预处理预处理器预处理器忽略任何不支
6、持的#pragma伪指令忽略任何不支持的#pragma伪指令。预处理器支持的伪指令包括:预处理器支持的伪指令包括:CODE_SECTOINCODE_SECTOINDATA_SECTIONDATA_SECTIONFUNC_EXT_CALLEDFUNC_EXT_CALLED15.2.2 TMS320C2000 C语言的数据类型15.2.2 TMS320C2000 C语言的数据类型注:注:在TMS320C2x/C2xx/C5x C语言中,字节长度为16位,sizeof操作符返回的对象长度是以16位为字节长度的字节数。例如sizeof(int)=1。在TMS320C2x/C2xx/C5x C语言中,字
7、节长度为16位,sizeof操作符返回的对象长度是以16位为字节长度的字节数。例如sizeof(int)=1。15.2.3 TMS320C2000 C语言的关键字15.2.3 TMS320C2000 C语言的关键字 const(常数)const(常数)ioport(I/O端口)ioport(I/O端口)interrupt(中断)interrupt(中断)near(近)near(近)far(远)far(远)volatile(可变的)volatile(可变的)15.2.4 寄存器变量15.2.4 寄存器变量TMS320C2000 C编译器在一个函数中TMS320C2000 C编译器在一个函数中最多
8、可以使用两个寄存器变量最多可以使用两个寄存器变量。寄存器变量的声明必须在变量列表或函数的起始处进行寄存器变量的声明必须在变量列表或函数的起始处进行,在嵌套块中声明的寄存器变量被处理为一般的变量。编译器使用AR6和AR7作为寄存器变量:,在嵌套块中声明的寄存器变量被处理为一般的变量。编译器使用AR6和AR7作为寄存器变量:AR6被赋给第一个寄存器变量AR6被赋给第一个寄存器变量 AR7被赋给第二个寄存器变量AR7被赋给第二个寄存器变量寄存器变量的地址会被放入分配的寄存器中,这样变量的访问速度会更快。寄存器变量的地址会被放入分配的寄存器中,这样变量的访问速度会更快。16位类型的变量16位类型的变量
9、(char、(char、short、int和指针)都可以被定义为寄存器变量。但在运行时,设置一个寄存器变量大约需要4条指令,为了更有效地使用这个功能,short、int和指针)都可以被定义为寄存器变量。但在运行时,设置一个寄存器变量大约需要4条指令,为了更有效地使用这个功能,仅当变量被访问超过2次时,才使用寄存器变量。仅当变量被访问超过2次时,才使用寄存器变量。程序优化编译器也会定义寄存器变量,但使用方式不同。编译器会自己决定哪些变量作为寄存器变量,程序中声明的寄存器变量会全部被忽略。程序优化编译器也会定义寄存器变量,但使用方式不同。编译器会自己决定哪些变量作为寄存器变量,程序中声明的寄存器变
10、量会全部被忽略。声明的格式为:声明的格式为:register type reg;register type reg;15.2.5 pragma伪指令15.2.5 pragma伪指令pragma伪指令通知编译器的预处理器如何处理函数。TMS320C2000 C编译器支持下列pragma:pragma伪指令通知编译器的预处理器如何处理函数。TMS320C2000 C编译器支持下列pragma:CODE_SECTIONCODE_SECTION DATA_SECTIONDATA_SECTION FUNC_EXT_CALLEDFUNC_EXT_CALLED1.CODE_SECTION1.CODE_SEC
11、TION这个伪指令在名称为section name的命名段中为symbol分配空间。这个伪指令在名称为section name的命名段中为symbol分配空间。语法为:语法为:#pragma CODE_SECTION(symbol,#pragma CODE_SECTION(symbol,“section namesection name”););2.DATA_SECTION2.DATA_SECTION这个伪指令在名称为section name的命名段中为symbol分配空间。这个伪指令在名称为section name的命名段中为symbol分配空间。语法为:语法为:#pragma DATA_S
12、ECTION(symbol,#pragma DATA_SECTION(symbol,“section namesection name”););3.FUNC_EXT_CALLED3.FUNC_EXT_CALLED当使用-pm选项时,编译器将使用程序级的优化。在这个优化层次中,编译器将删除所有未被main函数直接或间接调用的函数。当使用-pm选项时,编译器将使用程序级的优化。在这个优化层次中,编译器将删除所有未被main函数直接或间接调用的函数。而用户程序里可能包含要被手工编写的汇编语言程序调用而没有被main函数调用的函数,这时就应该用FUNC_EXT_CALLED来通知编译器保留此函数和被此
13、函数调用到的函数,这些函数将作为而用户程序里可能包含要被手工编写的汇编语言程序调用而没有被main函数调用的函数,这时就应该用FUNC_EXT_CALLED来通知编译器保留此函数和被此函数调用到的函数,这些函数将作为C程序的入口点。C程序的入口点。这个伪指令必须出现在对要保留的函数的任何声明或引用之前,其这个伪指令必须出现在对要保留的函数的任何声明或引用之前,其语法为:语法为:#pragma FUNC_EXT_CALLED(func);#pragma FUNC_EXT_CALLED(func);15.2.6 asm语句15.2.6 asm语句TMS320C2000 C编译器可以在编译器输出的汇
14、编语言程序中直接输出汇编指令或语句。利用asm语句嵌入TMS320C2000 C编译器可以在编译器输出的汇编语言程序中直接输出汇编指令或语句。利用asm语句嵌入汇编语言程序,可以汇编语言程序,可以实现一些C语言难以实现或实现起来比较麻烦的硬件控制功能实现一些C语言难以实现或实现起来比较麻烦的硬件控制功能。asm语句在语法上就象是调用一个函数名为asm的函数,函数参数是一个字符串:asm语句在语法上就象是调用一个函数名为asm的函数,函数参数是一个字符串:asm(asm(“assembler textassembler text”););编译器会直接将参数字符串复制到输出的汇编语言程序中,因此必
15、须保证参数双引号之间的字符串是一个有效的汇编语言指令。双引号之间的编译器会直接将参数字符串复制到输出的汇编语言程序中,因此必须保证参数双引号之间的字符串是一个有效的汇编语言指令。双引号之间的汇编指令必须以空格、制表符(TAB)、标记符(LABEL)或注释开头汇编指令必须以空格、制表符(TAB)、标记符(LABEL)或注释开头,这和汇编语言编程的要求是一致的。,这和汇编语言编程的要求是一致的。编译器不会检查此汇编语句是否合法编译器不会检查此汇编语句是否合法,如果语句中有,如果语句中有错误,在汇编的过程中会被汇编器指出。错误,在汇编的过程中会被汇编器指出。使用asm指令的时候应小心使用asm指令的
16、时候应小心不要破坏C语言的环境不要破坏C语言的环境。如果C代码中。如果C代码中插入跳转指令和标记符插入跳转指令和标记符可能会可能会引起不可预料的操作结果引起不可预料的操作结果。能够改变段或其它影响C语言环境的指令也可能引起麻烦。能够改变段或其它影响C语言环境的指令也可能引起麻烦。对包含asm语句的程序对包含asm语句的程序使用优化器时要特别小心使用优化器时要特别小心。尽管优化器不能删除asm指令,但它可以重新安排asm指令附近的代码顺序,这样就可能会引起不期望的结果。尽管优化器不能删除asm指令,但它可以重新安排asm指令附近的代码顺序,这样就可能会引起不期望的结果。15.2.7 访问I/O空
17、间15.2.7 访问I/O空间读写I/O空间的功能是TMS320C2000 C编译器对标准C的扩展,是利用关键字读写I/O空间的功能是TMS320C2000 C编译器对标准C的扩展,是利用关键字ioportioport(I/O端口)来实现的。(I/O端口)来实现的。该关键字的用法为:该关键字的用法为:ioport type portioport type porthexnumhexnum;ioport指示这是定义一个端口变量的关键字。ioport指示这是定义一个端口变量的关键字。type(类型)必须是char(字符)、short(短整型)、int(整型)或对应的无符号类型。type(类型)必须
18、是char(字符)、short(短整型)、int(整型)或对应的无符号类型。porthexnum为定义的端口变量,其格式必须是porthexnum为定义的端口变量,其格式必须是“portport”后面跟一个16进制数,如后面跟一个16进制数,如“port000Aport000A”是定义是定义访问访问I/O空间地址0Ah的变量。I/O空间地址0Ah的变量。所有I/O端口的定义所有I/O端口的定义必须在文件级必须在文件级完成,不支持在函数级声明的I/O端口变量。完成,不支持在函数级声明的I/O端口变量。利用ioport关键字定义的I/O端口变量可以象一般变量一样利用ioport关键字定义的I/O端
19、口变量可以象一般变量一样进行赋值操作进行赋值操作:ioport unsinged port10;/*访问I/O空间10h的变量*/ioport unsinged port10;/*访问I/O空间10h的变量*/.port10=a;/*将a写到端口10h*/port10=a;/*将a写到端口10h*/.b=port10;/*从端口10h读入b*/b=port10;/*从端口10h读入b*/.端口变量的使用不仅限于赋值操作,事实上,用ioport关键字定义的I/O端口变量可以象其它变量一样端口变量的使用不仅限于赋值操作,事实上,用ioport关键字定义的I/O端口变量可以象其它变量一样用在表达式中
20、用在表达式中:a=port10+b;/*读端口10h,加上b,结果赋给a*/a=port10+b;/*读端口10h,加上b,结果赋给a*/port10+=a;/*读端口10h,加上a,结果写回到端口10h*/port10+=a;/*读端口10h,加上a,结果写回到端口10h*/在在进行函数调用进行函数调用的时候,可以做I/O端口变量的值传递,而不是引用:的时候,可以做I/O端口变量的值传递,而不是引用:call(port10);/*读端口10h,将其值传递给函数调用*/call(port10);/*读端口10h,将其值传递给函数调用*/call(&port10);/*引用传递无效!*/call
21、(&port10);/*引用传递无效!*/15.2.8 访问数据空间15.2.8 访问数据空间访问DSP数据空间是利用指针来实现的访问DSP数据空间是利用指针来实现的:*(unsigned int*)0 x1000=a;/*将a的值写入数据空间*(unsigned int*)0 x1000=a;/*将a的值写入数据空间1000h地址*/1000h地址*/b=*(unsigned int*)0 x1000;/*读出数据空间1000h地址b=*(unsigned int*)0 x1000;/*读出数据空间1000h地址的值,赋给b*/的值,赋给b*/可见可见访问DSP数据空间地址不需要对要访问的单
22、元预先定义访问DSP数据空间地址不需要对要访问的单元预先定义,利用指针直接访问就可以了。这样,利用指针直接访问就可以了。这样,访问数据空间很容易实现循环结构访问数据空间很容易实现循环结构。for(i=0;icnt;i+)for(i=0;iVECS PAGE 0.text:PROG PAGE 0.cinit:PROG PAGE 0.data :PROG PAGE 0.stack :IDATA2 PAGE 1.bss:IDATA2 PAGE 1.reg240 x :REG_MEM PAGE 115.7.4 头文件15.7.4 头文件头文件头文件2407c.h主要定义主要定义TMS320LF2407
23、的的片内外设控制寄存器片内外设控制寄存器。此文件在利用。此文件在利用TMS320LF2407进行的各种开发中可以通用。进行的各种开发中可以通用。15.7.5 汇编文件15.7.5 汇编文件示例程序中没有利用汇编语言编写控制程序,但由于对定时器中断的处理采用回调方式,需要编写汇编文件示例程序中没有利用汇编语言编写控制程序,但由于对定时器中断的处理采用回调方式,需要编写汇编文件定义中断向量表定义中断向量表。.ref _gptime1,_c_int0.ref _gptime1,_c_int0.sect .vectors.sect .vectorsRSVECT B _c_int0 ;Reset Vec
24、torRSVECT B _c_int0 ;Reset VectorINT1 B PHANTOM ;Interrupt Level 1INT1 B PHANTOM ;Interrupt Level 1INT2 B _gptime1;Interrupt Level 2INT2 B _gptime1;Interrupt Level 2INT3 B GISR3 ;Interrupt Level 3INT3 B GISR3 ;Interrupt Level 315.7.6 C文件15.7.6 C文件(1)声明部分(1)声明部分(2)主函数(2)主函数(3)初始化定时器函数(3)初始化定时器函数(4)定时
25、器中断服务函数gp_init(4)定时器中断服务函数gp_initvoid interrupt gptime1(void)uWork=(*PIVR);/*读外设中断向量寄存器读外设中断向量寄存器*/switch(uWork)case 0 x27:/*T1PINT,0 x27为定时器为定时器1的周期中断的向量值的周期中断的向量值*/(*EVAIFRA)=0 x80;/*清除中断标志清除中断标志T1PINT*/break;15.7.7 实例总结15.7.7 实例总结实例功能要求虽然简单,却包含了DSP控制程序设计中的许多问题,包括:实例功能要求虽然简单,却包含了DSP控制程序设计中的许多问题,包括
26、:(1)(1)各种文件的编写各种文件的编写:头文件(.h)、链接命令文件(.cmd)、汇编代码文件(.asm)、C源文件(.c);:头文件(.h)、链接命令文件(.cmd)、汇编代码文件(.asm)、C源文件(.c);(2)(2)数据空间的读写数据空间的读写,对各种片内外设控制寄存器的设置都是通过数据空间的写操作实现的;,对各种片内外设控制寄存器的设置都是通过数据空间的写操作实现的;(3)(3)I/O空间的读写I/O空间的读写,四个发光二极管的显示控制就是通过对I/O空间的写操作实现的;,四个发光二极管的显示控制就是通过对I/O空间的写操作实现的;(4)(4)中断服务函数的编写中断服务函数的编
27、写,程序中的gptime1函数是一个中断服务函数,从函数定义到两级中断服务,程序中的gptime1函数是一个中断服务函数,从函数定义到两级中断服务函数的结构都是DSP C语言编程中常用的中断处理方法;函数的结构都是DSP C语言编程中常用的中断处理方法;(5)(5)中断向量表的定义中断向量表的定义,虽然实例程序中只有一个自定义中断服务函数,但中断向量表的定义方法在各种DSP应用中是类似的。,虽然实例程序中只有一个自定义中断服务函数,但中断向量表的定义方法在各种DSP应用中是类似的。实例程序已经覆盖到了DSP控制程序设计中大多数常见的问题,而在实际应用中可能存在的各种复杂问题的解决方法则需要在应用中深入研究。实例程序已经覆盖到了DSP控制程序设计中大多数常见的问题,而在实际应用中可能存在的各种复杂问题的解决方法则需要在应用中深入研究。结束结束