views:

208

answers:

3

I am very new at C programming and I am working on a firmware application for my MCU. This method was working fine when I was using the KEIL compiler (Big Endian) but when I switched to the SDCC compiler (Little Endian) it is not working properly. Can someone please explain what I am doing wrong???

The target device is a Silicon Labs C8051F320 which is based on the 8051 architecture.

unsigned **int** MotorSteps  = 0;     //"Global" variables
unsigned **int** MotorSpeed  = 0;
bit RampUp()
{
    float t = 0;
    t = MotorSteps;
    if ( t < 51 )
    {
        t = (1-((50 - t)/50))*15;   
        t = (t * t);        
        MotorSpeed = 100 + t;           
        return 0;
    }
    else return 1;
}

ADDED: First, I now changed the MotorSteps and MotorSpeed to be unsigned ints. In my debugger, for some reason, if I set a break point at the if-statement line, on the first entrance of this function MotorSteps = 00, so t should get assigned to 0 also but the debugger shows that t=0.031497 (decimal). If I switch the debugger to display in Hex, t = 0x3d010300. It's like t is never getting assigned...

A: 

why did you switch from BE to LE? What is architecture of target device? And by the way what is it?

Anyway, to question. I am pretty sure that problem comes when conversion takes place. Try to trace your code line by line with calculator and try to find when the numbers become unexpected.

Andrey
I was originally using the KEIL compiler but I reached the limitations of the free version and didn't want to pay for the license so I switched to SDCC which is free and unlimitied... but opposite Endian-ness.
Jordan S
+2  A: 

If MotorSteps = 49 then

(50 - 49) / 50 = 0.02

next

(1 - 0.02) = 0.98

and

0.98 * 15 = 14.7

Squaring this value would set t as

t = 14.7 * 14.7 = 216.09

Finally, the implicit conversion from the float back to the unsigned char overflows the MotorSpeed variable:

MotorSpeed = 100 + 216.09...// Implicitly converts the float t to an unsigned char of 216

The sum of 100 + 216 = 316, of course, overflows an unsigned char and you end up with 316-256 = 60.

This is probably unwanted behavior regardless of the compiler.

semaj
Actually, assigning a float (or double) to an integral type when the value of the float is outside of the range of the integral type results in undefined behavior, not well-defined modular overflow as you might expect from an unsigned int. So the result may not be 60, and this may account for why this behaves differently in different compilers.
Tyler McHenry
A: 

It's like t is never getting assigned...

There is no reason for the compiler to assign a value of 0 to t in the declaration

float t = 0;

since it immediately gets assigned to MotorSteps on the next line. My guess is the optimizer is ignoring the assignment to zero in the declaration and the debugger is simply displaying the uninitialized value for the memory where t is located on the stack.

You might want to consider getting rid of the formula altogether and using a look up table for the ramp values. It looks like there are only 51 values so the table would be relatively small. The code to look up a value would be much quicker than using the floating point libraries on an 8051.

#define NUM_RAMP_STEPS 51
unsigned char MotorSteps = 0;     //"Global" variables
unsigned char MotorSpeed = 0;
const unsigned char RampTable[NUM_RAMP_STEPS] = {...appropriate values...};
bit RampUp()
{
    if ( MotorSteps < NUM_RAMP_STEPS )
    {
        MotorSpeed = RampTable[MotorSteps];           
        return 0;
    }
    else return 1;
}

At least you could test your integer rather than the float to avoid the floating point libraries unless you need them...

unsigned **int** MotorSteps  = 0;     //"Global" variables
unsigned **int** MotorSpeed  = 0;
bit RampUp()
{
    if ( MotorSteps < 51 )
    {
        float t = MotorSteps;
        t = (1-((50 - t)/50))*15;   
        t = (t * t);        
        MotorSpeed = 100 + t;           
        return 0;
    }
    else return 1;
}
semaj