这些小活动你都参加了吗?快来围观一下吧!>>
电子产品世界 » 论坛首页 » 综合技术 » 基础知识 » 我踩过的那些坑-幂函数POW不包含math.h竟然不报错

共1条 1/1 1 跳转至

我踩过的那些坑-幂函数POW不包含math.h竟然不报错

菜鸟
2025-10-21 15:07:04     打赏

最近使用keil5和stm32f103cb在调试一个BMI088 IMU芯片时,读出来三轴加速度数据后要转换成相应的加速度值,使用了以下代码:

	        #define GRAVITY_EARTH  (9.80665f)//地球重力加速度值,常数
        //该函数将整型数据转成相应的浮点加速度数据
        static float lsb_to_mps2(int16_t val, int8_t g_range, uint8_t bit_width)
        {
            double power = 2;
        
            float half_scale = (float)((pow((double)power, (double)bit_width) / 2.0f));
        
            return (GRAVITY_EARTH * val * g_range) / half_scale;
        }
        
        //以下是main函数代码
        main()
        {
             ......	
             BMI088a_Reset();
             BMI088a_Init();
             BMI088a_GetData(&bmi08_accel);//读取三轴加速度值
             
             x = lsb_to_mps2(bmi08_accel.x, 6, 16);//读取X轴数据并转成加速度值
             y = lsb_to_mps2(bmi08_accel.y, 6, 16);//读取Y轴数据并转成加速度值
             z = lsb_to_mps2(bmi08_accel.z, 6, 16);//读取Z轴数据并转成加速度值	
             usb_printf("%5d, %5d, %5d, %4.2f, %4.2f, %4.2f\n",bmi08_accel.x,bmi08_accel.y,bmi08_accel.z,x,y,z);
             usb_printf("\r\n\r\n");//插入换行
	}

因为代码是直接从别的工程拷贝过来的,就直接使用了,经过调试发现,串口助手能收到原始加速度bmi08_accel.x,bmi08_accel.y,bmi08_accel.z的值,但浮点化的加速度值x,y,z全是0。

后来经过单步调试,发现函数lsb_to_mps2第二句half_scale的值是0,如下图所示。

image.png

image.png

最后定位到是由于没有包含math.h头文件,包含后就好了。另外经验证,和勾选microlib也没关系。

然后,我对比了一下正确的map文件和错误的map文件。左侧是包含math.h的文件,右侧是没有包含math.h的文件。

image.png

可以看到左侧是引用了__aeabi_d2f和__aeabi_ddiv等double除法函数和double转float函数,而右侧没有,只引用了浮点乘法fmul和除法fdiv。

经过查询资料https://bbs.21ic.com/icview-3447122-1-1.html,ARM Cortex-M处理器中计算浮点数的方式有软件和硬件两种。对于不带 FPU 的处理器,ARM提供了一个「浮点支持软件库」用于计算浮点数:fplib。fplib提供的 API 以__aeabi开头,比如:

__aeabi_fadd:计算两个float型浮点数(float4个字节,32位)

__aeabi_dadd:计算两个double型浮点数(double8个字节,64位)

__aeabi_f2dfloat型转为double

__aeabi_d2fdouble型转为float

估计就是double处理时出错引起的计算错误。

但为啥包含math.h就引用了,没有包含math.h就不引用就不得而知了,可能编译器哪些选项对这个起作用吧。

关键很最奇怪的是,没有包含math.h竟然没有报错,连报警告都没有,让人很费解。



共1条 1/1 1 跳转至

回复

匿名不能发帖!请先 [ 登陆 注册 ]