Hex to Ascii routine wanted

Thread Starter

MaxHeadRoom

Joined Jul 18, 2013
28,699
Anyone have, or know of a 16bit hex to ASCII conversion routine in assembly for the PIC18F?
Especially if it takes advantage of the extra commands of the 18F, MUL etc.
I have found a few out there, but most seem to have a glitch of some kind?
Thanks.
Max.
 

Thread Starter

MaxHeadRoom

Joined Jul 18, 2013
28,699
Convert to individual ASCII digits for LCD display.
HEX 0x0156 -> ASCII (decimal 342) 33, 34, 32
Thanks.
Max.
 
Last edited:

kubeek

Joined Sep 20, 2005
5,795
I never saw a PICs isnctruction set, but it basically goes like this:
Take the highest nibble from the number (higherst 4 bits)
if the nibble is lower than 10, then add 48 and print
else add 55 and print
shift the whole number left by 4 bits and repeat everything 4 times

I am not sure if you can manipulate a whole 16bit number in one operation, so you might need to make the shift left to work with two bytes, that is usually done through a carry bit or similar.
Do you have any goals for efficiency and speed, or does it just need to work somehow?
 

Thread Starter

MaxHeadRoom

Joined Jul 18, 2013
28,699
I would like it as fast as possible, that is why I wanted to take advantage of the higher instruction set of the 18f.
I may have to re-work some of the ones I have tried so far.
Max.
 

kubeek

Joined Sep 20, 2005
5,795
My guess is it will take roughly 20 instructions to translate the 16bit number into ascii. Don´t know how often you would use this, but I bet it is way faster than your lcd routine, and shaving a few instrucions will not matter much.
 

ErnieM

Joined Apr 24, 2011
8,377
While technically not a part of the standard C library, many compiler packages host a function ltoa() for long to ASCII. It mirrors the standard function atol().

You can Google ltoa and find many examples, the the translate C to asm.

I will not guess why you would not simply compile code to assembly.
 

Lourens

Joined Jul 16, 2012
15
Hi MaxHR
i have available two routines in pic18 asm that will convert a signed and unsigned 16bit number to their ascii representation. They are part of the library for a graphical programming IDE i call VPS_P18. Here is the code for the unsigned value conversion to give you an idea. For the signed conversion the code is longer. How do i get the source files to you?
UINTtoASCII:
lfsr FSR1,ApplStack ; Flush application stack
movff POSTINC0, POSTINC1 ; Push Value on Application Stack
movff POSTINC0, POSTINC1 ; ...
call Word2asci ; Convert value to ASCII
movff FSR1L,FSR0L ; FSR0 point to string start
movff FSR1H,FSR0H ; ..
StkAddStackPtr -2 ; Clean-up application stack
return ;
 

John P

Joined Oct 14, 2008
2,026
Convert to individual ASCII digits for LCD display.
HEX 0x0156 -> ASCII (decimal 342) 33, 34, 32
Thanks.
Max.
The title says "Hex to Ascii routine wanted" but this is actually a conversion to decimal combined with output as ASCII. The decimal conversion will probably take most of the work.
 

John P

Joined Oct 14, 2008
2,026
Convert to individual ASCII digits for LCD display.
HEX 0x0156 -> ASCII (decimal 342) 33, 34, 32
Thanks.
Max.
The title says "Hex to Ascii routine wanted" but this is actually a conversion to decimal combined with output as ASCII. The decimal conversion will most likely take most of the work.

Coding for this may be more efficient if you know ahead of time what the range of the data can be--or is it all the way from 0x0000 to 0xFFFF?
 

John P

Joined Oct 14, 2008
2,026
So what you want isn't 16-bit conversion but 13 bits, with output 0-6000, or maybe 0-5999.

One starting point would be to note that if the top bit is set, the thousands place is going to be 4, 5 or 6, and you could test for those.
 

THE_RB

Joined Feb 11, 2008
5,438
Convert to individual ASCII digits for LCD display.
...
An easy way would be to mask off the bottom byte with 0b00001111 so you get a new nibble value in the range 0-15. Then use a standard computed jump table to RETLW with the ASCII value in the char range 0-9 or A-F.

After that you do a dual-byte bit shift (two RRF instructions) done 4 times, which moves the 16bit variable to the right 4 bits and loads the next nibble. Then rinse and repeat. The whole thing should be only a handful of lines of ASM code and the 16 byte lookup table.

A minor issue is that it outputs the 4 HEX digits starting from the LSN but that is not much of a drama you can just display the 4 characters on the LCD going from right to left.
 

MMcLaren

Joined Feb 14, 2010
861
Hi Max'...

I wonder if you're lookin' for something like this routine which produces packed BCD digits which are easily converted to ASCII? The 16-bit input is placed in the 16 bit "bin" variable (little endian format) before calling the routine and the four digit packed BCD output is located in the 16 bit "bcd" variable (little endian format) on exit. Do you know how to convert the packed BCD digits to ASCII for sending to the LCD?

This routine is for 14-bit core devices. I have a routine for 16-bit core devices too, which is smaller/quicker. I'll post it in a subsequent post, as soon as I find it...

Regards, Mike

Rich (BB code):
  /********************************************************************
   *  16-bit "bin" to 4-digit packed "bcd" (26 words, 340 cycles)     *
   *                                                                ***/
   void bin2bcd()               // destroys "bin" input
   { asm clrf   _bcd+0          // clear bcd output variable
     asm clrf   _bcd+1          //   "
     asm movlw  0x10            //
     asm movwf  _bitctr         // bitctr = 16
   lp1:
     asm movlw  0x33            // Mike Keitz's "bcd adj" method
     asm addwf  _bcd+0,F        //
     asm btfsc  _bcd+0,3        // test if lo result > 7
     asm andlw  0xF0            // lo result > 7 so take the 3 out
     asm btfsc  _bcd+0,7        // test if hi result > 7
     asm andlw  0x0F            // hi result > 7 so ok
     asm subwf  _bcd+0,F        // any results <= 7, subtract back
     asm movlw  0x33            //
     asm addwf  _bcd+1,F        //
     asm btfsc  _bcd+1,3        // test if lo result > 7
     asm andlw  0xF0            // lo result > 7 so take the 3 out
     asm btfsc  _bcd+1,7        // test if hi result > 7
     asm andlw  0x0F            // hi result > 7 so ok
     asm subwf  _bcd+1,F        // any result <= 7, subtract back
     asm rlf    _bin+0,F        // get another bit
     asm rlf    _bin+1,F        //
     asm rlf    _bcd+0,F        //
     asm rlf    _bcd+1,F        //
   //asm rlf    _bcd+2,F        // (for 5 digit output up to 65535)
     asm decfsz _bitctr,F       // done? yes, skip, else
     asm bra    lp1             //
   }                            //
 
Last edited:

MMcLaren

Joined Feb 14, 2010
861
Hi Max':

Here's a version for 18F (16 bit core) devices that's a bit smaller/faster;

Regards, Mike

Rich (BB code):
;******************************************************************
;
;  Bin2Bcd 16 bit binary to 4 digit packed BCD
;
;  Number Range: 0000..270F (0000..9999)
;
;  17 words, 215 cycles (including call and return)
;
BCD     equ     0x30            ; 16 bit little endian
BIN     equ     0x32            ; 16 bit little endian

        radix dec
Bin2Bcd
        clrf    BCD+0           ; LSB..MSB
        clrf    BCD+1           ;
        movlw   16              ;
        movwf   BitCtr          ;
CnvtBit
        rlcf    BIN+0,F         ; LSB..MSB
        rlcf    BIN+1,F         ;
        movf    BCD+0,W         ;
        addwfc  BCD+0,W         ;
        daw                     ;
        movwf   BCD+0           ;
        movf    BCD+1,W         ;
        addwfc  BCD+1,W         ;
        daw                     ;
        movwf   BCD+1           ;
        decfsz  BitCtr,F        ;
        bra     CnvtBit         ;
        return                  ;
 
Last edited:

t06afre

Joined May 11, 2009
5,934
That conversion function is standard in the Microchip C8 compiler. Can not remember what they call it. And I am not sitting a computer with C8 right now. But it is in the manual
 
You would be better working it out for yourself.
It really is not hard to do.
Just work from the top nibble and convert to ascii one nibble at a time.

If you cant do this simple task then you are going to struggle with the pic.
 
Top