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.

Bcd2Binary & Binary2Bcd

Status
Not open for further replies.

Dumken

Member
Hi. good day guys. Pls can anyone help me explain how the conversion process was done. Am finding it difficult understanding how the conversion was done. Pls i seriously need help.

int BCD2Binary(int a)
{
int r,t;
t = a & 0x0F;
r = t;
a = 0xF0 & a;
t = a >> 4;
t = 0x0F & t;
r = t*10 + r;
return r;
}

int Binary2BCD(int a)
{
int t1, t2;
t1 = a%10;
t1 = t1 & 0x0F;
a = a/10;
t2 = a%10;
t2 = 0x0F & t2;
t2 = t2 << 4;
t2 = 0xF0 & t2;
t1 = t1 | t2;
return t1;
}

I got the code from an RTC clock code attached below
 

Attachments

  • Digital-Clock.zip
    308.5 KB · Views: 178
Hi,

You really need to look at the code step by step if you really want to understand it.

For BCD to binary you are taking a number grouped a certain way and calculating what it takes to group it another way. The units digit is obtained by AND'ing with 0x0F, and the 10's digit is obtained by AND'ing with 0xF0. Multiplications then convert to binary, and add the results.

For binary to BCD, it's almost the same but i think there is a better algorithm on the web that will do any number of digits, like 5 or more if you use more registers. I cant recall the name if it but somebody else here probably does. I'll see if i can find it.

BCD to binary is good for interpreting user input, and binary to BCD is good for displaying results.

The algorithm is called something like "Double Dabble" and it converts any size binary to BCD whatever number of digits you need.

Here is an analysis of the program code for a couple different numbers. Note that whenever any four bit group becomes greater than 4 we add 3 to it. For the 'In Place" code we only add 3 when the number is greater than 4 and it is to the right of the 'x'.



Code:
The double-dabble algorithm, performed on the value 243, looks like this:

0000 0000 0000  11110011  Initialization
0000 0000 0001  11100110  Shift
0000 0000 0011  11001100  Shift
0000 0000 0111  10011000  Shift
0000 0000 1010  10011000  Add 3 to ONES, since it was 7
0000 0001 0101  00110000  Shift
0000 0001 1000  00110000  Add 3 to ONES, since it was 5
0000 0011 0000  01100000  Shift
0000 0110 0000  11000000  Shift
0000 1001 0000  11000000  Add 3 to TENS, since it was 6
0001 0010 0001  10000000  Shift
0010 0100 0011  00000000  Shift


Now do the number 255 in binary...

0000 0000 0000  11111111  start
0000 0000 0001  11111110  shift
0000 0000 0011  11111100  shift
0000 0000 0111  11111000  shift
0000 0000 1010  11111000  added 3 since ones was 7 (and 7>4)
0000 0001 0101  11110000  shift
0000 0001 1000  11110000  added 3
0000 0011 0001  11100000  shift
0000 0110 0011  11000000  shift
0000 1001 0011  11000000  added 3 to tens
0001 0010 0111  10000000  shift
0001 0010 1010  10000000  added 3
0010 0101 0101  00000000  shift
  done.


In-place algo for the binary number 1023:
(this is a bit harder to determine when to add 3)

INDEX THOU HUND TENS  UNITS
  0  11 1111 1111  x000  Start
  1  11 1111 111x  0001  Shift 1
  2  11 1111 11x0  0011  Shift 2
  3  11 1111 1x00  0111  Shift 3
  4  11 1111 1x00  1010  ADD-3 to UNITS
  4  11 1111 x001  0101  Shift 4
  5  11 1111 x001  1000  ADD-3 to UNITS
  5  11 111x 0011  0001  Shift 5
  6  11 11x0 0110  0011  Shift 6
  7  11 11x0 1001  0011  ADD-3 to TENS (live)
  7  11 1x01 0010  0111  Shift 7
  8  11 1x01 0010  1010  ADD-3 to UNITS
  8  11 x010 0101  0101  Shift 8
  9  11 x010 0101  1000  ADD-3 to UNITS
  9  11 x010 1000  1000  ADD-3 to TENS  <--
  9  1x 0101 0001  0001  Shift 9
 10  1x 1000 0001  0001  ADD-3 to HUND  <--
 10  x1 0000 0010  0011  Shift 10
 
Last edited:
If Mr Al's explanation went straight over your head....

Binary Code Decimal...

Example
lets take a number... decimal 23.

23 decimal is 17 hex and 00010111 binary.

Now the conversion.

23 modulus 10 = 3 ( save the 3 )
23 divided by 10 = 2 then 2 multiplied by 16 = 32

add the modulus result 32 + 3 = 35

35 decimal is 23 hex... BCD is 23

the couple of masks are only there to ensure you are working with the nibble only..

going back is the reverse..

23 hex.. (BCD )

23 take the lower nibble 3 ( save the 3 )
23 divide by 16 = 2 then 2 multiplied by 10 = 20

We now have 0x17 hex which is 23 decimal..

I don't know why MikroC uses int's when we are clearly using unsigned char's..
 
If Mr Al's explanation went straight over your head....

Binary Code Decimal...

Example
lets take a number... decimal 23.

23 decimal is 17 hex and 00010111 binary.

Now the conversion.

23 modulus 10 = 3 ( save the 3 )
23 divided by 10 = 2 then 2 multiplied by 16 = 32

add the modulus result 32 + 3 = 35

35 decimal is 23 hex... BCD is 23

the couple of masks are only there to ensure you are working with the nibble only..

going back is the reverse..

23 hex.. (BCD )

23 take the lower nibble 3 ( save the 3 )
23 divide by 16 = 2 then 2 multiplied by 10 = 20

We now have 0x17 hex which is 23 decimal..

I don't know why MikroC uses int's when we are clearly using unsigned char's..

Pls where is the multiplication by 16 coming from?
 
Hi,

A multiplication by 16 can be done using four left shifts.
For example if you start with binary (decimal):
0000 0001 (1)
and shift it left once you get:
0000 0010 (2)
and shift it left again you get:
0000 0100 (4)
and shift it left again:
0000 1000 (8)
and shift it left one last time:
0001 0000 (16)

so we managed to multiply 1 times 16 using just 4 shifts.

If we shift to the right four times instead of to the left four times we do an integer divide by 16, which means we divide by 16 but loose any fractional part.

Here is a step by step breakdown of the BCD2binary algorithm you posted. Each step after the operation shows the result of that operation:

a=0010 0011 to start, which is 23 binary coded decimal (BCD)

t=a&0x0F
t=0000 0011
r=t
r=0000 0011
a=0xF0&a
a=0010 0000
t=a>>4
t=0000 0010
t=0x0F&t
t=0000 0010
r=t*10+r
r = 0001 0100 + 0000 0011 = 0001 0111
return r
r is 23 binary so we converted 23 BDC to 23 binary.

I have to agree with Ian that the types should be unsigned integers, not just integers. Although some systems will handle both the same for these kinds of operations it is better to use the right type to be sure.
 
Last edited:
I think we need to asses your understanding of BCD

Here is a number:---- 1234

If this was in binary it would look like this 0100 1101 0010.. in Hexadecimal like this 0x4D2..
Now to represent a number in BCD we use the HEX format Each nibble represents a decimal no.
So we need the binary to look like this 0001 0010 0011 0100 In hexadecimal 0x1234..
Each nibble is capable of holding the values 0 ~ 15 or 16 values in total

0x1234 is decimal 4660 which isn't right!!!

To convert base 16 to base 10, you need to divide by 16 and multiply by 10..
To convert base 10 to base 16, you do the reverse...

BUT!!! we are using a hybrid number system that only RTC's seem to use..
Each group of 4 bits ( nibble ) contain a value 0~9 ( decimal ) but in a binary format.. Binary coded decimal.
 
Hi again,

Another view is that for a number like 123 decimal:
123

in BCD we interpret this as:
1*100+2*10+3

but the uC knows this as binary which would be:
1*256+2*16+3

so to convert from this last form to the binary form of 123 we would have to divide 0x100 hex by 256 and then multiply by hex 0x64, then add that to 0x14 hex divided by 16 and multiplied by 0x0A, then add 3. We should get ox7B as result.
 
To convert a single byte from binary to BCD you can simply add the number/10*6 to itself.

To convert 47 binary to BCD you add 4*6. I.E a+=a/10*6 ...... 47+4*6=71 = &h47

To convert back you subtract the high nibble times six.

To convert &h47 to binary you subtract 4*6. I.E a-=(a>>4)*6 .... &h47-4*6=47

Simples,

Mike.
 
Hi,

A multiplication by 16 can be done using four left shifts.
For example if you start with binary (decimal):
0000 0001 (1)
and shift it left once you get:
0000 0010 (2)
and shift it left again you get:
0000 0100 (4)
and shift it left again:
0000 1000 (8)
and shift it left one last time:
0001 0000 (16)

so we managed to multiply 1 times 16 using just 4 shifts.

If we shift to the right four times instead of to the left four times we do an integer divide by 16, which means we divide by 16 but loose any fractional part.
´

Concise and to the point. I like the way!
 
´

Concise and to the point. I like the way!

Hi,

Well thanks, and you made me realize that i probably should have also mentioned that any power of 2 can be done that way too, such as:
x*2: shift 1 time to the left
x*4: shift 2 times to the left
x*8: shift 3 times to the left
x*16: shift 4 times to the left
x*32: shift 5 times to the left

So the number of shifts to the left comes from the exponent in:
x*2^n

where n is the number of left shifts required.

The one catch is that we have to watch out how many bits our register can handle without an overflow. For example, if we have a binary number using an 8 bit register and we have first:
0101 0001

the first shift leads to:
1010 0010

but the second shift leads to:
0100 0100

which means we lost the first '1' and so the result is no good.
In this case, we detect a carry and use a second register to handle the upper bits. in this way we can handle any size argument even a 32 bit number as long as we have enough registers available. If we use a higher level language though this is probably already taken care of for us in the framework of the language.

There are other tricks too when working in asm especially. For example, if we have to multiply by 10 we dont find an exponent 'n' that works for that, we only have 8 and 16, which is not right. But we do realize that 10 can be broken down into 2*5, and 5 can be broken down into 4 and 1, which means we can shift the number three times to the left, add the original back to it, then shift the result once to the left:
say we want to multiply this times 10:
A=0000 1001

shift it to the left two times (this comes from the 4):
B=0010 0100

add that to the original (from the 1):
C=A+B=0010 1101

shift that to the left once (from the 2):
D=0101 1010

So we just took 9 and multiplied it by 10 and got 90 as result.

Another trick with the same problem would go like this...

Start with 9 again:
A=0000 1001

and we want to multiply by 10 which is 1010 in binary.
By looking at the bits in the 1010 we see two 1's, in positions 8 and 2. So to do it this other way we first shift three times:
B=0100 1000

and shift the original 1 time:
C=0001 0010

then add the two:
D=B+C=0101 1010

which again is 90.
 
Last edited:
Status
Not open for further replies.

Latest threads

Back
Top