Continue to Site

Welcome to EDAboard.com

Welcome to our site! EDAboard.com is an international Electronics Discussion Forum focused on EDA software, circuits, schematics, books, theory, papers, asic, pld, 8051, DSP, Network, RF, Analog Design, PCB, Service Manuals... and a whole lot more! To participate you need to register. Registration is free. Click here to register now.

Hex value To BCD conversion.

Status
Not open for further replies.

incomplete_jerin

Advanced Member level 2
Joined
Jun 4, 2010
Messages
549
Helped
97
Reputation
208
Reaction score
92
Trophy points
1,308
Location
INDIA
Activity points
3,912
Can anyone give me an idea of the logic behind converting a 8 bit value to BCD value with an example?
I searched in net but couldn't find a nice one. :-( :???:
Thanx in advance.

Jerin.
 

See EDN Oct 7 2010 issue
**broken link removed**
 

Hello!

What do you want to know exactly?
The logic behind this is simply to convert. Here is an example:
In decimal, you writ for instance 77, which converts to 0x4D in hexa, but
to 0x77 in BXD.

So you want to convert a decmal to BCD?

Code:
uint8 val;          // The value you want to convert
uint16 bcdval;   // The converted value
uint8 d0, d1, d2; // the 3 decimal figures used to write a 0 ~ 255

d2 = val / 100;
val -= 100 * d2;
d1 = val  / 10;
d0 = val % 10;

bcdval = d2 << 8 + d1 << 4 + d0;

That's it.

Dora
 

I want to convert a hex value(8 bit) to BCD.Actually we do add 6 to the hex values that has lower nibbles ranging from 'A' to 'F' only or we add 6 to all the hex values greater than 0x09?
Thanking you & Regards,
Jerin.
 

Hello!

Adding 6 will indeed work for any number between 10 and 15. (A and F).
Now I would be curious about your algorithm for greater numbers.
For example 0x20 should result in 0x32 in BCD. According to what you
say, since the low nibble is 0, then you don't add anything. And since
the higher nibble is 2, you don't add anything either. Could you explain
me how you will find 0x32?

By the way is there any problem in the algorithm I suggested?
At least it is simple.

Dora.


I want to convert a hex value(8 bit) to BCD.Actually we do add 6 to the hex values that has lower nibbles ranging from 'A' to 'F' only or we add 6 to all the hex values greater than 0x09?
Thanking you & Regards,
Jerin.
 

Be careful. Adding or subtracting 6 will adjust the high or low half of a hex number to it's binary equivalent but it will not take care of overflow from one digit to the next. Please remember that any hex number above 0x64 will convert to three BCD digits not two so the result has to be saved in two bytes.

I suggest you look at PIC Microcontoller Radix Math Methods for some proven code.

Brian.
 

Actually i posted this doubt in order to make a 0-999 BCD counter.Now i'm tryin to make it a 0-99 BCD counter first so that i can display the number in two 7 segment BCD display.......
There i fin difficulty in converting the numbers with lower nibble ranging from 'A' to 'F'...... Can anyone help me in this situation?
Thanking you & regards,
Jerin.
 

Look at it this way:

0 - 9 Just keep as they are
A - F Subtract 10 and carry one to the next higher digit.

Brian.
 

Dear brian,
Can you explain with an example please? Yet i couldn't figure it out... :-(
For eg: how will you convert the numbers with lower nibble b/w 'A'to 'F' & numbers other than that but greater than 0x0F to BCD?
I'm just pondering over it.......... :?:?:
Thanking you & regards,
Jerin.
 
Last edited:

The link I gave shows how to do it in assembly language and the code can be wrapped in 'C' asm segment.

In 'C', do it like this, entering with the value in 'HEXVal':

unsigned char MSD, LSD; // Most and Least significant Digits

LSD = HEXVal & 0x0F; // isolate the lower 4 bits
if(LSD > 10) // adjust if A - F
{
LSD -= 10;
MSD++;
}
MSD += ((HEXVal & 0xF0) >> 4);

That's it for two digits but be careful if the value causes an overflow, the full range of 0x00 to 0xFF that fits in a single byte will decode to THREE BCD digits 000 to 255 so values decoding to D'99' or 0x63 will need that extra BCD digit.

Brian.
 

Dear brian,
MSD += ((HEXVal & 0xF0) >> 4);
What is the logic behind shifting the MSB to the right by 4?Also the initial values of the 2 char variables must be 0 rite?
if(LSD > 10) // adjust if A - F
{
LSD -= 10;
MSD++;
}
Here each time when MSD increments do we have to initialize MSD to 0 after it has incremented & added?
Regards,
Jerin.

---------- Post added at 06:29 ---------- Previous post was at 04:58 ----------

Got it Brian.........!!!!!!!!!!!!
Thank you very much for you ideas........!!!!!!!!!! :)
The code is as follows:
B]Counter from 0-99[/B]

char i=0,key = 0,a = 0,keyval = 0,
val[] = {0x10,0x20,0x30,0x40,0x50,0x60,0x70,0x80,0x90};
short int temp = 0,keytemp = 0;
void main()
{
ADCON1 = 0x06;
TRISE = 0x01;
TRISD = 0x00;
PORTD = 0x00;
loop:
if(PORTE.f0 == 0)
{
Delay_ms(150);
if(PORTE.f0 == 0)
{
do
{
Delay_us(100);
}while(PORTE.f0 == 0);
a += 1;
if(a > 0x99)
{
temp = 0;
i = 0;
a = 0;
goto end;
}
if(a == val)
{
a += 6;
i++;
}
keyval = a;
keyval = keyval/16; //MSB
keytemp = a%16; //LSB
if(keytemp > 0x09)
{
keytemp -= 10;
keyval++;
}
keyval = keyval<<4;
temp = keyval + keytemp;
end:
key = temp;
PORTD = key;
}
}
goto loop;
}

It is working BEAUTIFULLY.............!!!!!!!!!!!!!
Thanks to all for their reply................
Regards,
Jerin. ;-)
 

Ugh! you use a 'goto' in C code - but I'll forgive you!

Incidentally, >>4 is the same as dividing by 16 but the compiler will normally make it from shift instructions instead of using division routines so in most cases it makes smaller and quicker code.

Brian.
 

Best practice is to structure you program so there are no 'jumps' at all except for calls to functions.
The trouble with 'goto' is it is very easy to end up in the wrong place, especially if you modify code between the goto instruction and the label it points to. Also be careful if you jump into or out of a function, although it is legal in 'C' you can easily crash your program if you unbalance the processor stack.

In your program, consider using a 'while' loop to make it repeat instead of 'goto'ing back to the start of the program and consider using the 'break' function to leave when the value reaches 0x99.

I'm not telling you you are wrong, just suggesting a safer way to write your program.

Brian.
 

Hello!

It is ALWAYS possible to write code without goto. I have never used a single
goto in many years of programming. The problem of the goto statement is
that it allows you to jump from anywhere to anywhere else.

Let's take a look at your code:
You have a loop label and a goto loop at the end of the program. Why not
replacing this by a
Code:
while(1) {
    // Insert your loop code here.
}
As for the second goto:
You test if a is greater than 0x99, in which case you reset everything
and then jump to the label.

Code:
Why not doing:

			if(a > 0x99) {
				temp = 0;
				i = 0;
				a = 0;
			}
			else {  // This area is not entered if a > 0x99
				if(a == val[i])	{
					a += 6;
					i++;
				}
				keyval = a;
				keyval = keyval/16; //MSB
				keytemp = a%16; //LSB
				if(keytemp > 0x09) {
					keytemp -= 10;
					keyval++;
				}
				keyval = keyval<<4;
				temp = keyval + keytemp;
			}
			key = temp;
			PORTD = key;

As you can see, in case you have a > 0x99, you initialize everything
and then you skip all the code which is in the else part which is equivalent
to what you did.

Dora.

Is there any other function for goto in C?
Regards,
Jerin.
 

Ya. Thanx to both Dora & Brian too.....
Now i'm on my way to make a 0-999 BCD counter. After i have completed that i will post it here in the forum.
Thanking you & regards,
Jerin. ;-)
 

Here is the code for 0-999 BCD counter:

char i = 0,j = 0,k = 0;
int a = 0,key = 0;
void main()
{
ADCON1 = 0x06;
TRISE = 0x01;
TRISD = 0x00;
TRISC = 0x00;
PORTC = 0;
PORTD = 0x00;
while(1)
{
if(PORTE.f0 == 0) //Polling for pin0 of PORTE(Button on pin0 of PORTE)
{
Delay_ms(150);
if(PORTE.f0 == 0)
{
do
{
Delay_us(100);
}while(PORTE.f0 == 0);
a += 1;
if(a == 0x03E8) //Hex value for 1000 in BCD
{
a = 0; //Clear the vlaue to 0
}
key = a;
i = key/100; // 1st digit
key = key%100;
j = key/10; // 2nd digit
key = key%10;
k = key; // 3rd digit
PORTC = i;
j = j<<4;
j = j + k;
PORTD = j;
}
}
}
}

Regards,
Jerin. ;-)
 

You will find the resulting hex file is bigger than it needs to be because of the divide and modulus instructions but the mathematics is good. 'C' compilers use libraries which can be quite large, in order to do division it will probably load the whole maths library which will result in bigger code. It is more efficient to use logic rather than arithmetic functions but if you have plenty of memory space left it isn't a problem.

Brian.
 

Status
Not open for further replies.

Similar threads

Part and Inventory Search

Welcome to EDABoard.com

Sponsor

Back
Top