Greetings.
I need your help understanding the use of FRAC16 format in the C
CodeWarrior programation.
When I have a quantity, for example, 15 how I transform this
number to FRAC16 format?
I make this this question because I want to know like making this
calculation:
Isensed = Value form ADC; (in FRAC16 type or form)
V = Isensed * Resistance; /*But Resistance = 15 Ohm*/
/*how transform Resistance to FRAC16 format, to obtain V in FRAC16
format?*/ Cordialmete, Oscar Javier Tadeo Jaramillo Galeano. Nit: 98665185-4 Telefono. 300-779-60-62 Busc un auto? Encontralo en Yahoo! Autos M de 4000 clasificados todos los ds! Usados - 0 km - Vendel tuyo |
|
Using FRAC16
Started by ●March 12, 2004
Reply by ●March 15, 20042004-03-15
--- In , Oscar Jaramillo <ojataga@y...> wrote: > Greetings. > > I need your help understanding the use of FRAC16 format in the C CodeWarrior programation. > > When I have a quantity, for example, 15 how I transform this number to FRAC16 format? > > I make this this question because I want to know like making this calculation: > > Isensed = Value form ADC; (in FRAC16 type or form) > V = Isensed * Resistance; /*But Resistance = 15 Ohm*/ > > /*how transform Resistance to FRAC16 format, to obtain V in FRAC16 format?*/ > The first thing you have to realize is that C doesn't support fixed point, it simply isn't in the standard. So instead we typecast Frac16 to signed short integers. So instead of an integer between -32768 and 32767 we think of a fraction between -1 and 1-2^(-15) by simply dividing by 32768. This works great as long as you are adding, since adding integers is the same as adding fractions. (You add the numerators...) So a line of C code such as Z = X + Y; works regardless of whether X,Y, and Z are thought of as fractions or integers. But Z = X*Y won't produce what you want. Since X and Y are both fractions in the range [-1,1) their product will also be in this range. But the product of two 16 bit numbers is a 32 bit number. So what C does in Z = X*Y is calculate the product of two 16 bit integers and then truncate the result by assigning the lower 16 bits into Z. That's exactly not what you want. What you want is for C to assign to Z the upper part. There is also the issue of the redundant sign bit. So if you declared a long integer and then did the calculation it would still be off by a factor of two: long ZBig; ZBig = X*Y; Z = ZBig >> 16; So if X=1/2, Y = 1/4 then you want X*Y = 1/8. But Z = 1/16 in the calculation above. The reason for this is that the product of two short integers produces a long integer (16x16 bits = 32 bits) which has a redundant sign bit. So infact you need to do the following: ZBig = X*Y; Z = ZBig >> 15; It is simply easier (and safer) to use one of the multiply primitives from SDK/Processor Expert: Z = mult_r(X,Y); O.K. - So adding in C is fine, but multiplying is dangerous unless you use the right primitives. The other trick to converting an algorithm in floating point to fixed point is to realize that in fixed point you don't carry the exponent in the calculation, just the mantissa. So each term of your calculation is just a mantissa in the range [-1,1). The exponent you have to keep in your head or calculate separately. "Block floating point" is a technique of scaling all the terms to have the same exponent, calculating with just the mantissas (fractions) and maintaining the exponent separately (either in your head or as a separate calculation). |