Continue to Site

Welcome to our site!

Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

  • Welcome to our site! Electro Tech is an online community (with over 170,000 members) who enjoy talking about and building electronic circuits, projects and gadgets. To participate you need to register. Registration is free. Click here to register now.

Microcontroller Aritmetic

Status
Not open for further replies.

akahrim

Member
Hello All,

I am trying to do math on a microcontroller. I'm using an 8bit micrcontroller from Atmel. I've read several articles on Fixed Point arthmetic and I am still a little confused on Fixed Point Arithmetic in regards to microcontrollers. The articles do not go into depth as to what happens in the microcontroller. Do microcontrollers without Floating point capability only understand integers? If so, Is the answer to Y=3/4 equal to zero in the microcontroller?

The other question I had is what happens if you have two 8bit integers (Y=100, X=100) and you multiply them ( Z=100x100, Z is also 8 bits). This creates an overflow but what actually happens when a variable overflows? I've googled it and I've seen explanations from "Undefined Behaviours" to wrapping. Any feedback would be greatly appreciated.
 
What language are you working in?

In fixed point you just move the decimal point around. So to find the circumference of a circle with radius 123 you would do 123 * 314 / 100 = 386 because 314 is Pi*100 so you need to divide after the multiply. Implementation depends on the language used.

Mike.
 
What language are you working in?

In fixed point you just move the decimal point around. So to find the circumference of a circle with radius 123 you would do 123 * 314 / 100 = 386 because 314 is Pi*100 so you need to divide after the multiply. Implementation depends on the language used.

Mike.
Hello Mike,

I'm working in C++.

Amir
 
In C it's up to you to ensure that integer maths is done correctly. Doing 123*314/100 will give the correct answer, doing 123/100*314 will give a wrong answer due to rounding (assuming left to right calculation). Likewise, overflow shouldn't be able to happen. Just use variables that are big enough that overflow won't occur.

Mike.
 
The other question I had is what happens if you have two 8bit integers (Y=100, X=100) and you multiply them ( Z=100x100, Z is also 8 bits). This creates an overflow but what actually happens when a variable overflows? I've googled it and I've seen explanations from "Undefined Behaviours" to wrapping. Any feedback would be greatly appreciated.

If you have three unsigned 8-bit integers:

uint8_t a = 100;
uint8_t b = 100;
uint8_t result;

and you multiply them
a * b;

What happens is, both variables are "promoted" to 16-bit integers and the multiplication is performed. The result is a 16 bit integer 10000 (decimal).
Which in binary form is: 0b00100111 00010000

Now, if you assign the result into an 8 bit integer only the lower 8 bits are saved:
result = a*b;

Result now contains the lower byte 0b00010000, which in decimal is 16.
 
Last edited:
In C it's up to you to ensure that integer maths is done correctly. Doing 123*314/100 will give the correct answer, doing 123/100*314 will give a wrong answer due to rounding (assuming left to right calculation). Likewise, overflow shouldn't be able to happen. Just use variables that are big enough that overflow won't occur.

Mike.
Thanks for the reply Mike.
 
If you have three unsigned 8-bit integers:

uint8_t a = 100;
uint8_t b = 100;
uint8_t result;

and you multiply them
a * b;

What happens is, both variables are "promoted" to 16-bit integers and the multiplication is performed. The result is a 16 bit integer 10000 (decimal).
Which in binary form is: 0b00100111 00010000

Now, if you assign the result into an 8 bit integer only the lower 8 bits are saved:
result = a*b;

Result now contains the lower byte 0b00010000, which in decimal is 16.
Hello MisterT, Thanks for the explanation. Makes perfect sense.

Amir
 
In fixed point you just move the decimal point around. So to find the circumference of a circle with radius 123 you would do 123 * 314 / 100 = 386 because 314 is Pi*100 so you need to divide after the multiply. Implementation depends on the language used.

That is so easy to say. In reality fixed point math is full of traps.

Here is a fixed point macros that I used/wrote 5 years ago (There was one good source that I used, but I don't remember it). I don't remember if there was any serious bugs..
I also have square root and trigonometric functions, if somebody is interested.
C:
/* Some usefull constants (6.10 format only)*/
#define FPZERO        (0x0000)
#define FPONE        (0x0400)
#define FPTEN        (0x2800)
#define FPPI        (0x0c91)
#define FP2PI        (0x1922)
#define FPHALFPI    (0x0648)
#define FPSQRT2        (0x05a8)

/* M.N fixed point format */
#define M (6)
#define N (10)
#define NMASK (0x3ff)

typedef int16_t fp_t;
typedef int32_t fpdbl_t;

/*
* *****************************************************************************
* Public function prototypes and macros
* *****************************************************************************
*/
#define max(a,b) (((a)>(b)) ? (a):(b))
#define min(a,b) (((a)<(b)) ? (a):(b))
//#define abs(a)   (((a)<(0)) ? -(a):(a))
#define sign(a)  (((a)<(0)) ? -1 : (a)>0 ? 1 : 0)

/* Addition and subtraction */
#define fpadd(a,b) ((a)+(b))
#define fpsub(a,b) ((a)-(b))

/* Multiplication */
#define fpmul(a,b) ((fp_t) ((((fpdbl_t)(a)) * ((fpdbl_t)(b))) >> N))

/* Division (a/b) */
#define fpdiv(a,b) ((fp_t) ((((fpdbl_t)a)<<N) / b))

/* Multiplication and division (v*m)/d */
#define fpmuldiv(v,m,d) ((fp_t)((((fpdbl_t)(v)) * ((fpdbl_t)(m))) / d))

/* Integer to fixed point and vice versa */
#define int2fp(a) (((fp_t)a)<<N)
#define fp2int(a) ((x)>>N)

/* Floating point to fixed point and vice versa */
#define float2fp(a) ((fp_t)((a) * (1<<N)))
#define fp2float(a) (((float)(a)) / (1<<N))

/* Extract the fractional part */
#define fpfract(x) ((x) & NMASK)
 
Last edited:
Status
Not open for further replies.

Latest threads

Back
Top