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.

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.
 
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
               ADDWF   PCL       , f
            	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
 
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;
}
 
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.
 
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)
 
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.
 
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 :?
 
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!.
 
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...
 
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).
 
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.
 
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!.
 
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
 
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?
 
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:
 
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.

New Articles From Microcontroller Tips

Back
Top