# Hex number to ascii character

Status
Not open for further replies.

#### rrb011270

##### New Member
Hi

I have an 8bytes data in an array, say array1[8] which contains the ff:
0xF1 0xDD 0x66 0x04 0xA3 0xDE 0x9B 0x0D ---> all in hex

I want to convert this data into ascii as:
F1DD6604A3DE9B0D ---> all in ascii character stored in an array2[16]

BTW, I am using this routine for my small project with PIC18F452.

Anyone in the community who can provide help, snippet or any info in ANSI C.

Thank u.

#### Nigel Goodwin

##### Super Moderator
rrb011270 said:
Hi

I have an 8bytes data in an array, say array1[8] which contains the ff:
0xF1 0xDD 0x66 0x04 0xA3 0xDE 0x9B 0x0D ---> all in hex

I want to convert this data into ascii as:
F1DD6604A3DE9B0D ---> all in ascii character stored in an array2[16]

BTW, I am using this routine for my small project with PIC18F452.

Anyone in the community who can provide help, snippet or any info in ANSI C.

Thank u.

I can't help you with C code, I never use it. But here's code for displaying hex on an LCD from my tutorials - it could very easily be altered to do what you need:
Code:
LCD_HEX	movwf	tmp1	;display W as hexadecimal byte
swapf	tmp1,	w
andlw	0x0f
call	HEX_Table
call	LCD_Char
movf	tmp1, w
andlw	0x0f
call	HEX_Table
call	LCD_Char
retlw	0x00

HEX_Table
RETLW   0x30
RETLW   0x31
RETLW   0x32
RETLW   0x33
RETLW   0x34
RETLW   0x35
RETLW   0x36
RETLW   0x37
RETLW   0x38
RETLW   0x39
RETLW   0x41
RETLW   0x42
RETLW   0x43
RETLW   0x44
RETLW   0x45
RETLW   0x46

#### Exo

##### Active Member
Code:
for (Loop = 0; Loop < 8; Loop++)
{
Temp = (Array1[Loop] & 0xF0) >> 4;
if (Temp < 10)
Array2[Loop * 2] = Temp + 48;
else
Array2[Loop * 2] = Temp + 55;

Temp = (Array1[Loop] & 0x0F)
if (Temp < 10)
Array2[(Loop * 2) + 1] = Temp + 48;
else
Array2[(Loop * 2) + 1] = Temp + 55;
}

#### Nigel Goodwin

##### Super Moderator
Hi Exo,

As a matter of interest, how much code does that generate?.

#### crust

##### Member
that will depend on the architecture ... on a VAX probably not much as it had tons of string manipulation instructions. On a RISC processor it will generate more. The C version might have a bit longer execution time, but it computes the values algorithmically, whereas the assembly version is probably faster but occupies more space due to the look-up table.

#### Exo

##### Active Member
Nigel Goodwin said:
Hi Exo,

As a matter of interest, how much code does that generate?.

I don't know, I don't use C to program pic's... I use C++ on the pc, but the code should work on a pic (if the compiler is decent)

#### Nigel Goodwin

##### Super Moderator
Exo said:
Nigel Goodwin said:
Hi Exo,

As a matter of interest, how much code does that generate?.

I don't know, I don't use C to program pic's... I use C++ on the pc, but the code should work on a pic (if the compiler is decent)

Right, the assembler code I posted above takes 26 bytes (including the lookup table) - and will run correspondingly fast (15uS or so at 4MHz, not counting the LCD display time). I suspect the C code will take a great deal more space, and run a great deal slower. Perhaps someone would like to try it?, I'd certainly be interested to see how a C compiler copes with a simple job like this - although really it's not a good test, as it's not a time critical routine.

#### Exo

##### Active Member
I just tried to compile it with C2C pic c compiler...
140 words for a 16F84A :shock:

Putting the temp + 48... part into a function (because it's two times the same) saves 28 words ... still 112 :?

#### Nigel Goodwin

##### Super Moderator
Exo said:
I just tried to compile it with C2C pic c compiler...
140 words for a 16F84A :shock:

Putting the temp + 48... part into a function (because it's two times the same) saves 28 words ... still 112 :?

It's hardly a fair comparison though - your C solution was written regardless of space used, my assembler solution was written with speed and shortness of code in mind - and was a lot easier to write than your C algorithm would have been in assembler!.

#### Exo

##### Active Member
indeed, I think the multiplications in the C routine take up most the space...

still, it's quite big, doing it in assembler the same way directly certainly wouldn't need 140 words.
Again this shows the biggest downfall of hi-level compilers on pics. The easyness of multiplying, dividing, ... makes the programmer use it quite often, not realising it will generate tons of code...

#### crust

##### Member
That sounds long for that piece of C code. First any reasonable compiler should recognize that *2 is a left bit shift and not perform the multiplication. Further, the c code actually did a bit more in that it included the loop over the array and the loop was unrolled so that there would not be a branch penalty. In some of my imaging algorithms, I often unroll the loops to get a bit better performance at the expense of space (there is also a cache issue, but that is not int he scope of this discussion).

#### crust

##### Member
I rolled a test version similar to the ASM routine posted (sans the lookup table), using my C compiler consumed 30 words including the argument push and pop from the stack.

#### Nigel Goodwin

##### Super Moderator
crust said:
I rolled a test version similar to the ASM routine posted (sans the lookup table), using my C compiler consumed 30 words including the argument push and pop from the stack.

How about posting your source code, and the assembler it produces?. Certainly 30 words looks more like it!.

#### crust

##### Member
Here is the code from my compiler. Note that as is often the case, it is difficult to do an apples to apples comparison because some people want speed, others want space, some would rather not have to allocate an extra temp buffer, etc. I used the AVR in this example since the instruction set is similar to the PICs (and that is one of the compilers I have).

Code:
char btohex(unsigned char x)
{
return (x>9 ? x+55 : x+48);
}

void atohex(unsigned char x, char a[])
{
a[1] = (btohex(x&0xF));
a[0] = (btohex(x>>4));
}

Code:
0000004a <btohex>:
4a: 8a 30          cpi   r24, 0x0A   ; 10
4c: 10 f0          brcs  .+4         ; 0x52
4e: 89 5c          subi  r24, 0xC9   ; 201
50: 01 c0          rjmp  .+2         ; 0x54
52: 80 5d          subi  r24, 0xD0   ; 208
54: 99 27          eor   r25, r25
56: 87 fd          sbrc  r24, 7
58: 90 95          com   r25
5a: 08 95          ret

0000005c <atohex>:
5c: ef 92          push  r14
5e: ff 92          push  r15
60: 1f 93          push  r17
62: 18 2f          mov   r17, r24
64: e6 2e          mov   r14, r22
66: f7 2e          mov   r15, r23
68: 8f 70          andi  r24, 0x0F   ; 15
6a: ef df          rcall .-34        ; 0x4a
6c: ff 2d          mov   r31, r15
6e: ee 2d          mov   r30, r14
70: 81 83          std   Z+1, r24 ; 0x01
72: 12 95          swap  r17
74: 1f 70          andi  r17, 0x0F   ; 15
76: 81 2f          mov   r24, r17
78: e8 df          rcall .-48        ; 0x4a
7a: ff 2d          mov   r31, r15
7c: ee 2d          mov   r30, r14
7e: 80 83          st Z, r24
80: 1f 91          pop   r17
82: ff 90          pop   r15
84: ef 90          pop   r14
86: 08 95          ret

If I decide to optimize a bit, here is what I come up with, 22 words.

Code:
void atohex(unsigned char x, char a[])
{
char y = x&0xf;
a[1] = (y>9 ? y+55 : y+48);
y = x>>4;
a[0] = (y>9 ? y+55 : y+48);
}

Code:
0000005c <atohex>:
5c: f7 2f          mov   r31, r23
5e: e6 2f          mov   r30, r22
60: 98 2f          mov   r25, r24
62: 9f 70          andi  r25, 0x0F   ; 15
64: 9a 30          cpi   r25, 0x0A   ; 10
66: 14 f0          brlt  .+4         ; 0x6c
68: 99 5c          subi  r25, 0xC9   ; 201
6a: 01 c0          rjmp  .+2         ; 0x6e
6c: 90 5d          subi  r25, 0xD0   ; 208
6e: 91 83          std   Z+1, r25 ; 0x01
70: 98 2f          mov   r25, r24
72: 92 95          swap  r25
74: 9f 70          andi  r25, 0x0F   ; 15
76: 9a 30          cpi   r25, 0x0A   ; 10
78: 1c f0          brlt  .+6         ; 0x80
7a: 89 2f          mov   r24, r25
7c: 89 5c          subi  r24, 0xC9   ; 201
7e: 02 c0          rjmp  .+4         ; 0x84
80: 89 2f          mov   r24, r25
82: 80 5d          subi  r24, 0xD0   ; 208
84: 80 83          st Z, r24
86: 08 95          ret

#### ivancho

##### New Member
I thought he meant that he need it something like this.
IF the ByteArrray[1] = F1 hex, then transfomr that, to a word array with ASCII F and 1, so that ASCII F would be in the high byte of the word and the ASCII 1 would be on the low byte of the word. (WordArray[1] = 01000110 00110001).... and do that for all of the 8 components of the array. That was what I got... and this is the code I got PICBASIC Pro.

Code:
X VAR BYTE
num8 VAR BYTE[7]
numascii VAR WORD[7]
NumVar VAR BYTE
NumChanged VAR BYTE

For X = 0 TO 7
NumVar = num8[X] >> 4  'same as / 16   (breaking number if F1 to F only)
GoSub hex2ascii
numascii[x] = NumChanged >> 8    'same as * 32   ('Shifting to upper byte)

NumVar = num8[X] && 00001111  '(breaking number if F1 to 1 only)
GoSub hex2ascii
numascii[x] = numascii[x] + NumChanged     'Adding lower byte

Next X

hex2ascii:

IF NumVar > 9 Then
NumChanged = NumVar + 55
Else
NumChanged = NumVar + 48
EndIF
Return

It compile to 128 words for a 16F876 but notice the use of an array with 8 components byet size and one array 8 components word size. They are not just floating around...... Nigel a ASM code like this one, what would it look like?

#### Nigel Goodwin

##### Super Moderator
ivancho said:
It compile to a huge 167 words but notice the use of an array with 8 components byet size and one array 8 components word size. They are not just floating around...... Nigel a assembly code like this one, what would it look like?

It would be a LOT bigger than the original code I posted, one reason is the maths functions it uses - you would need to write those (or download them), and call them as subroutines. By using a simple 16 byte lookup table it makes mine very small and very fast - and no maths required :lol:

#### crust

##### Member
Likewise, there was no math in the c solutions or their assembly derivatives posted either. Math other than addition, subtraction, shifts, or and/modulo, on a small cpu like that can eat lots of space and time.

Status
Not open for further replies.

Replies
14
Views
6K
Replies
7
Views
3K
Replies
4
Views
2K
Replies
22
Views
4K
Replies
0
Views
918