HC08LB8 arithmetic operation

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

HC08LB8 arithmetic operation

4,658 Views
rceit
Contributor I
Hello, i am working with a HC08LB8, freq_khz is a number between [40, 120], A_f, B_f are 16bit variables
 
My code is:
 
    A_f = (((3 * freq_khz * freq_khz)/50)+6 * freq_khz+8432);
   
    B_f = (freq_khz * freq_khz)/10;
 
the opertion:
 
              A_f = (((3 * freq_khz * freq_khz)/50)+6 *freq_khz+8432);
 
return a correct result, but in the next line: 
 
               B_f = (freq_khz * freq_khz)/10;
 
the result is not the right, i think that the problem is the CCR (Condition Code Register) but i do not know how make for have a correct result.
 
Thanks you.
 
Labels (1)
0 Kudos
10 Replies

773 Views
bigmac
Specialist III

Hello rceit,

I have now actually tried out your equations in the simulator, and obtained the expected results for both A_f and B_f variables, with freq_khz firstly set for 40, and then for a value of 120.  I declared all three variables as unsigned int.

The following results were obtained:

freq_khz   A_f   B_f
   40     8768   160
  120    10016  1440

Regards,
Mac

 

0 Kudos

773 Views
rceit
Contributor I
Hello bigmac and rocco, thanks for your reply.

This is the complete code, in my last post i have put less code for simplify the question, but in this way the information it is not full, sorry.

this is my code :

volt_T1=ADR; // get ADR value
freq_khz =AUX_K/HRPPER; // freq_khz between [40,120]

A_f = (((3 * freq_khz * freq_khz)/50)+(6 * freq_khz+8432));

//(3 * freq_khz * freq_khz) do not causes overflow in A_f?

B_f = (((9 * freq_khz * freq_khz)/10)+(2*freq_khz+12787))/10;

// 9 * freq_khz*freq_khz causes overflow and a bad B_f value?
// what is the solution? unsigned long?

volt_pk_T1_bin = (A_f * volt_T1 + B_f)/100;

// A_f * volt_T1 also causes overflow

Declaration of variables:

tU16 volt_pk_T1_bin; typedef unsigned int tU16;
extern tU16 extern tU16 A_f;;

tU16 A_f; typedef unsigned int tU16; extern tU16 A_f;
tU16 B_f; typedef unsigned int tU16; extern tU16 B_f;


//A_f, B_f, volt_pk_T1_bin are unsigned int global

Message Edited by rceit on 2006-06-11 05:44 AM

0 Kudos

773 Views
bigmac
Specialist III
Hello rceit,
 
If you wish to stick with the use of unsigned int, you might modify the second formula as follows -
 
B_f = ((((freq_khz*freq_khz)/10)*9)+(2*freq_khz+12787))/10;

This will do the division before the multiplication, and prevent overflow.  There could be a slight loss of precision due to integer rounding errors, but since you are doing a final division by 10, this should not be apparent in the end result.
 
Regards,
Mac
 
0 Kudos

773 Views
rceit
Contributor I

Hello Mac,

The problem of overflow is solved for  B_f, but it continues with :

volt_pk_T1_bin = (A_f * volt_T1 + B_f)/100;

and any change done an inaceptable loss of resolution. The problem will be the mathematical functions described in 2006-06-1202:59 AMreply?

0 Kudos

773 Views
bigmac
Specialist III

Hello rceit,


rceit wrote:
The problem of overflow is solved for  B_f, but it continues with :

volt_pk_T1_bin = (A_f * volt_T1 + B_f)/100;

and any change done an inaceptable loss of resolution.


Why do you not use the CW library for integer mathematical functions where I assume long variables can be handled?

You do not mention the range of values expected for volt_T1 variable.  You imply that this is equal to an address - or should this be the contents of an address - but this is not clear.  According to my calculations the range of values for A_f is 8768 to 10016, and for B_f the range is 1430 to 2598.  You may want to divide each of these by 100 prior to multiplying the first term by the volt_T1 value, with a maximum allowed value of about 655 when A_f and B_f have their maximum values.  So the formula might be re-arranged as follows:

volt_pk_T1_bin = ((A_f + 50)/100 * volt_T1 + (B_f + 50)/100;

Note the rounding correction for the integer division process.  This is probably the best result  achievable with integer arithmetic on 16-bit values.  The rounding correction might also be applied to the calculation of A_f and B_f (assuming the formulae do not already do this).

Regards,
Mac

 

 

0 Kudos

773 Views
rceit
Contributor I

Hello big,

Thanks for your help, finally i have solved the question:

volt_T1 is ADR value [0,255].

with A_f = 8768

                   volt_pk_T1_bin = (A_f * volt_T1 + B_f )/ 100 = 22372

with A_f = 87,68

                      A_f = A_f/100 +A_f -(A_f/100)*100

                   volt_pk_T1_bin = 87 * volt_T1+ (68 * volt_T1 + 1430)/100 = 22372

ciao.

0 Kudos

773 Views
rocco
Senior Contributor II
Hi, Rceit:

Yes, a number of terms in your equations exceed 65535 when the frequency is 120. So unsigned integers are not large enough.

If you are doing this all in C, I would suggest using longs. It may not matter whether you use signed or unsigned, but in my math library signed is a tiny bit more efficient than unsigned. I don't know about your C, however. Longs will certainly be more efficient than switching to floats.
0 Kudos

773 Views
rceit
Contributor I
Hi rocco, my code is C. I have try with unsigned long but this not works.
In my Sources folder i have defined basic mathematical functions:
 

Code:
/*****************************************************************************    Intrinsic functions definition*****************************************************************************/SByte Add_8(SByte x, SByte y);            /* source sdkmath.asm */SByte Lim_8(SByte x, SByte limit);        /* source sdkmath.c   */SByte Neg_8(SByte x);                     /* source sdkmath.asm */SByte Shl_8(SByte x, UByte n);            /* source sdkmath.asm */SByte Sub_8(SByte x, SByte y);            /* source sdkmath.asm */SWord16 Add(SWord16 x, SWord16 y);        /* source sdkmath.asm */SWord16 Lim(SWord16 x, SWord16 limit);    /* source sdkmath.c   */SWord16 Neg(SWord16 x);                   /* source sdkmath.asm */SWord16 Shl(SWord16 x, UByte n);          /* source sdkmath.asm */SWord16 Sub(SWord16 x, SWord16 y);        /* source sdkmath.asm */UWord16 Umul_16x8 (UWord16 x, UByte y);   /* source sdkmath.c   */SWord16 Smul_16x8 (SWord16 x, UByte y);   /* source sdkmath.c   */SWord16 Smul_8(SByte x, UByte y);         /* source sdkmath.c   */SByte   Sdiv_8(SWord16 x, UByte y);       /* source sdkmath.asm */UByte   Udiv_16to8(UWord16 x, UWord16 y); /* source sdkmath.asm */

 
May be this the problem? the arithmetical operations works with this funtions? if this is correct i can not make unsigned long opertions only the operations specified in the funtions list. 
(Alban formatted code)

Message Edited by Alban on 2006-06-12 10:18 AM

0 Kudos

773 Views
bigmac
Specialist III
Hello rceit,
 
A further issue may be that the variable A_f (and B_f) may need to be unsigned int for the first equation to work for all allowable values of freq_khz.  This is because the partial calculation 3*freq_khz*freq_khz may overflow a signed int value.  You don't specify what you are currently using.
 
Regards,
Mac
 
0 Kudos

773 Views
rocco
Senior Contributor II
Hi, rceit:

How is freq_khz defined? is it an 8-bit or 16-bit value?

What do you get as an incorrect result, and for what value of freq_khz?

Can you post the generated assembly code?
0 Kudos