Convert two ASCII Hexadecimal Characters (Two ASCII bytes) in one byte
Solution 1
i can't make sense of your examples, but if you want to convert a string containing hexadecimal ascii characters to its byte value (e.g. so the string "56" becomes the byte 0x56, you can use this (which assumes your system is using ASCII)
uint8_t*
hex_decode(const char *in, size_t len,uint8_t *out)
{
unsigned int i, t, hn, ln;
for (t = 0,i = 0; i < len; i+=2,++t) {
hn = in[i] > '9' ? in[i] - 'A' + 10 : in[i] - '0';
ln = in[i+1] > '9' ? in[i+1] - 'A' + 10 : in[i+1] - '0';
out[t] = (hn << 4 ) | ln;
}
return out;
}
You'd use it like e.g.
char x[]="1234";
uint8_t res[2];
hex_decode(x,strlen(x),res);
And res (which must be at least half the length of the in
parameter) now contains the 2 bytes 0x12,0x34
Note also that this code needs the hexadecimal letters A-F to be capital, a-f won't do (and it doesn't do any error checking - so you'll have to pass it valid stuff).
Solution 2
You can use strtol()
, which is part of avr-libc, or you can write just your specific case pretty easily:
unsigned char charToHexDigit(char c)
{
if (c >= 'A')
return c - 'A' + 10;
else
return c - '0';
}
unsigned char stringToByte(char c[2])
{
return charToHexDigit(c[0]) * 16 + charToHexDigit(c[1]);
}
Loïc G.
I'm a hobbyist programmer. I mostly use Python but also PHP, Javascript (JQuery). As well, I'm a hobbyist electronician and I use C with avr-gcc to program microcontrollers such as Atmel AVR.
Updated on July 19, 2022Comments
-
Loïc G. almost 2 years
I want to convert two ASCII bytes to one hexadecimal byte. eg.
0x30 0x43 => 0x0C , 0x34 0x46 => 0x4F
...The ASCII bytes are a number between
0
and9
or a letter betweenA
andF
(upper case only), so between0x30
...0x39
and0x41
...0x46
I know how "to construct"
0x4F
with the numbers0x34
and0x46 : 0x4F = 0x34 * 0x10 + 0x46
So, in fact, i would to convert one ASCII byte in hexadecimal value.
For that, i can build and array to assign the hexadecimal value to the ASCII char :
0x30 => 0x00 0x31 => 0x01 ... 0x46 => 0x0F
But, maybe it have a most « proper » solution.
The program will be run on an AVR µC and is compiled with
avr-gcc
, soscanf()
/printf()
solutions aren't suitable.Have you got an idea ? Thanks
-
Loïc G. over 12 yearsOk, it was so easy ... I thought to the 4 bits left rotation for the number between 0 to 9 but the solution was even simpler ! Thanks
-
Loïc G. over 12 yearsIt was a joke ? : $ man ascii Aucune entrée de manuel pour ascii
-
Adam Rosenfield over 12 years@Loic: No, you must be missing the manual page. Here's the English version: linux.die.net/man/7/ascii
-
R.. GitHub STOP HELPING ICE over 12 yearsUse
(in[i]|32)-'a'+10
and now you can support uppercase and lowercase (with just one more instruction in the machine code, most likely). -
Rudy Velthuis over 12 yearsIsn't
uint8_t
a byte? Shouldn't that beuint16_t
if it is supposed to contain two bytes? -
nos over 12 years@Rudy Velthuis It's supposed to be a byte, since it contains 1 byte, not 2
-
Rudy Velthuis over 12 years@nos: yes, I see it is an array of uint8_t. Brain fart, sorry.
-
Dmitry about 9 yearsinline uint8_t asciiToByte(char c) { if (c >= '0' && c <= '9') return c - '0'; if (c >= 'A' && c <= 'F') return c - 'A' + 10; return 0; }
-
ojblass about 8 yearsMake sure to include cytpe.h