![](templates/subSilver/images/CCSLogo.jpg) |
![CCS C Software and Maintenance Offers](templates/subSilver/images/forumAd6.jpg) |
View previous topic :: View next topic |
Author |
Message |
plehman
Joined: 18 Feb 2004 Posts: 12
|
float to int32 typecasting |
Posted: Wed Feb 18, 2004 4:57 pm |
|
|
Hello,
I am using the 3.185 compiler, and have run into a small problem with a function I have written. The problematic function, called correct_adc_value(), is given below:
int32 correct_adc_value(int32 RawValue)
{
int i;
int32 Answer;
for (i = 0; i < 4; i++)
{
C.hValue[i] = read_eeprom(16 + i);
D.hValue[i] = read_eeprom(20 + i);
}
convert_ieee_to_microchip(&C.hValue[0]);
convert_ieee_to_microchip(&D.hValue[0]);
Correct.fValue = (C.fValue * RawValue) + D.fValue;
Answer = (int32) Correct.fValue;
return Answer;
}
the variables C, D, and Correct are actually unions as shown below:
union float_temp
{
float fValue;
int hValue[4];
} A, B, C, D, Correct;
Here's is what I am doing...
I retrieve an unsigned 24-bit A/D conversion value, and use make32() to create an int32 variable representing that value, which I then pass to correct_adc_value as RawValue (MSB always 0). The idea is to apply an Cx + D style correction to the RawValue to account for reference voltage differences, part tolerances, etc. basically, anything that can hinder the performance of the A/D.
The coefficients for the algorithm, C and D, are loaded into the union from the PIC's eeprom memory using the .hValue[i] variables, as shown in the first part of the function. This part works correctly. The same goes for the IEEE-754 to Microchip conversion. I am including that conversion code as well below, in case anyone is interested.
void convert_ieee_to_microchip(int *Value)
{
int1 Temp;
Temp = shift_left(&Value[1], 1, 0);
Temp = shift_left(&Value[0], 1, Temp);
shift_right(&Value[1], 1, Temp);
}
void convert_microchip_to_ieee(int *Value)
{
int1 Temp;
Temp = shift_left(&Value[1], 1, 0);
Temp = shift_right(&Value[0], 1, Temp);
shift_right(&Value[1], 1, Temp);
}
Now to the problem...
The type cast at the end seems to clip to only the 2 LSBs. In testing this, I pass 0x00456789 as RawValue into the routine, and if C is 0x3F800000 (IEEE-754 for 1.0) and D is 0x00000000 (IEEE-754 for 0), the returned value is 0x00006789, where I expected 0x00456789.
It should be noted that I do a similar correction to a 16bit (long) d/a value and it works without issue.
Thanks in advance for your help. |
|
![](templates/subSilver/images/spacer.gif) |
plehman
Joined: 18 Feb 2004 Posts: 12
|
|
Posted: Sun Feb 22, 2004 2:51 pm |
|
|
I finally seem to have found a solution to my problem. It seems if I add a typecast for RawValue to a float in the third line from the end, the calculation for Correct.fValue. This line would then look like the following:
Correct.fValue = (C.fValue * (float) RawValue) + D.fValue;
Hopefully this will help anyone who runs into this problem in the future. |
|
![](templates/subSilver/images/spacer.gif) |
Ttelmah Guest
|
|
Posted: Sun Feb 22, 2004 3:32 pm |
|
|
plehman wrote: | I finally seem to have found a solution to my problem. It seems if I add a typecast for RawValue to a float in the third line from the end, the calculation for Correct.fValue. This line would then look like the following:
Correct.fValue = (C.fValue * (float) RawValue) + D.fValue;
Hopefully this will help anyone who runs into this problem in the future. |
Yes.
This particular behaviour has been mentioned in many threads in the past. The CCS compiler, performs 'slow' automatic casting, in that it only propogates to a higher type, when either commanded to do so (with a cast), or when a higher type is involved in a maths component. So, where most C compilers would look at the whole statement, and propogate to the highest type used in the whole statement, the CCS compiler, will keep the types to the smaller sizes, by default. the advantage, is that it helps to ensure that larger/slower maths operations are not used unnecessarily, but the downside, is that when some operations are performed data will be lost.
There have been many posts in the past advising that when explicit use of a larger arithmetic type is required, you should allways cast.
You have now found this, and hopefully will serve to remind others of this behaviour...
Best Wishes |
|
![](templates/subSilver/images/spacer.gif) |
|
|
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
|