We are running a survey to help us improve the experience for all of our members. If you see the survey appear, please take the time to tell us about your experience if you can.
I am trying to use the following code to convert 2 digit ASCII numbers to BCD number, for setting RTC Clock DS1307.
unsigned char ASCII_TO_BCD(unsigned char ascii_text[2]) { unsigned char bcd_value; ascii_text[0] &= 0x0F; // set high nibble(3) to 0 (may not be needed) ascii_text[0] <<= 4; // shift lower nibble to higher ascii_text[1] &= 0x0F; // set high nibble(3) to 0 (may not be needed) bcd_value = ascii_text[0] | ascii_text[1]; // mix both to get BCD return bcd_value; }
When I pass '12' to the function, 0x33 is returned instead of 0x12. Is something wrong in this code? Thanks.
use "-'0'" to convert ASCII characters to numbers ('1' ->1, 'n'->n), on which the BCD transform should be made - not the ASCII values themselves!
try this.
unsigned char ASCII_TO_BCD(unsigned char ascii_text[2]) { unsigned char bcd_value; // left side if(ascii_text[0] >= '0' && ascii_text[0] <= '9') // 0-9 range { bcd_value = ( ascii_text[0] - 48) << 4 ; // 48 for '0' ASCII offset } else if (ascii_text[0] >= 'A' && ascii_text[0] <= 'F') // A-F range { bcd_value = ( 10 + ascii_text[0] - 65 ) << 4 ; // 65 for 'A' ASCII offset } else if (ascii_text[0] >= 'a' && ascii_text[0] <= 'f') // a-f range { bcd_value = ( 10 + ascii_text[0] - 97) << 4 ; // 97 for 'a' ASCII offset } // right side if(ascii_text[1] >= '0' && ascii_text[1] <= '9') // 0-9 range { bcd_value |= ( ascii_text[1] - 48); // 48 for '0' ASCII offset } else if (ascii_text[1] >= 'A' && ascii_text[1] <= 'F') // A-F range { bcd_value |= ( 10 + ascii_text[1] - 65) ; // 65 for 'A' ASCII offset } else if (ascii_text[1] >= 'a' && ascii_text[1] <= 'f') // a-f range { bcd_value |= ( 10 + ascii_text[1] - 97 ) ; // 97 for 'a' ASCII offset } return bcd_value; }
Thank you Sir! It is perfectly working. I am not using the alphabets a-f or A-F. Only numbers are used. So I tried skipping the 'if-else if', but it is not working. I will use the code as it is for now, & will study it later on.
unsigned char bcd_value; bcd_value = ( ascii_text[0] - 48) << 4 ; // 48 for '0' ASCII offset bcd_value |= ( 10 + ascii_text[1] - 97 ) ; // 97 for 'a' ASCII offset return bcd_value;
I am also not getting why my code(which I posted) was not working. Anyway, THANK YOU VERY MUCH.
It is possible to appease a crocodile? Imagine the swarms of lazy, stupid, uneducated and rude idiots that are going to come down here asking for free code now that they see such a noble act of charity. Well done christian crosa, well done.
No Sir, I am not asking for free code. If you have read my post properly, I was asking to spot the mistake in my code. I even don't use any code in my design until I understand it. That's why I specially mentioned that I will use the code as it is for now, & will study it later on.
I was not specifically referring to you.
Now if you only use digits (0..9) - why then did you suddenly include the one line that makes use of character 'a' and was intended for the hexadecimal range 'a' .. 'f'?
Next thing - the guy who did give you example code does something I don't like:
bcd_value = ( ascii_text[0] - 48) << 4 ; // 48 for '0' ASCII offset
ascii_text contains characters ('0', '1', ... '9') 48 is a magic number that requires the comment "48 for '0' ASCII offset".
So a comment is explicitly needed just because the code is mixing between characters and the ordinal numbers of characters.
It is way better to write:
bcd_value = ( ascii_text[0] - '0') << 4 ;
Suddenly, no comment is needed since there is no longer any magic value 48 to explain.
There is a big reason why the C language allows us to perform mathematical operations directly using characters.
Thanks Per, I had used wrong line of code. I also changed 48 to '0'. Certainly it is more readable & understandable.
No problem.
Try some other arguments besides "12", and maybe you'll notice a pattern...
It fails because of the difference between what you think an array-type function argument as in
void func(int in[2])
does, and what actually happens. You believe this behaves vaguely like
void func(int in1, int in2)
while it really is equivalent to
void func(int *in)
I'll also venture an educated guess that in the actuall call of your function, which you didn't show, the argument is a string literal, i.e. it looks like this:
result = asciitobcd("12");
, and that changing the call to
{ unsigned char tempstr[] = "12"; result = asciitobcd(temp);}
magically cures it.
A note to the experts in here: please don't spoil the OP's a-ha! experience. Let him figure this one out for himself.