Search code examples
cmicrocontroller

How to Convert unsigned long int to char to show on LCD in C


I have a variable that should be converted to character to show on LCD, my problem is when I convert this integer to char with sprintf it shows wrong number, every number more than 4 lengths shows incorrect It only shows numbers under length 4 correctly.

my microcontroller is ATmega16a IDE is CodeVisionAVR and the language is C

unsigned long int username;
char show[20];

unsigned long int ScanKey(void)
{
    unsigned long int num = 0;
    _lcd_write_data(0x0F);
    PORTC .2 = 1;
    while (1)
    {
        PORTD .0 = 0;
        PORTD .1 = 1;
        PORTD .2 = 1;
        delay_ms(5);
        if (PIND .3 == 0)
        {
            while (PIND .3 == 0;
            lcd_putchar('1');
            num = (num * 10) + 1;
        }
        else if (PIND .4 == 0)
        {
            while (PIND .4 == 0);
            lcd_putchar('4');
            num = (num * 10) + 4;
        }
        else if (PIND .5 == 0)
        {
            while (PIND .5 == 0);
            lcd_putchar('7');
            num = (num * 10) + 7;
        }
        else if (PIND .6 == 0)
        {
            while (PIND .6 == 0);
            _lcd_write_data(0x10);
            lcd_putchar(' ');
            _lcd_write_data(0x10);
            num /= 10;
        }

        PORTD .0 = 1;
        PORTD .1 = 0;
        PORTD .2 = 1;
        delay_ms(5);
        if (PIND .3 == 0)
        {
            while (PIND .3 == 0);
            lcd_putchar('2');
            num = (num * 10) + 2;
        }
        else if (PIND .4 == 0)
        {
            while (PIND .4 == 0);
            lcd_putchar('5');
            num = (num * 10) + 5;
        }
        else if (PIND .5 == 0)
        {
            while (PIND .5 == 0)
                ;
            lcd_putchar('8');
            num = (num * 10) + 8;
        }
        else if (PIND .6 == 0)
        {
            while (PIND .6 == 0);
            lcd_putchar('0');
            num = (num * 10) + 0;
        }

        PORTD .0 = 1;
        PORTD .1 = 1;
        PORTD .2 = 0;
        delay_ms(5);
        if (PIND .3 == 0)
        {
            while (PIND .3 == 0);
            lcd_putchar('3');
            num = (num * 10) + 3;
        }
        else if (PIND .4 == 0)
        {
            while (PIND .4 == 0);
            lcd_putchar('6');
            num = (num * 10) + 6;
        }
        else if (PIND .5 == 0)
        {
            while (PIND .5 == 0);
            lcd_putchar('9');
            num = (num * 10) + 9;
        }
        else if (PIND .6 == 0)
        {
            while (PIND .6 == 0);
            break;
        }
    }
    PORTC .2 = 0;
    _lcd_write_data(0x0C);

    return num;
}

lcd_clear();
lcd_putsf("Enter Username:");
lcd_gotoxy(0, 1);
sprintf(show, "%lu", username);
lcd_puts(show);

this is not my whole code, it's the part I have a problem with.

i enter this 56321

enter image description here

the output is this

enter image description here

https://files.fm/f/qpwrmfs6h this is the video.

and I tried %ul and %lu, %ul have the same problem and %lu output is like this enter image description here enter image description here

my English is not very well and it is hard for me to add details


Solution

    1. Do not use printf and scanf functions in the 8 bits environment. They are resources greedy and are not very suitable for this kind of micros.
    2. printf and scanf implementations are limited and do not support many formats.
    3. 32bits numbers operations are very expensive (especially division) in the 8 bits environment - try to use 16 bits where possible
    #define MASK32ULONG 1000000000UL
    #define MASK16UINT  10000
    
    char *toDecimal(char *buff, unsigned long val)
    {
        unsigned long mask = MASK32ULONG;
        unsigned long remain;
        char *wrk = buff;
    
        do
        {
            int digit = val / mask;
    
            if(digit || !val) *wrk++ = '0' + digit;
            val %= mask;
            mask /= 10;
        }while(val);
        *wrk = 0;
        return buff;
    }