问题1:CCS编译环境下的使用步骤及常见问题
解决方案:
一、见到下面的警告对话框请不要担心,值得一提的是 DSP 开发成本相对比较高,它需要专用的仿真器和目标板,一般来说成本都是几千元的。对于一般的想熟悉下编辑环境不想花费代价,就可以在弹出下面对话框中选择画线按钮。
三、单击“ open ”选项,会出现两个下拉菜单,其含义图中已经有所说明,这里我们选择第一个软件仿真。
四、单击我们就可以进入到软件编辑窗口中。
五、为了方便说明,我们打开一个已经新建好的工程,工程后缀为“ *.pjt ”。用CCS打开/创建工程时,工程存放的路径名中不能有中文!(不像VS6、ISE等可以使用任意路径名)
六、打开工程后,打开工程文件中的 sourse 文件夹会发现里面有很多的 C 语言文件,但是我们只用到最后一个,即下图中画圈部分。其他的文件不需要去深入的了解,如果我们想新建工程的话,那么我们认为把以前的文件 COPY 还比较快点,另外稳定性的高。
七、文件的编译。一般来说我们主要用图中画圈部分的两中编译方法。
八、如果上面的编译没有问题我们就可以进行下面的操作了。
打开“ *.out ”文件之后,我们可以进行下面的调试的操作了。首先,在菜单“ debug ” 的下拉菜单中依次选取: Reset CPU 、 Restart 和 Go main 三个选项,注意顺序一定不能弄反,否则可能编译不了。 上一步骤完成之后,我们就可以进行单步或者是全速执行等调试操作了。这和 keil 软件的功能差不多,不需要在这里多加重复。
问题2:CCS中库使用问题
解决方案:
下面以“volume”程序为例讲一下CCS中如何看程序运行的时钟周期。首先打开一个Project文件。
其中*.c文件和*.h文件与普通的C语言编程中是一致的(TI编译器支持ANSI C标准)。需要指出的是三个文件:VOLUME.CMD、RTS6400.LIB、VECTORS.ASM。VOLUME.CMD文件给出了程序空间和数据空间的设置、及编译后各程序段在程序或数据空间的具体位置。RTS6400.LIB文件为DSP运行时库,VECTORS.ASM为中断向量表,都是区别于纯软件编程的独到之处,熟悉以后会有更深的体会。下图为volume.CMD文件的代码,MEMORY分为程序空间IPRAM和数据空间IDRAM,并分别给出了起始地址origin和长度len,各段在 MEMORY空间的分配也作了定义。对于实际的目标板硬件系统,由实际的存储器空间及DSP芯片上的存储空间决定。对于软件仿真,可以不考虑有没有 MEMORY资源。
自己在编写工程项目文件时,经常会遇到下面的问题,没有C语言程序的入口函数,细心比较一下会发现工程文件中缺少了一个运行时支持RTS6400.LIB,不同的DSP芯片需要不同的运行时库来支持。
问题3:LOG_printf和printf的正确使用问题(区别与联系)
解决方案:
共性:都是用于输出一些内容,一般用于显示一些调试信息,而且可以格式化输出,比如用’%d’输出整数
区别:
1输出目标不同,printf输出到output窗口,而LOG_printf输出到BIOS的log窗口
2汇编指令条数不同,printf需要上万条汇编指令,而LOG_printf只要30多条汇编指令,因此LOG_printf的运行速度比printf要快的多,一般在实时系统中,都使用LOG_printf来输出,这样对系统的实时性影响才不大。
3.参数个数不同,printf后面的参数个数可以有很多个(具体多少个没测试过),而LOG_printf后面最多只能有4个参数,第一个是写入的地址,第二个是字符串,后面最多加上两个格式化输出的数据,这两个数据还必须是整型,或者指针,或者常量字符串
4.可以输出的格式不同,printf有很多的格式,而LOG_printf只有有限的几种.(%d整型,%x无符号16进制数,%o无符号8进制数,%s常量字符串,%p指针)
5.LOG_printf输出的长度受设定的buffer大小限制,如果超出buffer大小,根据设置的不同,可以是停止输出,或者覆盖原来的内容
6.LOG_printf的优先级比较低,可能是在KNL层,只有系统比较空闲的时候,才会输出,而printf是必然会输出.(比如在一个i=1到 100的循环中,用printf就会输出100个数,而用LOG_printf就只会输出一部分数,而且在没有碰到断点的时候,根本不会输出,因为他的优 先级相当低,只有在走到断点的时候,系统才允许它执行。)
Printf函数使用图示
问题4:CCS中改变程序选项引起的语法错误问题
问题描述;
在学习VOLUME1.pjt时,我们在对该工程文件进行compile&build后,进一步选择Project?Build Options。打开后选择Compiler tab , 然后选择 从目录里点击Preprocessor, Pre-Define Symbol [-d]写入 FILEIO 在 field,然后点TAB键并确定修改完成。
REBULID一次得到如下结果:
解决方案:双击描述第一行错误syntax error: expected a ";". (actual line number may vary),然后在processing(input, output)句末添加一个“;”再次运行程序就可以顺利load了。
问题5:CCS3.1与WIN7不兼容问题
问题描述:CCS3.1在WIN7系统下无法安装,可能是由于WIN7内部某些库经过更新而无法为CCS3.1使用所致
解决方法:
安装虚拟机,在虚拟机上启动WINDOWS XP系统,然后在虚拟机环境下安装CCS3.1
接着就可以在虚拟机下启动WINDOWS XP安装CCS3.1,并且可以以后每次启动CCS3.1都是在虚拟机环境下启动。
启动CCS3.1时会出现如图窗口,选择忽略即可打开该软件。
这样CCS3.1与WIN7不兼容的问题得以解决。
问题6:FFT变换功率谱计算问题
问题描述:
在for(i=0; i
其中数组FFT中存放FFT变换后的结果,数据类型为int,偶数下标为实部,奇数下标为虚部。计算后结果保持到Power数组中,用Graph绘制Power中的数据,如图1所示。原始信号中包含10Hz和50Hz两个频率的信号成分,功率谱中应该在10Hz与50Hz对应的位置出现两个波峰,而图1没有体现出这样的特性。
数组FFT中偶数下标为实部,奇数下标为虚部,用Graph直接将实部与虚部都绘制出来,虽然曲线没有实际的意义,但一定程度上反映出功率谱曲线的形状,同时可以直观的观察每个数据的数值。对比图2和图1,可以发现,计算功率是结果出错了。错误的原因可能是int型整数乘法溢出了。
解决方法:扩大计算精度可以防止溢出的发生。原有的计算功率的语句替换为:
for(i=0; i
Power[i]= sqrt((float)OutFFT[i*2]*OutFFT[i*2]+(float)OutFFT[i*2+1]*OutFFT[i*2+1]);
将int整形乘法转换为float类型的乘法,保证乘法运算不溢出。
用Graph绘制出功率谱如图3所示,此时功率谱在10Hz与50Hz处出现两个波峰,与实际情况相符。
问题7:CCS3.3下 float类型函数返回了错误的值
问题描述: stencil recognize即调试图像清晰度函数,函数definition_calc()在 image_deal.c 里定义,返回值为float, 返回变量为SG_sum; 在主函数里引用,并将函数返回值赋值给一个float型变量,变量名为image_definition; 编译通过,无错误和警告.SG_sum值计算正确, 但函数返回后,变量image_definition的结果不正确.
解决方案:
1.函数返回值强制类型转换为long,将函数返回类型和image_difinition的类型都修改为long, 结果正确。
2.复原返回值为float, 在主函数之前加函数float definition_calc()声明, 结果正确。
初步结论: 虽然CCS3.3下,跨文件函数引用不需要函数声明也能编译链接通过,但为了避免同上的莫名其妙问题出现,推荐还是严格按照C的标准语法编程--跨文件函数引用,提前声明。后续问题: 为什么只有float返回才会出问题,int和long char都正常?是不是编译器需要做设置或调整?既然不需要提前声明,那是不是系统自动生成了头文件或是其他什么文件。
问题8:CCS3.3中每种数据类型的长度和取值范围总结
问题描述:在CCS编程过程中,常常会因为没有确定好合适的数据类型,从而造成数据溢出是的计算的结果出现错误。而初学者在这方面经验不足,因而有时找不到语法错误,但是却得不到自己想要的结果,例如两个数进行点积运算
在给寄存器载入数据前我们需要了解我们运算的数据类型是什么,因此我们首先要计算数据长度才能确定数据类型。对于以下较大数据选用一个16位寄存器在相乘时会出现数据溢出的情况,从而使程序检验阶段程序员分析判定出现疑问。
解决方案:
在数据计算之前,需要对数据类型做出清晰地认识,避免发生低级错误
数据类型 |
长度(字节) |
值域 |
char |
1 |
ASCII码字符 |
unsigned char |
1 |
-128~127 |
signed char |
1 |
0~255 |
unsigned int |
4 |
0~4294967296 |
int/signed int |
4 |
-2147483648- 2147483647 |
unsigned short/unsigned short int |
2 |
0~ 65535 |
short/short int/signed short/signed short int |
2 |
- 32768~ 32767 |
unsigned long/unsigned long int |
8 |
0~1.8447e+019 |
long/long int/signed long/signed long int |
8 |
-9.2234e+018~9.2234e+018 |
float |
4 |
约精确到小数点后6位数 |
double |
8 |
约精确到小数点后15位数 |
|
|
|
问题9:CCS3.3中代码运行时间统计问题
问题描述:由于在实际编程过程中会考虑到程序性能的问题,因此需要在CCS中统计代码的运行时间,以便对不同方式或思路下的程序性能做出合理的判定。具体实现过程可以按照下面的方式执行。
解决方案:在CCS3.3中如何统计代码的运行时间,首先,将代码的阅览模式设置成前面的源码和汇编同时显示的模式。
点击"Profile"--"Clock"--"Enable",来使能CLOCK功能。接下来点击"Profile"--"Clock"--"View",在CCS最下面会出现一个类似于秒表的工具,旁边显示数字“0”。
我们关注main函数这一块,在代码“int *input = &inp_buffer[0];”前面设置断点,然后点击Run,这样程序就会停在这一行代码前面,而且黄色指针指示源码,绿色指针指向汇编。
这时,底下的CLOCK工具开始显示的是753,当然不同的环境显示的数字应该是不一样的。这就是从开始执行到这一语句所花的时间了,那753的单位是“CPU Cycles”,CPU的时钟周期。
将两个地方的CLOCK工具显示的值相减就能得到这一段代码的执行时间了。
问题10:CCS3.3 程序入口定义问题
问题描述: warning: entry point symbol _c_int00 undefined
解决方案:使用C写DSP时,在rts.lib库中定义了入口地址:_c_int00
而使用汇编语言编程,就不用包括rts.lib库,所以入口地址及其标号可以由人工指定。而使用C时,就不同了,必须从rts.lib定义的这个入口_c_int00入口,是约定的。
The –c and cr options cause the linker to use linking conventions that are required by the C compiler.”
其实在汇编语句中也可以不用_c_int00来定义程序入口,只要把编译器选项 -c去掉,用-e 选项来定义你想要的程序入口地址。这个可在CMD文件里加-c。
这个错误是没有加库文件,你可以project view 右键加入,也可以在project->build options->Linker->libraries中加入..\..\lib\cls\lib\(搜索路径)还要加上库名cslDM642.lib;rts6400.lib分号隔开。