gongxd 发表于 2011-2-28 22:30:02

CCS3.3 5402 浮点运算 诡异问题求解

请教高手们一个问题
我写了一段程序
用ccs3.3 dsp5402
仿真的时候是没有错误的
脱离仿真器运行就错误,程序也是在运行的,就是 有浮点运算的地方有问题

比如
x=11.0;
peakError=0.0001;
sampleRate=882000;
peakx=(float)x+peakError;
peakfrequency=(float)(sampleRate)/(float)(128.0) ;

peakfrequency的结果却是负数


还有 用double的 地方 也出现错误
仿真没问题 运行就出错
这个问题已经困扰我好几天了 现在头大了 请大家帮帮我谢谢

zhangsusu 发表于 2011-2-28 22:58:30

看到你到处发帖 5402本身就是一款定点的dsp 浮点算法都是通过C模拟的 效率很低
你需要查54x的C programming 手册 看看里面浮点算法的说明
不过 我觉得一个切实可行的方法就是描述清楚你的问题
包括 输入值范围 输出值范围 计算表达式(算法) 大家一起看能否定点(Q化)完成
定点算法本身就是dsp的特色 要是都去操作外设 dsp和51 也没啥大的区别了
论坛里讨论定点算法的比较少 可以借此活跃人气 呵呵

gongxd 发表于 2011-3-1 10:24:10

回复【1楼】zhangsusu
-----------------------------------------------------------------------

谢谢 zhangsusu,呵呵

我现在疑惑的是 为什么 仿真 浮点运算是正确的 下载运行的就不对呢
当然通过定点可以解决这个问题
但是根本原因还是没找到啊
期待高人指点

程序如下






//计算阻尼比
void cacldamp(Int16 *sounddataorg)
{
//最大值点数组
Uint16 peakpointindex;
Uint16 peakpoint;
Uint16 peakpointindextmp;
//最大峰值点索引
Uint16 Maxpeakpointindex;
Uint16 i;
double damptmp;

//找出波形所有的峰值
peakpointindextmp=0;
for (i=SonicPM.SoundDecay.WindowStart;i<sounddataorgmax_1;i++)
{

        if (sounddataorg>=sounddataorg && sounddataorg>sounddataorg)
        if (sounddataorg>=sounddataorg && sounddataorg>sounddataorg)
        {
        //取过极大值点
                peakpointindex=i;
                peakpoint=sounddataorg;
                peakpointindextmp++;
        }
        //如果采集够指定的波形数就跳出循环
        if (peakpointindextmp>peakpointcount)
        {
                break;
        }

}//for

//如果极大值点个数大于0为正常,继续处理
if (peakpointindextmp>0)
{
        //for (i=0;i<peakpointindextmp;i++)
        //{
                if( peakpointindextmp>SonicPM.SoundDecay.WindowLength)
                {
                Maxpeakpointindex=getpeakpositonUint16(peakpoint,peakpointindextmp-SonicPM.SoundDecay.WindowLength);
                }
                else
                {
                Maxpeakpointindex=getpeakpositonUint16(peakpoint,peakpointindextmp);
                }


        //}

        //获得点数长度方便显示
        SonicPM.SoundDecay.WindowStartPoint=peakpointindex;

        SonicPM.SoundDecay.WindowLengthPoint=peakpointindex;
        //计算峰值频率
        damptmp=100000*log(
        (        (double)peakpoint/
        (double)peakpoint   )
        );
//阻尼比计算公式 1/n* ln (An/A1)

/*
        damptmp=damptmp/
        ((double)peakpointindex
        -
        (double)peakpointindex
        );
*/

        damptmp=damptmp/(double)(SonicPM.SoundDecay.WindowLength);
        damptmp=damptmp/2.0;
       damptmp=damptmp/3.1415926;

        SonicPM.DetDamp=(Int16)damptmp;
}
else
{
//计算峰值频率
SonicPM.DetDamp=-1;
}


其中 sounddataorg 是采集的声音数据 16位int
格式的

函数的功能是 找出波形的最大的幅值 然后间隔n个波形的最大值

计算波形的衰减系数

算式是衰减=1/n * Ln(A1/An)

A1 An 都不超过 32768也进行了强制转换 为double 了

仿真计算结果正确下载后 计算结果为 0x7FFFFH

haeha 发表于 2011-3-1 11:26:58

能用串口输出吗,看看从哪部开始计算结果不对了。
另外,用sizeof看下double的长度,我记得ccs3.3里,double和float精度是一样的

gongxd 发表于 2011-3-1 15:57:13

能输出数据 可以运行程序后 用仿真器调试看到执行 浮点乘除法时错误
加减没问题

但是用仿真器下载进程序去就没有问题

zhangsusu 发表于 2011-3-1 16:19:39

回复【3楼】haeha
-----------------------------------------------------------------------
用仿真器+watch 就行了 这么复杂的算法 串口搞不定

zhangsusu 发表于 2011-3-1 19:10:56

回复【2楼】gongxd
-----------------------------------------------------------------------

你仿真使用的simulator吗?
下载是用得load 还是 烧到flash上了?
对于
sampleRate=882000;
peakfrequency=(float)(sampleRate)/(float)(128.0) ;

何不写成
// 对于54x Int32 means long
Int32 sampleRate = 882000;
Int32 peakfrequency;

peakfrequency = sampleRate >> 7; // means sampleRate/128

gongxd 发表于 2011-3-1 20:41:04

回复【6楼】zhangsusu
-----------------------------------------------------------------------

看了一天汇编,似乎找到问题了
我的程序 是通过单片机的 HPI 接口 boot的

上段程序中
damptmp=damptmp/2.0;
damptmp=damptmp/3.1415926;

用到了 2.0,3.1415926 的常数,编译到.const 了
汇编调试的时候,看到 这两个数据并没有初始化,所以计算错误


程序中还用到了 很多其他的常数,但都是整形的,似乎已经初始化了

我把

damptmp=damptmp/2.0;
改为
uint16 ddd=2;
damptmp=damptmp/(double)ddd;

就可以了


请问是这个样子么,那.const段要编写代码手动初始化么


如下的方法 可以么



设置.const段的装载地址和运行地址。其表达式如下。
.const : LOAD = FLASH PAGE 0 , RUN = EXT PAGE 1
{
__const_run = .;      /* 获取运行地址 */
*(.c_mark)      /* 标志装载地址 */
*(.const)          /* 分配.const段 */
__const_length = .- __const_run;/* 计算段长 */
}
   采用了装载地址与运行地址分离的方式后,为了使程序正常运行,在初始化时,需要将.const段的内容从装载地址拷贝到运行地址内。这段程序可以在编译时由编译器自动生成。这还需要对软件所使用的库文件作简单的修改。该库名称即是rts.lib(表示不同类型的DSP,有2xx,25,50等等)。修改该库的方法是将源文件从库中提取出来,作修改,编译后再替代原有的文件。具体的操作如下:先执行DOS命令:
dspar -x rts.src boot.asm
这句的功能是从rts.src文件中提取出boot.asm文件。这个rts.src即是rts.lib的源文件。在boot.asm文件中能找到CONST_COPY这个标志量,为了实现所需要的功能它应被赋值为1。对boot.asm文件的编辑完成之后,就可以将其编译生成目标文件,执行语句:
dspa -v boot.asm
其中对于不同的DSP需要使用不同的参数,对于240xA来说,应该使用2xx来代替“”。语句执行完后会生成boot.obj文件。再执行语句:
dspar -r rts.lib boot.obj
这时它就替换了库里的同名文件。在编译时编译器就会自动增加拷贝.const段到数据空间的语句。这种方法不必修改程序,代价是牺牲了一定数据存储空间,时间开销主要出现在初始化中。这是最经济实用的方法之一。
使用代码工具
各种各样的代码生成工具可以大大增加编程的灵活性。除了前面提到的dspar与dspa两个指令外,C文法分析程序dspac.exe对.C文件进行文法分析,生成.IF中间文件,dspopt.exe对.IF文件进行优化,生成.OPT文件。此外,还有其它多种功能不同的代码工具。对于应用环境苛刻的程序,它们有利于分析如何对其进行优化。





正在试验,dsp不太熟悉啊,呵呵



请问是这个样子么,那.const段要编写代码手动初始化么

gongxd 发表于 2011-3-1 21:04:35

回复【6楼】zhangsusu
-----------------------------------------------------------------------

问题 解决 是这个地方的问题 谢谢 zhangsusu 的帮助

gongxd 发表于 2011-3-2 09:19:08

又出现 新问题了

我的程序中用到了 FFT 函数 其中有正弦函数表
   .sintab

在段分配中
         .sintab :>       DARAM1   PAGE 1

放到 ram中 无法运行
也应该是没初始化

请问有什么好的方法 初始化 sintab么

gongxd 发表于 2011-3-5 08:18:12

点击此处下载 ourdev_620059C3DH9W.rar(文件大小:232K) (原文件名:rtslib5000.rar)

HPIBoot cmd文件

birenpeter 发表于 2011-3-28 13:31:49

回复【10楼】gongxd
-----------------------------------------------------------------------

太好了啊,我也遇到这个问题
页: [1]
查看完整版本: CCS3.3 5402 浮点运算 诡异问题求解