Question

I am working on a small electronics project at home using a PIC microcontroller 18F which I am programming with HiTech C18 that is going to be used for digital control of a bench power supply.

I have run into a problem which is that I have a floating point number in a variable lets say for example 12.34 and need to split it out into 4 variables holding each individual number so i get Char1 = 1, Char2=2 etc etc for display on a 4-way seven segment LED display. The number will always be rounded to 2 decimal places so there shouldnt be a need to track the location of the decimal point.

I am trying to avoid any rounding where possible above 2 decimal places as the displays are giving measurements of voltage/current and this would affect the accuracy of the readouts.

Any advice on how to get this split would be greatly appreciated.

Thanks

Was it helpful?

Solution

Use sprintf to put the value into a character array. And then pick out the digits from there.

You could convert the floating point value directly to text. Or you could multiply by 100, truncate or round to int, and then convert that to text.

OTHER TIPS

Convert to int and then to a string.

float x;
int i = x*100;
// or i = x*100.0f + 0.5f is round to nearest desired.
if ((i < 0) || (i > 9999)) Handle_RangeProblem();
char buf[5];
sprintf(buf, "%04d", i);

In embedded applications, many compilers use the fixed format string to determine which parts of the large printf() code will be needed. If code is all ready using "%f" else where, then a direct sprintf("%f") here is not an issue. Otherwise using %04d" could result in significant space savings.

Floating point numbers are stored in binary format comprised of a sign bit, mantissa, and exponent. A floating point number may not exactly match a given decimal representation (because of the different base-10 for decimal from the base-2 storage of floating point). Conversion of a floating point number to a decimal representation is a problem often assigned in beginning programming courses.

Since are only interested in two decimal places, and a limited range of values, you could use a fixed point representation of your value. This would reduce the problem from conversion of a floating point to decimal into conversion of integer to decimal.

long
longround( float f )
{
    long  x;
    x = (long)((f*100)+.5); //round least significant digit
    return(x);
}

char*
long2char( char ca[], long x )
{
    int pos=0;
    char sign = '+';
    ca[pos] = '0';
    long v = x;
    if( v<0 ) {
        sign = '-';
        v = -v;
    }
    for( pos=0; v>0; ++pos )
    {
        ca[pos] = (v%10)+'0';
        v = v/10;
    }
    ca[pos++] = sign;
    ca[pos] = '\0'; //null-terminate char array
    //reverse string - left as exercise for OP
    return(ca);
}

If you have a problem where the largest value could exceed the range of values supported by long integer on your system, then you would need to modify the above solution.

Given the stated stability of your decimal point: simply sprintf() float into a buffer with appropriate format specifier, then you have your 4 values in a string easily extracted into what ever type you need them to be in...

Example

float num = 12.1234456;
char  buf[6];

int main(void)
{
    char a[2], b[2], c[2], d[2];
    int  x, y, z, w;    

    sprintf(buf, "%0.2f", num);//capture numeric into string  
    //split string into individual values   (null terminate)
    a[0] = buf[0]; a[1]=0;
    b[0] = buf[1]; b[1]=0;
    //skip decimal point
    c[0] = buf[3]; c[1]=0;
    d[0] = buf[4]; d[1]=0;  

    //convert back into numeric discretes if necessary
    x = atoi(a);
    y = atoi(b);
    z = atoi(c);
    w = atoi(d);
}  

There are certainly more elegant ways, but this will work...

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top