This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

[参考译文] CCS/MSP430G2955:将INT转换为浮点型数据的浮点型问题和Sprintf问题

Guru**** 2535750 points
Other Parts Discussed in Thread: MSP430G2955

请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/tools/code-composer-studio-group/ccs/f/code-composer-studio-forum/567175/ccs-msp430g2955-converting-int-to-float-problem-and-sprintf-issue-for-float-type-data

部件号:MSP430G2955

工具/软件:Code Composer Studio

我正在使用CCS MSP430G2955 1.0.0022万 开发运行在6.1 上的代码,我在将int转换为float时遇到问题,请参阅下面列出的相关代码:

Int CurrentOfBottomDevice;

浮点包装当前;

......

......

......

 CurrentOfBottomDevice =-100;

 PackCurrent =(FLOF)CurrentOfBottomDevice;

 taskENTER_critical();
 Sprintf (sCurrent,"i =%f",PackCurrent);
 taskEXIT_critical();

相应的反汇编代码如下所示:

1120  CurrentOfBottomDevice =-100;
3AB2:  40B2 FF9C 13BE     MOV.W  #0xx9c,&CurrentOfBottomDevice
1122  PackCurrent =(FLOW)CurrentOfBottomDevice;
3ab8:  421C 13BE          MOV.W  &CurrentOfBottomDevice,R12
3abc:  12B0 6B90          呼叫   ##_FS_utof
3AC0:  4C810008          MOV.W  R12,0x0008 (SP)
3AC4:  4D8.1万a          MOV.W  R13,0x000a (SP)
1124  taskENTER_critical();
3AC8:  C232               DINT    
3aca:  4303               NOP     
3acc:  4303               NOP     
3ace:  5392 16F8          不包括&usCriticalNesting   
1125  sprintf (sCurrent,"I =%f",PackCurrent);
3ad2:  40B17536 0000     MOV.W  #0x7536 0x0000 (SP)
3ad8:  4191 0008 0002     MOV.W  0x0008 (SP),0x0002 (SP)
3ade:  419.1万a 0004     MOV.W  0x000a (SP),0x0004 (SP)
3ae4:  410C               MOV.W  SP,R12
3ae6:  503C 000c          Add.W  #0x000c,R12
3aea:  12B0 6CB2          致电   #sprintf
1126     taskEXIT_critical();
3aee:  9382 16F8          TST.W  &usCriticalNesting
3af2:  2405               JEQ    (C$L142)
3af4:  8392 16F8          DEC.W  &usCriticalNesting
3af8:  2002               JNE    (C$L142)
3afa:  D232               EINT    
3afc:  4303               NOP     

可以看到调用函数__FS_utof将int转换为float, 但是int变量是-100,所以结果是错误的,PackCurrent的值是6.5436万.0 ,内存中相应的4字节十六进制数据是0x477F9C00,而 根据IEEE标准,-100的4字节十六进制数据应该是0xC2C8万。  这里的问题是,为什么编译器不使用__FS_itof函数,该函数也可以找到。

另一个问题是有关sprintf函数的,下面列出了sprintf的分解函数:

int sprintf (char *out,const char *format,...)

       VA_列表参数;
       
       VA_START( args, format );
       返回打印(输出,格式,参数)(&O);
}

打印功能的代码如下所示:

静态int print( char **out,const char *format,va_list args )

 寄存器int宽度, pad;
 寄存器int PC =0;
 CHAR SCR[2];

 用于(;*format !=0;++格式){
  如果(*format =='%'){
   ++格式;
   宽度=垫= 0;
   如果(*format =='\0') Break;
   如果(*format =='%')转到输出;
   如果(*format =='-'){
    ++格式;
    PAD = PAD_RIGHT;
   }
   同时(*format =='0'){
    ++格式;
    PAD || PAD_ZERO;
   }
   用于(;*format >='0'&&*format <='9';++格式){
    宽度*= 10;
    宽度+=*format -'0';
   }
   如果(*format ==’s){
    register char *s =(car *)va_arg( args, int );
    PC +=打印(输出,s:"(空)",宽度,垫);
    继续;
   }
   如果(*format =='d'){
    pc += printi (out,va_arg( args,int ),10,1, 宽度,垫片,'A');
    继续;
   }
   如果(*format =='x'){
    pc += printi (out,va_arg( args,int ),16,0, 宽度,垫片,'A');
    继续;
   }
   如果(*format =='X'){
    pc += printi (out,va_arg( args,int ),16,0, 宽度,垫片,'A');
    继续;
   }
   如果(*format =='u'){
    pc += printi (out,va_arg( args,int ),10,0, 宽度,垫片,'A');
    继续;
   }
   如果(*format =='c'){
    /* char被转换为int,然后被推送到堆栈*/
    scr[0]=(car)va_arg( args, int );
    SCR[1]='\0';
    PC +=打印件(输出,SCR,宽度,PAD);
    继续;
   }
  }
  否则{
  输出:
   printchar (输出,*format);
   +PC;
  }
 }
 如果(输出)**输出='\0';
 VA_END_( args );
 返回PC;

格式字符串%f在该代码中似乎根本没有处理,这是否表示sprintf不处理浮点数据显示?

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    下面是代码的变量定义
    Int CurrentOfBottomDevice;
    浮点包装当前;
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    这不是随TI编译器RTS库提供的sprintf的定义。 您已经有了一个大大简化的版本,它放弃了printf的大部分功能,大概是为了保存代码大小。 是的,它看起来根本不支持%f。

    很抱歉,我无法重现使用__FS_utof的错误。

    您使用的编译器版本是什么? (它与CCS版本不同。) 什么命令行选项?
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您是否正在使用TI MSP430编译器?  还是GCC MSP430编译器?

    Steven Yao 说:
    打印功能的代码如下所示:[/QUOT]

    您是如何获得此源代码的?

    谢谢,此致,

    -George

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好,George /考古学家

       感谢您关注我的问题,我正在使用TI编译器,下面是编译器信息

    我发现Sprintf问题的原因是FreeRTOS提供的功能覆盖了TI提供的原始功能,在我从FreeRTOS中删除了该功能后,Sprintf函数只能按预期工作。 但是,对于interger和floart传输问题仍然存在,使用的actualall函数仍然是__fs_utof,而不是__fs_itof。关于 如何获取源代码, 我只需从反汇编窗口复制interger和float类型转换的代码

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    很抱歉,我仍然无法再现使用__FS_utof的错误。  以下是我正在使用的测试用例:

    Int CurrentOfBottomDevice;
    float PackCurrent;
    void func()
    {
    CurrentOfBottomDevice =-100;
    PackCurrent =(FLOF)CurrentOfBottomDevice;
    }
    

    要进一步分析此问题,我需要一个可编译的测试用例,包括完整的命令行选项。  您可以在生成控制台窗口中很容易地找到命令行选项。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好,考古学家:

       下面是我从控制台窗口捕获的命令行信息

    ****配置构建调试项目IntegerOperationTest ****

    "C:\\ti\\ccsv6\\utils\\bin\\gmake "-k all
    '建筑文件:../main.c'
    '调用:MSP430编译器'
    "C:/ti/ccsv6/tools/compiler/ti-CGT-MSP6/CS_base/MSP/cl430" 4.4 -vmsp --abi=eabi -Ooff --use_HW_bumpy=none --include_path="C:/ti/ccsv6/ccsv6/ccsv6/csv_base/MSPw_include"--include_path="C:4.4 /guide_g_g_pre-g_f_guide_f_-f_probsp_-f_-f_f_-comprebsp_-f_-f_f_-probsp_-f_-f_-f_-f_guidexcluse_f_-f_guidex_-f_-f_guidex_-f_g_diag_guidex_-f_g_diex_-f_prox_-f_-f_-prox_guidex_g_  
    "../main.c"第14行:警告#552-D:已设置变量"温度",但从未使用
    "../main.c",第17行:备注#1530-D:(ULP 5.1)检测到除法操作。 建议在运行期间或不使用时将其移至RAM,因为这些都是处理/耗电密集型任务
    "../main.c",第17行:备注#1533-D:(ULP 6.1)检测到在没有硬件乘法器的设备上使用乘法
    "../main.c",第17行:备注#2553-D:(ULP 14.1)"int"类型的数组索引(包括"开始")。 建议使用“unsigned int”
    "../main.c",第17行:备注#2553-D:(ULP 14.1)"int"类型的数组索引(包括"开始")。 建议使用“unsigned int”
    "../main.c",第17行:备注#2553-D:(ULP 14.1)"int"类型的数组索引(涉及"end")。 建议使用“unsigned int”
    "../main.c",第18行:备注#1533-D:(ULP 6.1)检测到在没有硬件乘法器的设备上使用乘法
    "../main.c"第14行:备注#1535-D:(ULP 8.1)变量"开始"用作常量。 建议将变量声明为'static const'或'const'
    "../main.c"第14行:备注#1535-D:(ULP 8.1)变量"end"用作常量。 建议将变量声明为'static const'或'const'
    "../main.c"第15行:备注#1535-D:(ULP 8.1)变量"RTS"用作常量。 建议将变量声明为'static const'或'const'
    '完成的建筑:../主楼C
    ''
    '正在构建目标:IntegerOperationTest.out '
    '调用:MSP430连接器'
    “c:\ti/ccsv6/tools/compiler/ti-CGT-MSP430_Integg2955_--vsp-abi=eabi 4.4 --use_HW_bump=none --advice:power =all -g --definit=__MSP430g2955_--immsp_warning=225 --diag_wheap_sp_up=-up/f-msp_msp_msp_msp_msp_msp_gf_compilerip_m=-f_msp_m/securb=-f_msp_msp_msp_integurb=-f_m/securbip-ccup_gf_m=-ccup_gf_m=-ccup_integurb_m_m_m=-ccup_gf_gf_integurb_m_m_m_m=-ccup_gf_gf_cref="-ccup_cref="-ccup_cref="-ccup_display_m_lip_cref="-f_ 4.4 4.4  
    链接>
    备注#1.0371万-D:(ULP 1.1)检测到未使用低功耗模式状态更改指令
    备注#1.0372万-D:(ULP 4.1)在此项目中检测到未初始化的端口1。 建议初始化所有未使用的端口,以消除未使用的引脚上浪费的电流消耗。
    说明#1.0372万-D:(ULP 4.1)在此项目中检测到未初始化的端口2。 建议初始化所有未使用的端口,以消除未使用的引脚上浪费的电流消耗。
    说明#1.0372万-D:(ULP 4.1)在此项目中检测到未初始化的端口3。 建议初始化所有未使用的端口,以消除未使用的引脚上浪费的电流消耗。
    说明#1.0372万-D:(ULP 4.1)在此项目中检测到未初始化的端口4。 建议初始化所有未使用的端口,以消除未使用的引脚上浪费的电流消耗。
    '完成生成目标:IntegerOperationTest.out '
    ''

    ****构建已完成****

    main.c文件与此类似

    #include <MSP4S.h>


    #define min_TEMP -50
    const unsigned long TemperatureLookUpTable[]={32.95万, 24.77万, 18.85万, 14.41万, 11.13万, 8.643万,6.777万,5.341万,4.247万,3.39万, 2.728万,2.205万,1.796万,1.469万,1.209万, 1万,8313,6940,\
                                                       5827,4911,4160,3536,3020, 2588,2228,1924,1668,1451, 1226,1108,973};

    /*
     主要c
     */
    int main (void){
       WDTCTL = WDTPW | WDTHOLD; //停止看门狗计时器

       Int Start (内部开始)=0,End (结束)=1 ,Temperature (温度);
       Long l SubTemperatureDivision,RTS = 274万;

       lSubTemperatureDivision = 5 *(TemperatureLookUpTable[开始]- RTS)* 6.5536万 /(TemperatureLookUpTable[开始]- TemperatureLookUpTable[结束]);
       温度=(lSubTemperatureDivision >> 16)+启动* 5 + Min_TEMP;

       返回0;
    }

    在反汇编窗口中,我发现了一个名为函数__mspabi_divul的除法操作,用于无符号整数操作,attached是我用于teste2e.ti.com/.../IntegerOperationTest.zip的整个项目

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    这是另一个示例;示例main()中没有浮点运算。  示例main()中的几乎所有算术都将被计算为无符号长型,这可能不是您真正想要的类型。

    第一个操作是(TemperatureLookUpTable[Start]- RTS)。  TemperatureLookUpTable是unsigned long的数组,但RTS的类型为signed long。  C标准要求将RTS中的值转换为unsigned long,并且结果为unsigned long类型。  结果将是一个非常大的无符号数字;我怀疑您需要一个负数。

    同样,5和6.5536万在与结果(TemperatureLookUpTable[Start]- RTS)和(TemperatureLookUpTable[Start]- TemperatureLookUpTable[end])相乘之前都转换为无符号long,显然具有无符号long类型,因此您要除两个无符号长整型值,因此自然会得到无符号长整型除法。

    我建议您将长表达式细分为几个较小的步骤,以便更容易看到涉及的类型。  例如:

    {
    开始时间=0,结束时间=1,温度;
    
    长lSubTemperatureDivision,RTS =274万;
    
    unsigned long T1 = TemperatureLookUpTable[开始]- RTS;/* RTS是类型转换! */
    unsigned long T2 =5 * T1 * 6.5536万;/* 5和6.5536万是转换的类型! */
    unsigned long T3 = TemperatureLookUpTable[Start]- TemperatureLookUpTable[end];
    unsigned long T4 = T2/T3;
    
    lSubTemperatureDivision = T4;/*类型转换! */
    
    长T5 = lSubTemperatureDivision >> 16;
    int T6 =开始* 5;
    长t7 = T5 + T6;/* T6是类型转换的! */
    长T8 = t7 + Min_TEMP /* Min_TEMP的类型已转换! */
    温度= T8;/*类型转换! */
    } 
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    考古学家

       我将数组元素更改为带符号长整型,并将所有操作更改为带符号操作,如下所示

    #include <MSP4S.h>


    #define min_TEMP -50
    Const Long TemperatureLookUpTable[]={3.29500247亿2477.001885亿,144100,111300, 8.643万,6.777万,5.341万,4.247万,3.39万, 2.728万,2.205万,1.796万,1.469万,1.209万, 1万,8313,6940,\
                                                       5827,4911,4160,3536,3020, 2588,2228,1924,1668,1451, 1226,1108,973};

    /*
     主要c
     */
    int main (void){
       WDTCTL = WDTPW | WDTHOLD; //停止看门狗计时器

       Int Start (内部开始)=0,End (结束)=1 ,Temperature (温度);

       Long l SubTemperatureDivision,RTS = 274万;

       长T1 = TemperatureLookUpTable[开始]- RTS;/* RTS类型已转换! */
       长T2 = 5 * T1 * 6.5536万;/* 5和6.5536万是转换的类型! */
       Long T3 = TemperatureLookUpTable[Start]- TemperatureLookUpTable[End];
       长T4 = T2 / T3;

       lSubTemperatureDivision = T4;/*类型转换! */
       长T5 = lSubTemperatureDivision >> 16;
       Int T6 =开始* 5;
       长t7 = T5 + T6;/* T6是转换的类型! */
       Long T8 = t7 + Min_TEMP;/* Min_TEMP为转换类型! */
       温度= T8;/*类型转换! */

       返回0;
    }

       但我发现T2和T4仍然是阳性的,应该是阴性的。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    将6.5536万更改为6.5536万L。
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    你好,考古学家

       我按照您的建议将6.5536万更改为6.5536万L。但T2的值仍为正数

       当我进行单步跟踪时,我可以看到T1是-241.05万,T2是4.01342464亿,虽然很长,但仍然是正数。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    很抱歉,我做的估算不正确。 给定您的最新代码,T1的值为-241.05万。 从算术角度来说,5 * T1 * 6.5536万的值为-78.986万587500,58.75万,对于32位"长"保压而言,该值太大。 这是带符号整数溢出的示例,这是未定义的行为。 您将需要切换到使用"长"算术或重新调整表达式,以避免获得如此大的临时值。 如果您将每个TN变量更改为"long long (长)",则应得到正确答案。