Search code examples
cgccavravr-gccatmel

Displaying ASCII characters from an array on a LCD with ATmega32


I've got an LCD, connected to an Atmega32, working with single characters using this function:

void send_char(uint8_t c){
    PORTD = c; // set the output pins to the ascii value of the char
    PORTB |= 0x05;
    _delay_us(1);
    PORTB &= 0xfa;
    _delay_us(60);
    PORTD = 0x00;
    update_cursor();
}

I can call this with a character as an argument: send_char('a'); and it works.

Then I tried wrapping a send_string function around it:

void send_string(const char * msg){
    while (*msg != '\0'){
        send_char(*msg++);
    }
}

This just puts gibberish on my LCD indicating that the ASCII value has been far off. And when I try passing an empty string (send_string("")) a minimum of three gibberish characters get displayed on the LCD.


Solution

  • First, it seems that you are using the avr-gcc compiler. When making questions for embedded devices, you always need to say which compiler you are using.

    I will now try to help you understand what is wrong with your code and why your solution works. The function you have defined:

    void send_string(const char * msg);
    

    expects a string pointer in RAM. It doesn't matter that you have used the const keyword, the compiler still expects the string to be in RAM. So if you have a string in ROM:

    const char msg[] PROGMEM = "Test";
    

    and you try to pass it in your function:

    send_string(msg);
    

    it just passes an invalid address to it and thus gibberish are displayed. If instead you copy it first to RAM, as you did in your solution, it works fine:

    char buf[strlen(msg)];
    strcpy_P(buf,msg);
    send_string(buf);
    

    If you want to define a function that will directly read a ROM string, you can do it like this:

    void send_string_P(const char *data)
    {
        while (pgm_read_byte(data) != 0x00)
            send_char(pgm_read_byte(data++));
    } 
    

    Notice the _P suffix. This is the general convention used to distinct functions that operate on ROM from the ones that operate on RAM.

    All these and more are nicely explained here. I also suggest that you try the AVR Freaks forum for these kind of questions. People there will be certainly more experienced in these issues than Stack Overflow users and are always happy to help.