Search code examples
cembeddedstellaris

How to convert uint32_t to double or float and print?


I'm using an analog to digital converter to read a voltage value from 0 to 3.3V. The ADC gives an output from 0x00 to 0x0FFF (0 to 4095). I want to print the voltage reading with two decimal places. I have read a number of answers but nothing I've tried has worked. Here's my code:

uint32_t pui32ADC0Value[1]; // ADC0 data value
double D0v;                 // Decimal value

// Read value from ADC
ADCSequenceDataGet(ADC0_BASE, 3, pui32ADC0Value);

// Convert to decimal
D0v = (double)pui32ADC0Value[0] / 4095 * 3.3;

// Print to console
UART0printf("\n\r> D0 = %.2d V", D0v);

The output I get is: D0 = ERROR2d V

pui32ADC0Value prints without any problems and gives the expected values, so I know that it is working.

What does this error mean?

NOTE: UART0printf is a pre-defined UART function on the TIVA TM4C microcontroller I am using.

UPDATE: I wrongly assumed UART0printf is identical to printf, as I have used it before with %u, %s, and %x. However for numbers it only supports %c, %i, and %u. I am re-working my code and will update if I don't get anywhere.

UPDATE 2: Could I do something like this? I know it will round incorrectly...

uint32_t pui32ADC0Value[1]; // ADC0 data value
uint32_t D0v[2];                 // Decimal value

// Read value from ADC
ADCSequenceDataGet(ADC0_BASE, 3, pui32ADC0Value);

// Convert to decimal
for ( int i = 0; i <= 2; i++){
    D0v[i] = (pui32ADC0Value[0]/10^i) / 4096 * 3.3;
}

// Display the AIN0 (PE0) digital value on the console.
UART0printf("\n\r> D0 = %d.%d%d V", D0v[0],D0v[1],D0v[2]);

Solution

  • If this function works printf like:

    UART0printf("\n\r> D0 = %.2f V\n", D0v);
    

    Also your code may work a little faster if you use:

    D0v = (double)pui32ADC0Value[0] * (3.3 / 4095);
    

    The compiler will precompute 3.3 / 4095 and will do a single floating point multiply operation. Otherwise it's possible that the division is done first (which usually takes much more CPU cycles than a multiply) and then the multiply * 3.3 will be done.

    Also since you seems to need only 2 digit precision, you could use float (single precision) instead of double. It may execute faster (but it's possible to be even slower), this depends on the platform.

    Update for UPDATE2 in the question:

    Try this:

    uint32_t pui32ADC0Value[1]; // ADC0 data value
    uint32_t D0v;               // Decimal value
    
    // Read value from ADC
    ADCSequenceDataGet(ADC0_BASE, 3, pui32ADC0Value);
    
    // Convert to millivolts
    D0v = pui32ADC0Value[0] * (3300.0 / 4095);
    
    // Display the AIN0 (PE0) digital value on the console.
    UART0printf("\n\r> D0 = %d mV", D0v); // If it's OK for you to display in mV
    UART0printf("\n\r> D0 = %d.%03d V", D0v / 1000, D0v % 1000); // Print in V