This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

hexadecimal to ASCII

I am doing an ADC12 conversion and sending this value to ADC12MEM0. Once the ADC12 is complete, I am sending the ADC12MEM0 values upper and lower 8 bits to the hyperterminal.  I understand that it is simply sending the hex values in the register over as ascii, but I would like to display these values as hex on the hyperterminal. I would like to copy the register exactly as it appears to the hyperterminal (0x0FFF on ADC12MEM0 would make hyperterminal display 0x0FFF... etc.). I have looked at hex to ascii tables and I understand how this works, but I have no idea how to write this as code in code composer studio. Is there some advice you could give me or an example code I can look at to better understand. Below I have provided my code. Thanks!

# include <msp430xG46x.h>

volatile unsigned int temp;
volatile unsigned int i;


void main(void)
{
WDTCTL = WDTPW+WDTHOLD; // Stop watchdog
// Initialization of ADC12//

P6SEL |= 0x01; // Enable A/D channel A0
ADC12CTL0 &= ~ENC;
ADC12CTL0 = ADC12ON + SHT0_2 + REFON + REF2_5V+MSC; // turn on ADC12, set samp time
ADC12CTL1 = SHP+CONSEQ_2; // Use sampling timer
ADC12MCTL0 = SREF_1 + INCH_0; // Vr+=VeREF+ (external)
ADC12CTL0 |= ENC; // Enable conversions
// Initialization of Rs-232//
FLL_CTL0 |= XCAP14PF; // Configure load caps

do
{
IFG1 &= ~OFIFG; // Clear OSCFault flag
//_delay_cycles(50000); // Time for flag to set
}
while ((IFG1 & OFIFG)); // OSCFault flag still set?
P2SEL |= 0x30; // P2.4,5 = USCI_A0 RXD/TXD

UCA0CTL1 |= UCSSEL_1; // CLK = ACLK
UCA0BR0 = 0x03; // 32k/9600 - 13.65
UCA0BR1 = 0x00; //
UCA0MCTL = 0x06; // Modulation
UCA0CTL1 &= ~UCSWRST; // **Initialize USCI state machine**
IE2 |= UCA0TXIE + UCA0RXIE; // enable RXD and TXD interrupt;
while (1)
{
// ADC loop //
ADC12CTL0 |= ADC12SC; // Start conversions
//while (!(ADC12IFG & 0x0001)); // Conversion done?
temp = ADC12MEM0; // Move result
__no_operation(); // SET BREAKPOINT HERE
// RS-232 loop //
UCA0TXBUF = temp; // send lower part
__no_operation();
//while(!(IFG2 & UCA0TXIFG))
//{
//_delay_cycles(1000); // wait for first transmit
//}
UCA0TXBUF = temp >> 8;// send upper part
__no_operation();
// _delay_cycles(1000);
//UCA0TXBUF = temp;
}
}

  • printf( ... ); will do that (and a lot more than that).



  • Preston Lortie said:
    I am sending the ADC12MEM0 values upper and lower 8 bits to the hyperterminal.  I understand that it is simply sending the hex values in the register over as ascii

    No, you have a slight misunderstanding there!

    You are sending pure binary (or "hex") data, and hyperterminal is interpreting it as ASCII.

    That is, you send the hex value 0x0D, and hyperterminal thinks, "what character has ASCII code value 0x0D?", and displays that character - in this case, a Carriage Return (CR).

    0x0FFF on ADC12MEM0 would make hyperterminal display 0x0FFF

    Remember that the "0x" prefix is merely a 'C' notation to indicate that what follows is to be interpreted as a hexadecimal number - the "0x" does not exist as part of the ADC value! Therefore, if you want to see "0x" on hyperterminal, your code will have to generate those two characters.

    I have looked at hex to ascii tables and I understand how this works, but I have no idea how to write this as code in code composer studio

    'C' code is 'C' code - irrespective of what tool you use to write it!

    Is there some advice you could give me

    Write out all 16 possible values of a hex digit, 0..F, in a column.
    Then write out the ASCII codes of the 16 characters '0' to 'F' in another column alongside.
    Then look at the two columns, and see what pattern you can see between the hex digit values and the ASCII codes...

    Hint: there are actually two patterns: one for 0..9, and another for A..F

    A great deal of computer programming is about spotting patterns - so this is a very good learning exercise!

     

  • old_cow_yellow said:
    printf( ... ); will do that

    Indeed it will!

    As will  sprintf(), and a number of other functions from the standard 'C' library...

    However, the ability to represent a hex digit value as a "displayable" character is so fundamental that it is probably worth the OP learning (and understanding) now how to do it.

     (and a lot more than that).

    Indeed. But therein lies a potential problem for small embedded systems: because printf() does do such a lot more, it can significantly "bloat" the size of your code...

  • Andy Neil said:

     quote(and a lot more than that)./quote

    Indeed. But therein lies a potential problem for small embedded systems: because printf() does do such a lot more, it can significantly "bloat" the size of your code...

     HI Andy, you never was in the nerd status?

     So why not answer in an helpful manner?

     Why bother with an hidden hint and not show how hex and ascii tables are related to?

     Why also at OCW answer you replyed in a so bad look? On 46x that is plenty of flash I also use (s)printf also if I have my library to sending out hex on a one line based code.

     Sometimes guru level has to be settled down to deal with person too and understand what they want. This forum as I see is not a high level one specialized but an intermix of beginner and advanced so I hope some hint to TI are to be send to focus on what level question are to be answered.

     

  • Roberto Romano said:
    So why not answer in an helpful manner?

    There is an old saying:

    Give a man a fish, and you have fed him for one meal;

    Teach a man to fish, and you have fed him for life.

    I think that it is far more "helpful" to get the OP to think for himself than to just give him the answer "on a plate".

    Roberto Romano said:
    at OCW answer you replyed in a so bad look?

    Why do you think it's a "bad look"?

    If I had a dollar for every forum post saying, "My code is so simple (sic), but overflows the memory space - what could be wrong?"  - where the answer is the use of printf() - then I would be very rich indeed!

  • In this case, the set of values to be converted is so small (only 16), that it can easily & economically be done with just a lookup table...

  • Andy sorry but you forgot the more important part: we have to build something better, so TI probably has to think split forum to beginner/student/hobbyst/professional, this way we prepare teaching material about and we can concentrate on real colleague problem. In my point of view some library can be loaded to forum and left here with instruction on how to use, yes I agree with you our work cannot be wasted away, I decided to dedicate some free time to this formum and I do when I can.

    example:

    char bin2hex(int a)

    {

    a&=0xf;

    if(a>9)

    return('A'-1+a);

    return('0'+a);

    }

    or lookup table (tricky)

    declaration

    char BIN2HEX[]="0123456789ABCDEF";

    usage

     hexchar=BIN2HEX[a&0xf];

     I am sure these codes alone create troubles to our friend, why not release with some explanations? I agree tons of example exist but why not collect here to MSP area?

     Hint about?

  • Thanks for the replies guys, but honestly you haven't answered my question. As I have said I understand that the values being sent through serial are hex values, but are being treated as ASCII characters (and I understand the table of hex to ASCII). I am having my problem with converting these hex values to ASCII, since my program will repeatedly do an ADC conversion and send this to the hyperterminal. So my question is how do I CONTINUALLY convert the hex value to ASCII characters that will reflect the ADC12MEM0 register (and yes i understand I must put a 0x0030 and 0x0078 to get the "0x" prefix I want). My problem is mainly coding, since I know there is a way to keep reading and converting these values to ASCII without going through all 4095 different possibilities.

  • Preston Lortie said:
    my question is how do I CONTINUALLY convert the hex value to ASCII

    If you know how to do one hex value, then doing it "continually" is just a matter of doing the same thing each time you get a new value!

    ie, in pseudo-code:

    repeat:
       read a value;
       convert it to ASCII text;
       send the ASCII text

    Preston Lortie said:
    converting these values to ASCII without going through all 4095 different possibilities.

    You convert each digit in turn, to build the full string.

    As already noted, printf() will do this for you (though best not called in an ISR).

  • Preston Lortie said:

    My problem is mainly coding, since I know there is a way to keep reading and converting these values to ASCII without going through all 4095 different possibilities.

     Hi Preston, sorry to see Andy has full reason in some writing, what do you think to have a correct transfer of byte values without a supporting protocol still ascii or binary? Your code transmitted bynary codes and hyperterminal interpret it, you can store them but I think you lose some codes due to ascii control codes interpreteation. Hyperterminal is not the best program to do this and your coding style still is wrong due impossibility of select where byte start and where finish. A better approach is to use 7 bit encoding and define a start symbol grouping some bytes on a frame.

     Again what do you want to do? Hyperterminal is not good to dump binary, choose a better program or write your code.

     Transmit from MSP as HEX then add a cr lf comma or tab to separate one word from the other.

  • Preston Lortie said:

    Thanks for the replies guys, but honestly you haven't answered my question. As I have said I understand that the values being sent through serial are hex values

     Hi Preston, here is where you and Andy are in a disagree point.

     I cannot say you have reason but this is your fault: values sent to serial are BINARY values and has nothing to do with decimal hex or octal values, they are binary and hiperterminal interpret as ascii codes.

     Value 65 decimal is interpreted as 0100 0001 in binary as 'A' in ascii value 65 as decimal 0x41 in hexadecimal and o101 in octal so if you wish to print it you have to send equivalent ascii stream to serial line.

     I know about this mistake by my student fault too.

     Andy, this can clarify what is about my idea?

  • Roberto Romano said:
    Transmit from MSP as HEX

    No!

    You need to transmit ASCII-coded text strings!

    Hyperterminal is perfectly adequate to receive this.

     

    Roberto Romano said:
    add a cr lf comma or tab to separate one word from the other.

    Yes - good point!

  • Andy Neil said:

    Transmit from MSP as HEX

    No!

    You need to transmit ASCII-coded text strings!

    Hyperterminal is perfectly adequate to receive this.

    [/quote]

     Andy, sometimes you are more worst than a nerd ;)

     To all community my apologizes about HEX used instead as HEX ascii coded value representing binary value of variable, I was thinking transmitting as HEX signify transmitting a string coded from  {0..,a..f} char set from character encoding ascii or whichever is used to transmit data.

  • The thing is, when it comes to computer programming, attention to details is absolutely key!!

    If one doesn't clearly understand the difference between sending a pure biary number, and sending its text representation - then one will come unstuck!

    However, I do realise that it can be hard to express such nuances when you're having to write in a foreign language. So, please, take such clarifications just as clarifications - not as criticisms!

     

  • Alright I tried using the printf command and it would not print serially to PUTTY. I tried to do a much simpler example code using printf, and this would not work either. I am using CCS5.1. Just to be clear here is the simple printf code I am running that will not work.

    #include <stdio.h>
    void  main( void )
    {
        printf("Hello World! %i\n", 123 );
    }

    This does not output anything via serial. Is this the version of CCS I am using or do I have to do anything special to get the printf command to work?

  • Have you given up trying to do this "manually", then?

    Preston Lortie said:
    it would not print serially to PUTTY

    So you've switched from Hyperterminal - are you sure that you have PUTTY correctly configured?

    Preston Lortie said:
    do I have to do anything special to get the printf command to work?

    Note that printf() is a library function - not a "command".

    The thing with printf() is - where does the output go?
    The standard 'C' library defines it to go to stdout; on a PC, that is "the console"  - but what does that mean on a microcontroller?

    You need to check your CCS documentation to see whether there is a default, and/or whether you have to provide some "driver" for it...

    Alternatively, you could just use sprintf() to put the output into a buffer, and then send that buffer "manually"...

  • This Wiki page contains a link to the MSP430 Compiler Manual:

    http://processors.wiki.ti.com/index.php/Printf_support_in_compiler

     

  • Preston Lortie said:
    IE2 |= UCA0TXIE + UCA0RXIE; // enable RXD and TXD interrupt;

     Hi Preston, first don't enable interrupt if no service routine are in place, this can generate program restart you cannot explain why.

    Preston Lortie said:
    UCA0TXBUF = temp; // send lower part
    __no_operation();
    //while(!(IFG2 & UCA0TXIFG))
    //{
    //_delay_cycles(1000); // wait for first transmit
    //}
    UCA0TXBUF = temp >> 8;// send upper part
    __no_operation();
    // _delay_cycles(1000);
    //UCA0TXBUF = temp;

     Don't try this way build some libraries instead:

    void Putch(unsigned char ch)
    {
        while (!(IFG2&UCA0TXIFG))           // USCI_A0 TX buffer ready?
          __no_operation();
        UCA0TXBUF = ch;                     // TX -> character
    }

    void PutStr (const char * ch)
    {
       while (*ch)
          Putch(*ch++);
    }

    after that use sprintf and pass the buffer string to PutStr

    The putch routine is the basic of printf usage but use a smarter way writing some code to output:

    char mybuffer[40];

    sprintf(mybuffer,"hello world 0x%x\n",temp);

    PutStr(mybuffer);

  • While printf is convenient, it is also slow, requires lots of stack space and significantly raises the size of the binary.

    Speed is an issue if you try to send the result form within an ISR. Don't do this. You'll run into timing problems rather sooner than later.
    Stack usage is an issue on MSPs with low ram. Like the G series. Or the 1232.
    High size is a problem not only on MSPs with small flash, but even on bigger ones, it can make the generated binary larger than the allowed size for the free compiler versions. And paying several hundred bucks for a full compiler license jsut to use printf...

    However, a fast and cheap version can be implemented easily (and there is some code already posted in an older thread):

    Count, how often you can subtract 10.000 from the value before it becoems <10000. Do NOT use "/" as divisions are slooow (this also applies to "%"). Do really a loop
    for (count='0'; value>10000; count++, value-=10000);

    The '0' is not a typo! After the loop, count will directly hold the ASCII letter representing the 10k's and can be directly sent to HyperTerm.

    Then repeat for 1000, 100, 10. Finally, add '0' to the remaining value for the last digit. You'll get a 5 digit decimal number with leading zeroes. Fast and small and no stack usage.
    You can turn it into a function by passing the 'digit' value. A bit slower then, requires a bit stack, but even smaller code :) And can be used for ASCII conversions of octals or even binary numbers too :)

  • How about this

     

    static const char hex_string[] = "0123456789ABCDEF";


    void

    print_hex(uint8_t c)
    {
    char output_short[] = {"XX"};

    output_short[
    0] = hex_string[(c >> 4) & 0x0F];
    output_short[
    1] = hex_string[ c & 0x0F];

    TXString(output_short,
    2 /* sizeof(output_short) */ );
    }

  • Bruce Mitchell said:
    print_hex(uint8_t c)
    {
    char output_short[] = {"XX"};

     Hi this part generate string on stack so time and space are wasted out...

     May be better to direct transfer character calling two time the txstring:

    print_hex(uint8_t c)
    {
    TXString(hex_string[(c >> 4) & 0x0F],1);
    TXString(hex_string[ c & 0x0F],1);
    }

    //Also consider to convert bin to HEX by function:

    char bin2hexdigit(char c)

    {

    c&=0x0f; // 4 bit

     if(c>9) c+=('A'-'0'-10);   // ASCII offset from number to capital letters

    // if(c>9) c+=('a'-'0'-10);   // ASCII offset from number to small letters

    return(c+'0');  // Add character offset to binary value

    }

     The value ('A'-'0'-10) evaluate to 7 and is the  difference to add to character '0' to obtain the character 'A' when binary value is 10, compiler calculate this value but I used this form for clarity.

     also the difference between small and capital is 32 so to convert to hex with small letter need add 39 -> ('a'-'0'-10) instead of 7

  • Hi Roberto

    I think use sprintf will increase more memory size

    You can try use a sub-function like this...

    //in while loop

    TX_Byte((uint8_t)uartBuffer[0]); //Byte0, Carriage return
    uartBuffer[0] = 0x0D;

    //HexToASCII

    void TX_Byte (uint8_t TX_DATA)
    {
    while (!(IFG2&UCA0TXIFG)); // USCI_A0 TX buffer ready?
    UCA0TXBUF = (unsigned char *)TX_DATA; // TX_DATA
    }

    Best Regards,

**Attention** This is a public forum