Home > other >  Displaying a single numeric digit as a string
Displaying a single numeric digit as a string

Time:11-22

I am writing to an LCD and have developed the drivers to accept a string input for the value. I have a variable called "cycles" that is a uint16. I need to convert that value to a string and write it to the display. My string write function prototype is as follows:

void lcd_string(uint8_t column, uint8_t page, const uint8_t *font_address, const char *str)

My way of displaying the value is to break the value into individual digits and write them individually to the display at the proper position.

I have the following code that works for what I want to do, but I would like to eliminate the long if/else if statement if possible.

loop = 0;
while (cycles_1 > 0) {
                        
    temp = cycles_1 % 10;
                    
    if (temp == 9) lcd_string(36 - (6 * loop),6,font_6x8_num,"9");
    else if (temp == 8) lcd_string(36 - (6 * loop),6,font_6x8_num,"8");
    else if (temp == 7) lcd_string(36 - (6 * loop),6,font_6x8_num,"7");
    else if (temp == 6) lcd_string(36 - (6 * loop),6,font_6x8_num,"6");
    else if (temp == 5) lcd_string(36 - (6 * loop),6,font_6x8_num,"5");
    else if (temp == 4) lcd_string(36 - (6 * loop),6,font_6x8_num,"4");
    else if (temp == 3) lcd_string(36 - (6 * loop),6,font_6x8_num,"3");
    else if (temp == 2) lcd_string(36 - (6 * loop),6,font_6x8_num,"2");
    else if (temp == 1) lcd_string(36 - (6 * loop),6,font_6x8_num,"1");
    else if (temp == 0) lcd_string(36 - (6 * loop),6,font_6x8_num,"0");
                    
    cycles_1 /= 10;
    loop  ;
                
}

I tried the following but the string was not writing to the display.

loop = 0;
while (cycles_1 > 0) {
                        
    temp = cycles_1 % 10;
                    
    lcd_string(36 - (6 * loop),6,font_6x8_num,{0x30   temp, '\0'});
                    
    cycles_1 /= 10;
    loop  ;
                
}

I figured adding 0x30 to the temp value would convert it to an ASCII number and then I would terminate it with a null termination character, but this doesn't seem to be working. Any suggestions of what I might try?

CodePudding user response:

If you have a number named temp between 0 and 9, you can convert it to a 1-character C string with a null terminator using this code:

char str[2] = { '0'   temp };

There is no need to have a separate case for each digit.

CodePudding user response:

As you tagged the question [avr], you are using GNU tools for AVR, which use AVR-LibC as their libc implementation. It provides utoa which converts an unsigned (which is uint16_t) to string. Notice that utoa is non-standard.

#include <stdlib.h>
#include <stdint.h>
...
    uint16_t cycles_1 = 12345;
    char buf[6];
    utoa (cycles_1, buf, 10);
    lcd_string (..., buf, ...);

In case cycles_1 is a 16-bit signed type, there is itoa.

utoa and itoa are implemented in assembly; they are fast and have a small foot-print. They don't use division or modulo.

If you really want to output each character individually, you can

    char buf[2], var = 3;
    
    buf[1] = '\0';
    buf[0] = '1';       lcd_string (..., buf, ...);
    buf[0] = '2';       lcd_string (..., buf, ...);
    buf[0] = '0'   var; lcd_string (..., buf, ...);
    ...

or, using it with your code:

uint8_t loop = 0;
while (cycles_1 > 0)
{
    char temp = cycles_1 % 10;
    char str[2] = { '0'   temp, 0 };
                   
    lcd_string (36 - loop, 6, font_6x8_num, str);
    cycles_1 /= 10;
    loop  = 6;
}

Notice however that this is slow and expensive, as it need division (and perhaps also modulo) for each digit.

  • Related