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.

TMS320F28335: Use double for computation

Part Number: TMS320F28335

I am recieving a float number from CAN bus, but the nubmer is smaller than F_MIN, about 1e-42, but as soon as I assign it to a long double or a float, it becomes 0. So I tried to use the following function to convert, but still the same result. 

My compiler is very old, 6.1, and I use the FPU lib. Any ideas?

Thanks,

Nelson


long double f32bits_to_double(Uint32 bits)
{
    Uint32 sign = bits >> 31;
    Uint32 expo = (bits >> 23) & 0xFFu;
    Uint32 mant =  bits & 0x7FFFFFu;
    long double v;
    if (expo == 0u) {
        /* zero or subnormal: value = mant * 2^-149 */
        v = ldexp((long double)mant, -149);
    } else if (expo == 0xFFu) {
        v = mant ? NAN : INFINITY;
    } else {
        /* normal: value = (1.mant) * 2^(expo-127) */
        v = ldexp((long double)(mant | 0x800000u), (int)expo - 127 - 23);
    }
    return sign ? -v : v;
}

 

  • Nelson,

    Not sure whether this is an artifact of the compiler. But have you tried adding the --double_support compiler option?

  • Hi Sira,

    I added it to the project file, it seems like the .out file changed a bit. But the result is the same. It does seem to have something to do with the compiler. 

    long double temp_ld1, temp_ld2;

    temp_ld1 = (long double)-1.339395E-60;

    The compiler gave me error, saying it out of the range of float. It is kind of strange to me, any idea why?

    Regards,

    Nelson

  • Hi Sira,

    I added it to the project file, it seems like the .out file changed a bit. But the result is the same. It does seem to have something to do with the compiler. 

    long double temp_ld1, temp_ld2;

    temp_ld1 = (long double)-1.339395E-60;

    The compiler gave me error, saying it out of the range of float. It is kind of strange to me, any idea why?

    Regards,

    Nelson

  • Nelson,

    Is your output format COFF?

    In TI C2000 COFF, float and double are both 32-bit (single precision float), while long double is 64-bit (double-precision float). Since you are declaring your variables as a long double, even if you're using COFF, it should be a 64-bit double-precision float emulated in software.

    So I'm thinking something is happening with the compiler. Let me check with a compiler expert.

    Thanks,

    Sira

  • Feedback from our compiler expert -  the error is correct. C standard interprets a float constant as a "double" which is only 32bits. for their use case they need to add the "L" suffix.  -1.39E-60L

  • I changed the function to the following, it seems to be working.

    /* 2^-149 as an exact 64-bit long double (smallest float subnormal step) */
    static const long double TWO_POW_M149 = 1.4012984643248171e-45L;

    /* Convert the 32-bit IEEE-754 single-precision bit pattern from the CAN
    frame into a double, handling subnormals correctly (no FPU32 flush). */
    long double f32bits_to_double(Uint32 bits)
    {
    Uint32 sign = bits >> 31;
    Uint32 expo = (bits >> 23) & 0xFFu;
    Uint32 mant = bits & 0x7FFFFFu;
    if (expo == 0u) {
    /* zero or subnormal: value = mant * 2^-149, done in 64-bit -> no flush */
    long double v = (long double)mant * TWO_POW_M149;
    return sign ? -v : v;
    } else if (expo == 0xFFu) {
    return (long double)0; /* inf/nan: handle as your app needs */
    } else {
    /* normal number: plain conversion is safe (normals don't flush) */
    float f;
    *(Uint32 *)&f = bits;
    return (long double)f;
    }
    }

    Thanks,

    Nelson