ST意法半导体
直播中

123

11年用户 889经验值
擅长:可编程逻辑
私信 关注
[问答]

cubeide中浮点函数返回值错误是怎么回事?

我在某个.c文件中定义了一个float函数,在函数内设置断点查看return运算结果是正确的,但我在另一个.c文件中引用这个函数给某个变量赋值时,变量的值就错误了。感觉像是cubeide的浮点运算设置问题,已经开启了cubeide的支持浮点运算和sprintf的选项。
这个是浮点函数的运行结果,我在函数内设置断点查看,计算运行是正确的Name : valueDetails:4.37491322Default:4.37491322Decimal:1082916682Hex:0x408bff4aBinary:1000000100010111111111101001010Octal:010042777512这个是引用函数赋值后得到的错误结果,通过引用函数赋值之后得到的变量直接飞了,引用函数后得到的结果是错误的Name : mid_angleDetails:1.08291674e+009Default:1.08291674e+009Decimal:1317083135Hex:0x4e8117ffBinary:1001110100000010001011111111111Octal:011640213777我确保函数类型和赋值的类型一致,都是float,且代码在keil中编译运行没问题,在cubeide中未改动代码,但函数传递值时就错了,不知道咋解决floatgetAngle11(void)
{
float angle_data,d_angle,value;angle_data = I2C_getRawCount();// tracking the number of rotations // in order to expand angle range form [0,2PI] to basically infinityd_angle = angle_data - angle_data_prev;// if overflow happened track it as full rotationif(fabs(d_angle) > (0.8*cpr) ) full_rotation_offset += d_angle > 0 ? -_2PI : _2PI; // save the current angle value for the next steps// in order to know if overflow happenedangle_data_prev = angle_data;// return the full angle // (number of full rotations)*2PI + current sensor angle value=(full_rotation_offset + ( angle_data / (float)cpr) * _2PI);return  value ;}引用时是这样的volatilefloat mid_angle,end_angle;mid_angle=getAngle11();感觉是cubeide的浮点设置问题,我之前开启了支持浮点数编译和打印的设置,不知道还有啥浮点数问题

回帖(2)

武妹

2025-3-13 16:15:58
基本可以肯定函数返回做为结果赋值同类型变量是没啥问题的。
之前用过类似操作,刚才也特意测试了下。
while (1)
{
/ USER CODE END WHILE /
/ USER CODE BEGIN 3 /
if(Flag_ADC)
{
  Flag_ADC=0x00;  Vrefint = CalculateVREF(AdcResult_vref);          Vbat = CalculateVBAT(AdcResult_vbat) ;}}
float CalculateVREF(uint32_t vref)
{
return (float )( (vref/4095.)*3.3);}
float CalculateVBAT(uint32_t vbat)
{
return  (float )( ((vbat)/4095.)*9.9);}
举报

刘军

2025-3-17 18:06:35

在CubeIDE中遇到浮点函数返回值错误的问题,可能是由于以下原因导致的。以下是逐步排查和解决方案:


1. 检查浮点ABI和编译选项一致性



  • 确认所有文件使用相同的浮点设置

    在项目属性中,进入 C/C++ Build > Settings > Tool Settings,检查以下选项是否一致:

    • Miscellaneous > Other flags:确保包含 -mfloat-abi=hard(硬件浮点)或 -mfloat-abi=softfp(兼容软浮点)。

    • Floating Point:选择正确的FPU类型(如 fpv4-sp-d16 适用于Cortex-M4)。

    • 确保所有源文件使用相同的配置,避免混合使用不同的ABI。



2. 验证函数原型声明



  • 在调用方正确声明函数

    在调用函数的.c文件中,必须包含正确的函数原型。例如:
    // 在头文件或调用方顶部声明
    extern float your_function(float arg);


    • 避免隐式声明:未声明函数可能导致编译器误认为返回类型为int,从而错误解析返回值。



3. 确认FPU已正确初始化



  • 检查启动代码

    在STM32的启动文件(如 startup_stm32f4xx.s)中,确保在复位后启用FPU:
    ; 启用FPU(Cortex-M4示例)
    LDR.W R0, =0xE000ED88
    LDR R1, [R0]
    ORR R1, R1, #(0xF << 20) ; 设置CP10和CP11为全访问
    STR R1, [R0]
    DSB
    ISB


    • 如果没有这段代码,添加它或确认项目配置正确。



4. 确保栈对齐正确



  • 8字节栈对齐

    ARM FPU要求栈在函数调用时8字节对齐。在启动代码中,初始栈指针(SP)应为8的倍数。例如:
    ; 启动文件中的栈定义(通常自动对齐)
    __initial_sp    EQU     0x20020000  ; 确认地址是8的倍数


5. 排除优化干扰



  • 临时关闭优化

    在项目属性的 C/C++ Build > Settings > Optimization 中,设置优化级别为 -O0(无优化),重新编译测试。


6. 工具链更新



  • 更新ARM GCC工具链

    进入 Help > STM32CubeIDE Firmware Updater,检查是否有编译器更新。或手动下载最新工具链并替换。


7. 调试寄存器传递



  • 查看汇编代码

    在调试模式下,进入反汇编视图(Window > Show View > Disassembly),观察函数返回时是否将结果放入 s0 寄存器(单精度),而调用方是否从 s0 读取。若使用硬件浮点但调用方从通用寄存器(如 r0)读取,说明ABI不匹配。


8. 检查变量类型和赋值



  • 显式类型转换

    确保接收返回值的变量类型正确。例如:
    float result = your_function(); // 正确类型
    // 而非 double result = your_function(); // 可能导致错误扩展


示例解决方案




  1. 统一编译选项

    在项目属性的 MCU Settings 中,启用FPU并选择正确的ABI:


    -mcpu=cortex-m4 -mfloat-abi=hard -mfpu=fpv4-sp-d16



  2. 添加FPU初始化代码

    main() 函数开头添加以下代码(如果启动文件未启用FPU):


    #include 
    void enable_fpu(void) {
    SCB->CPACR |= (0xF << 20); // 启用CP10和CP11
    __DSB();
    __ISB();
    }
    int main(void) {
    enable_fpu();
    // ...其他代码
    }



  3. 验证函数声明

    在头文件 your_header.h 中声明函数:


    #ifdef __cplusplus
    extern "C" {
    #endif
    float your_function(float arg);
    #ifdef __cplusplus
    }
    #endif



最终验证



  • 通过内存查看器检查

    在赋值后的变量地址处,查看其十六进制值是否与函数返回的 0x408BFF4A(对应4.37491322)一致。如果不同,则说明传递过程中发生了错误解释。


通过以上步骤,应能解决CubeIDE中浮点返回值错误的问题。如果问题依旧,建议检查硬件连接或尝试简化代码示例以进一步隔离问题。

举报

更多回帖

发帖
×
20
完善资料,
赚取积分