Отображение символов ASCII из массива на ЖК-дисплее с помощью ATmega32 - PullRequest
2 голосов
/ 23 ноября 2010

У меня есть ЖК-дисплей, подключенный к Atmega32, работающий с одиночными символами с помощью этой функции:

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();
}

Я могу назвать это символом в качестве аргумента: send_char('a');, и это работает.

Затем я попытался обернуть вокруг него функцию send_string:

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

Это просто приводит к тому, что на моем ЖК-дисплее появляется бред, указывающий, что значение ASCII было далеко. И когда я пытаюсь передать пустую строку (send_string("")), на ЖК-дисплее отображается минимум три бессмысленных символа.

Ответы [ 4 ]

3 голосов
/ 26 ноября 2010

Сначала кажется, что вы используете компилятор avr-gcc. При создании вопросов для встроенных устройств всегда нужно указывать, какой компилятор вы используете.

Теперь я постараюсь помочь вам понять, что не так с вашим кодом и почему ваше решение работает. Функция, которую вы определили:

void send_string(const char * msg);

ожидает указатель строки в оперативной памяти. Неважно, что вы использовали ключевое слово const, компилятор все еще ожидает, что строка будет в ОЗУ. Так что если у вас есть строка в ПЗУ:

const char msg[] PROGMEM = "Test";

и вы пытаетесь передать его в своей функции:

send_string(msg);

он просто передает ему неверный адрес и, таким образом, отображает тарабарщину. Если вместо этого вы сначала скопируете его в оперативную память, как вы делали это в своем решении, он работает нормально:

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

Если вы хотите определить функцию, которая будет непосредственно читать строку ПЗУ, вы можете сделать это следующим образом:

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

Обратите внимание на суффикс _P. Это общее соглашение, используемое для отделения функций, работающих на ПЗУ, от функций, работающих на ОЗУ.

Все это и многое другое хорошо объяснено здесь . Я также предлагаю вам попробовать форум такого типа AVR Freaks . Люди, несомненно, будут более опытными в этих вопросах, чем пользователи Stack Overflow, и всегда рады помочь.

1 голос
/ 23 ноября 2010

Это работает для меня:

#include <stdio.h>
#include <stdint.h>

void send_char(uint8_t c)
{
    printf("%c", c);
}

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

int main()
{
    send_string("Stackoverflow!");

    return 0;
}

В своем коде вставьте sleep(1); после вызова send_char() и посмотрите, не изменит ли это поведение, которое вы наблюдаете.

1 голос
/ 23 ноября 2010

Это работает на моем контроллере Atmel (хотя я не знаю почему):

Сначала нужно добавить литерал в ПЗУ через PROGMEM из <avr/pgmspace.h>:

const char msg[] PROGMEM = "Test";

Затем скопируйте литерал в буфер в оперативной памяти контроллера:

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

Теперь send_string(msg) можно использовать как положено ..

1 голос
/ 23 ноября 2010

Я не вижу ничего плохого в вашем коде (не то, чтобы я знал, как разговаривать с Atmega32).Попробуйте запустить его в отладчике и печатать c при каждом вызове send_char, или просто поставить printf("%d\n", (int)c); в качестве первой строки send_char.

...