|
|
View previous topic :: View next topic |
Author |
Message |
CCS newby
Joined: 27 May 2011 Posts: 5
|
Printf not printing floating point numbers correctly. |
Posted: Fri May 27, 2011 7:54 am |
|
|
I am using printf in a function off main to printf a floating point variable. This does not work work correctly and always prints the variable as 0.00. If I insert a line into the main function to printf a floating point variable this then works and also makes the printf in the other function work correctly. Any ideas what the problem is? Is this a compiler bug? |
|
|
temtronic
Joined: 01 Jul 2010 Posts: 9226 Location: Greensville,Ontario
|
|
Posted: Fri May 27, 2011 8:50 am |
|
|
Sounds like you have a 'local' variable in the printf function and not a 'global' one.
We'd need to see your code to be sure.
You could look at any of the examples that CCS supplies in the 'examples' folder to see how it can be done.... |
|
|
CCS newby
Joined: 27 May 2011 Posts: 5
|
|
Posted: Wed Jun 01, 2011 3:47 am |
|
|
Thanks for the repsonse.
I am using this line in a function to print a value:
printf("tempf= %f",tempf);
The variable is defined in the function thus: float tempf;
This will not print the varaible correctly until I add a line such as this to the main function: printf("Hello %lf",1.0f);
A strange problem..! |
|
|
SherpaDoug
Joined: 07 Sep 2003 Posts: 1640 Location: Cape Cod Mass USA
|
|
Posted: Wed Jun 01, 2011 5:35 am |
|
|
Send us a whole compilable program that shows the problem, preferably a very short one. Also tell us your compiler version. _________________ The search for better is endless. Instead simply find very good and get the job done. |
|
|
ERICOO
Joined: 13 Jun 2011 Posts: 14 Location: NIGERIA
|
PRINTF NOT PRINTING FLOATING POINT NUMBERS CORRECTLY |
Posted: Tue Jun 28, 2011 4:52 am |
|
|
According to temtronic it would be best if you send your code.
however you be sure that all variables you using for your formular are globally declared as float or if you are simply wanting to display an integer as float e.g you want display 12 as 12.00
first store 12 in a float type variable and display using the printf format. see below
float newby = 12.00 (instead of 12)
.
.
.
.
printf(lcd_putc "\f%2.2f", newby)
.
.
} |
|
|
brock
Joined: 29 Jun 2011 Posts: 8
|
PRINTF NOT PRINTING FLOATING POINT NUMBERS CORRECTLY |
Posted: Wed Jun 29, 2011 9:20 am |
|
|
All,
I am having the exact issue that CCS newby is having except that putting a print in main doesn't get me out of it, but insertion of a print in another function does.
I even tried the following:
Code: |
temp = adc_sample(i);
printf(" PV: ADC: %f\r",temp);
printf(" PV: ADC: %f\r",5.27);
printf(" PV: ADC: %f\r",temp);
temp = 1.234;
printf(" PV: ADC: %f\r",temp);
|
and all printed 0.000.
When I inserted a printf elsewhere in the program, it works perfectly.
There is some sort of compiler bug, I think.
I'll submit the entire code post if requested. |
|
|
CCS newby
Joined: 27 May 2011 Posts: 5
|
|
Posted: Wed Jun 29, 2011 9:33 am |
|
|
I also managed to get rid of the issue by putting more spaces before the %f in between the quotes on the relevant printfs. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Jun 29, 2011 11:54 am |
|
|
Post your PIC, #fuses and compiler version. |
|
|
brock
Joined: 29 Jun 2011 Posts: 8
|
PRINTF NOT PRINTING FLOATING POINT NUMBERS CORRECTLY |
Posted: Wed Jun 29, 2011 1:42 pm |
|
|
#FUSES INTRC,NOWDT,PUT,MCLR,NOPROTECT,NOCPD,BROWNOUT,NOIESO,NOFCMEN,NOLVP
Compiler Version: 4.122 |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Jun 29, 2011 1:54 pm |
|
|
But what PIC are you using ? No one in this thread has ever stated
what PIC they are using. |
|
|
brock
Joined: 29 Jun 2011 Posts: 8
|
PRINTF NOT PRINTING FLOATING POINT NUMBERS CORRECTLY |
Posted: Wed Jun 29, 2011 2:50 pm |
|
|
Sorry - I am using a 16F887. |
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Jun 29, 2011 3:10 pm |
|
|
I made a test program and it works fine. I ran it in MPLAB simulator
(MPLAB vs. 8.70) and compiled it with CCS compiler vs. 4.122.
Here's the result in the Output Window:
Quote: |
PV: ADC: 5.67
PV: ADC: 5.27
PV: ADC: 5.67
PV: ADC: 1.23
|
I also ran it in hardware with a 16F887 on a PicDem2-Plus board and
got the same result. I only changed the '\r' at the end of each line
into "\n\r" so it would go to a newline in the TeraTerm window.
Here's the test program:
Code: |
#include <16F887.H>
#FUSES INTRC,NOWDT,PUT,MCLR,NOPROTECT,NOCPD,BROWNOUT,NOIESO,NOFCMEN,NOLVP
#use delay(clock = 4000000)
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7, ERRORS)
float adc_sample(int8 ch)
{
return(5.678);
}
//======================================
void main()
{
int8 i;
float temp;
i = 0;
temp = adc_sample(i);
printf(" PV: ADC: %f\r",temp);
printf(" PV: ADC: %f\r",5.27);
printf(" PV: ADC: %f\r",temp);
temp = 1.234;
printf(" PV: ADC: %f\r",temp);
while(1);
} |
|
|
|
brock
Joined: 29 Jun 2011 Posts: 8
|
PRINTF NOT PRINTING FLOATING POINT NUMBERS CORRECTLY |
Posted: Wed Jun 29, 2011 3:52 pm |
|
|
i can make it work too...if I add another printf in a completely different routine.
Here's the complete code file. It should work as-is, but fail if the printf (search for CCSINFO) is commented out.
Code: |
#include <16F887.h>
#include <stdlib.h>
#include <ctype.h>
#include <stdio.h>
#FUSES INTRC,NOWDT,PUT,MCLR,NOPROTECT,NOCPD,BROWNOUT,NOIESO,NOFCMEN,NOLVP
// Setup Clock
#use delay(internal=8M)
// Setup the Serial Port to (9600,8,N,1)
#use rs232(baud=9600,BITS=8,PARITY=N,STOP=1,xmit=PIN_C6,rcv=PIN_C7,)
// Register Map
#byte porta = 0x05
#byte portb = 0x06
#byte portc = 0x07
#byte portd = 0x08
#byte porte = 0x09
#byte pir2 = 0x0d
#byte sspbuf = 0x13
#byte sspcon = 0x14
#byte adresh = 0x1e
#byte adcon0 = 0x1f
#byte trisa = 0x85
#byte trisb = 0x86
#byte trisc = 0x87
#byte trisd = 0x88
#byte pie1 = 0x8c
#byte pie2 = 0x8d
#byte sspcon2 = 0x91
#byte sspstat = 0x94
#byte wpub = 0x95
#byte adresl = 0x9e
#byte adcon1 = 0x9f
#byte cm2con0 = 0x108
#byte eedat = 0x10c
#byte eeadr = 0x10d
#byte eedath = 0x10e
#byte eedatl = 0x10f
#byte anselh = 0x189
#byte eecon1 = 0x18c
#byte eecon2 = 0x18d
#bit C2OE = 0x108.5
#DEFINE POT_STEPS 1024
#DEFINE UPPER_CAL_LIMIT POT_STEPS - 1
#DEFINE LOWER_CAL_LIMIT 0x0000
#DEFINE NOP 0x0000
#DEFINE WRITE_RDAC_REGISTER 0x0400
#DEFINE READ_RDAC_REGISTER 0x0800
#DEFINE STORE_RDAC_SETTING_TO_TP0 0x0c00
#DEFINE REFRESH_RDAC_FROM_LAST_TP 0x1000
#DEFINE REFRESH_RDAC_FROM_SPEC_TP 0x1400
#DEFINE READ_LAST_TP_ADDR_STORED 0x1800
#DEFINE WRITE_CONTROL_REGISTER 0x1c00
#DEFINE READ_CONTROL_REGISTER 0x2000
#DEFINE PLACE_DEVICE_IN_SHUTDOWN 0x2400
#DEFINE POT_AVERAGING_COUNT 20
#DEFINE POT_SETTLE_TIME_MS 2
#DEFINE POT_COUNT 1
#DEFINE POT_PARAMETERS 3
#DEFINE TOTAL_POT_PARAMETER_COUNT POT_PARAMETERS*POT_COUNT
#DEFINE CAL_PRESENT_ADDRESS 0x0
#DEFINE POT_CAL_TABLE_BASE_ADDRESS 0x1
#DEFINE CAL_FLAG 0xf0
const float nominal_rail_voltages[POT_COUNT] =
{
0.9 // Nominal Voltage Targets
};
float pot_cal_table[TOTAL_POT_PARAMETER_COUNT];
void init_io()
{
adcon0 &= 0xfe;
trisb = 0xff;
anselh |= 0x01;
adcon0 |= 0x80;
adcon1 |= 0x90;
wpub &= 0x00;
adcon0 |= 0x01;
trisc &= 0xD7;
sspstat = 0x80;
sspcon = 0x22;
sspcon2 = 0x0;
portd |= 0x10;
trisd = 0xef;
}
float adc_sample(int target_pot)
{
int i,adc_mask;
float v8,sum8;
sum8 = 0;
adcon0 &= 0xc3;
adc_mask = (target_pot + 1) * 32;
adcon0 |= adc_mask;
delay_ms(POT_SETTLE_TIME_MS);
for (i = 0; i < POT_AVERAGING_COUNT; i++)
{
adcon0 |= 0x02;
while (adcon0 & 0x02) {}
v8 = (float) (adresh * 256 + adresl + 2) * 4.096 / 1024;
sum8 = sum8 + v8; }
sum8 = sum8 / i;
printf(" ADCS: %4.3f\r",sum8); // CCSINFO: IF I COMMENT THIS PRINT OUT, NO FLOATING POINT printf WORKs
return sum8;
}
long set_pot(long write_val)
{
int write_valh, write_vall;
int return_valueh,return_valuel;
long return_value;
// printf("Set Pot: WV: %04Lx\r",write_val);
write_valh = write_val >> 8;
write_vall = write_val & 0x00ff;
portd &= 0xef; // Drop the CS
sspbuf = write_valh; // Ship the data
delay_us(100); // Manditory delay
return_valueh = sspbuf; // Clear the input buffer and save-off the return string.
sspbuf = write_vall; // Ship the data
delay_us(100); // Manditory delay
portd |= 0x10; // Raise CS
return_valuel = sspbuf; // Clear the input buffer and save-off the return string
return_value = return_valueh * 256 + return_valuel;
delay_ms(20); // Make sure we have cleared everything out
return return_value;
}
void increment_pot(long steps)
{
long return_value, new_set_value;
return_value = set_pot(READ_RDAC_REGISTER);
return_value = set_pot(READ_RDAC_REGISTER);
new_set_value = return_value + steps;
new_set_value |= 0x0400; // Set the write control bit
// printf("RV: %04Lx, Steps: %04Lx, NV: %04Lx\r",return_value, steps, new_set_value);
return_value = set_pot(new_set_value);
}
void decrement_pot(long steps)
{
long return_value, new_set_value;
return_value = set_pot(READ_RDAC_REGISTER);
return_value = set_pot(READ_RDAC_REGISTER);
new_set_value = return_value - steps;
new_set_value |= 0x0400; // Set the write control bit
// printf("Pot: RV: %04Lx, Steps: %04Lx, NV: %04Lx\r",return_value, steps, new_set_value);
return_value = set_pot(new_set_value);
}
void set_pot_to_voltage(int pot_address, float target_voltage) // Routine sets a pot to a voltage
{
float actual_voltage;
float error_high, error_low;
float offset_voltage,cal_divisor;
int convergence_error;
long steps;
actual_voltage = adc_sample(pot_address);
if (target_voltage > actual_voltage)
{
offset_voltage = (target_voltage - actual_voltage);
cal_divisor = ((pot_cal_table[pot_address] - pot_cal_table[pot_address + 1])/POT_STEPS);
error_high = (float)(offset_voltage/cal_divisor);
steps = (long) error_high;
printf("Note: In > Actual, Steps: 0x%04lx %Ld\r",steps,steps);
increment_pot(steps);
actual_voltage = adc_sample(pot_address);
if(target_voltage > actual_voltage)
{
while (target_voltage > actual_voltage)
{
increment_pot(1);
actual_voltage = adc_sample(pot_address);
}
error_high = actual_voltage - target_voltage;
decrement_pot(1);
actual_voltage = adc_sample(pot_address);
error_low = target_voltage - actual_voltage;
if (error_high < error_low)
{
increment_pot(1);
}
}
else if (target_voltage < actual_voltage)
{
while (target_voltage < actual_voltage)
{
decrement_pot(1);
actual_voltage = adc_sample(pot_address);
}
error_low = target_voltage - actual_voltage;
increment_pot(1);
actual_voltage = adc_sample(pot_address);
error_high = actual_voltage - target_voltage;
if (error_low < error_high)
{
decrement_pot(1);
}
}
else
{
convergence_error = 1;
}
}
else if (target_voltage < actual_voltage)
{
offset_voltage = (actual_voltage - target_voltage);
cal_divisor = ((pot_cal_table[pot_address] - pot_cal_table[pot_address + 1])/POT_STEPS);
error_low = (float)(offset_voltage/cal_divisor);
steps = (long) error_low;
printf("Note: Actual > In, Steps: 0x%04lx %Ld\r",steps,steps);
decrement_pot(steps);
actual_voltage = adc_sample(pot_address);
if(target_voltage > actual_voltage)
{
while (target_voltage > actual_voltage)
{
increment_pot(1);
actual_voltage = adc_sample(pot_address);
}
error_high = actual_voltage - target_voltage;
decrement_pot(1);
actual_voltage = adc_sample(pot_address);
error_low = target_voltage - actual_voltage;
if (error_high < error_low)
{
increment_pot(1);
}
}
else if (target_voltage < actual_voltage)
{
while (target_voltage < actual_voltage)
{
decrement_pot(1);
actual_voltage = adc_sample(pot_address);
}
error_low = target_voltage - actual_voltage;
increment_pot(1);
actual_voltage = adc_sample(pot_address);
error_high = actual_voltage - target_voltage;
if (error_low < error_high)
{
decrement_pot(1);
}
}
else
{
convergence_error = 1;
}
}
if (convergence_error == 1)
{
printf("ERROR!\r");
}
}
void init_pots() // Routine opens the POTs RDAC register for writing
{
long return_value;
int i;
// printf("Init Pots\r");
// Read the value of the control register - Command 8
return_value = set_pot(READ_CONTROL_REGISTER);
return_value = set_pot(READ_CONTROL_REGISTER);
delay_ms(5);
// Write the value of the control register - Command 7
return_value = set_pot(WRITE_CONTROL_REGISTER | 0x02);
return_value = set_pot(WRITE_CONTROL_REGISTER | 0x02);
delay_ms(5);
// Read the value of the control register - Command 8
return_value = set_pot(READ_CONTROL_REGISTER);
return_value = set_pot(READ_CONTROL_REGISTER);
// printf("RV: %04x\r",return_value);
for (i=0; i< POT_COUNT; i++) // Set All Pots to nominal
{
set_pot_to_voltage(i,nominal_rail_voltages[i]);
}
delay_ms(5); // Make sure we have cleared everything out
}
void load_cal_data()
{
int int_array[4],i,j;
float *float_ptr;
// printf("Load Cal Data:\r");
for (j=0; j < TOTAL_POT_PARAMETER_COUNT; j++)
{
for(i = 0; i<4 ; i++)
{
int_array[i] = read_eeprom(POT_CAL_TABLE_BASE_ADDRESS+i+(4*j));
}
float_ptr = int_array;
pot_cal_table[j] = *float_ptr;
// printf("LCD: Addr: %02x: Value %4.8f\r",j,pot_cal_table[j]);
}
}
void clear_cal()
{
printf("CC:\r");
write_eeprom(CAL_PRESENT_ADDRESS, 0xAA);
delay_ms(50);
}
void write_cal_parameter(int eeprom_addr, int *ptr, int range)
{
int i,eeprom_data;
for(i = 0; i< range ; i++)
{
eeprom_data = ptr[i];
// printf("WCP: %02x %02x, PIE2: %02x\r",eeprom_addr+i, eeprom_data, pie2);
write_eeprom(eeprom_addr+i, eeprom_data);
delay_ms(30);
}
// printf("EEPROM: ");
// for(i = 0; i<24 ; i++)
// {
// printf("%02x ",read_eeprom(i));
// }
// printf("\r");
}
void cal_pot()
{
long return_value;
float high_value, low_value, step_size;
int eeprom_data, i;
int *ptr;
// printf("Cal Pot\r");
eeprom_data = read_eeprom(CAL_PRESENT_ADDRESS);
if (eeprom_data != CAL_FLAG) // Read the EEPROM - if cal flag in addr 0, then blow this step off
{
for(i=0; i < POT_COUNT; i++)
{
printf("No Cal Data present. Calibrating.\r");
return_value = set_pot(WRITE_RDAC_REGISTER | UPPER_CAL_LIMIT);
delay_ms(10);
high_value = adc_sample(i);
return_value = set_pot(WRITE_RDAC_REGISTER | LOWER_CAL_LIMIT);
delay_ms(10);
low_value = adc_sample(i);
printf("Addr: 0x%02x: Cal High: %4.3f, Low: %4.3f\r",i,high_value,low_value);
ptr = &high_value;
write_cal_parameter(POT_CAL_TABLE_BASE_ADDRESS+(i*POT_PARAMETERS),ptr,4);
ptr = &low_value;
write_cal_parameter(POT_CAL_TABLE_BASE_ADDRESS+(i*POT_PARAMETERS)+4,ptr,4);
write_eeprom(CAL_PRESENT_ADDRESS,CAL_FLAG);
step_size = (high_value - low_value)/POT_STEPS;
ptr = &step_size;
write_cal_parameter(POT_CAL_TABLE_BASE_ADDRESS +(i*POT_PARAMETERS)+8,ptr,4);
write_eeprom(CAL_PRESENT_ADDRESS,CAL_FLAG);
delay_ms(30);
}
}
load_cal_data();
}
void print_help()
{
printf("\r\r\r\r\rSPI Test\r");
}
void print_volts()
{
int i;
float temp;
for (i=0; i < POT_COUNT; i++)
{
temp = adc_sample(i);
printf(" PV: ADC: %f\r",temp);
printf(" PV: ADC: %f\r",5.27);
printf(" PV: ADC: %f\r",temp);
temp = 1.234;
printf(" PV: ADC: %f\r",temp);
}
}
struct char_input // character input buffer
{
char *characters[10];
int8 len;
int1 err;
} user_input;
// Character input routine with backspace editing
void get_string(int max)
{
int len;
char c;
--max;
len=0;
do
{
c=getc();
if(c==8) // Backspace
{
if(len>0)
{
len--;
putc(c);
putc(' ');
putc(c);
}
}
else if ((c>=' ')&&(c<='~'))
if(len<max)
{
user_input.characters[len++]=c;
putc(c);
}
} while (c!=13);
user_input.characters[len]=0;
user_input.len = len;
}
float parse_input() {
float result_float;
char ptr[10];
int i;
user_input.len = 0; // Initialize the port variables prior to get_string call
user_input.err = 0;
get_string(10); // Load the global string with command line stuff
for (i=0;i<10;i++) // Load the global buffer output locally - some weird compiler stuff otherwise.
{
ptr[i] = user_input.characters[i];
}
result_float = strtof(ptr,ptr + strlen(ptr));
printf("\rReceived Float: %5.4f\r",result_float);
return result_float;
}
void main()
{
float input_value;
int error;
reset:
print_help();
init_io();
cal_pot();
init_pots();
// Set them all to mid-range
while (1)
{
printf("> "); // Print the Prompt
input_value = parse_input();
printf("\rInput Value: %4.3f\r",input_value);
error = 0;
if ((input_value <= pot_cal_table[0]) && (input_value >= pot_cal_table[1]))
{
set_pot_to_voltage(0,input_value);
}
else if (input_value == 0)
{
clear_cal();
goto reset;
}
else
{
printf("Input of range!\r");
}
print_volts();
}
} |
|
|
|
PCM programmer
Joined: 06 Sep 2003 Posts: 21708
|
|
Posted: Wed Jun 29, 2011 4:52 pm |
|
|
This is too much code and it's too convoluted for me.
I did notice one thing. Here you've declared an array of pointers to chars
but you use it as an ordinary array of characters. You should remove the *.
Quote: |
struct char_input // character input buffer
{
char *characters[10];
int8 len;
int1 err;
} user_input;
c=getc();
user_input.characters[len++]=c;
|
|
|
|
brock
Joined: 29 Jun 2011 Posts: 8
|
PRINTF NOT PRINTING FLOATING POINT NUMBERS CORRECTLY |
Posted: Wed Jun 29, 2011 5:11 pm |
|
|
Did you build it and see if it does what I said it does?
I could strip it down, but then the issue probably will submerge.
The fact remains that with this code NO printf prints floats correctly. Comment out the line labeled CCSINFO and you should see it....
Not that it's relevant, but but the line input works...so I don't see how the usage could be off.... |
|
|
|
|
You cannot post new topics in this forum You cannot reply to topics in this forum You cannot edit your posts in this forum You cannot delete your posts in this forum You cannot vote in polls in this forum
|
Powered by phpBB © 2001, 2005 phpBB Group
|