Помощь - Поиск - Пользователи - Календарь
Полная версия этой страницы: Размещение строки во флэш
Форум разработчиков электроники ELECTRONIX.ru > Микроконтроллеры (MCs) > AVR
011119xx
Делаю так:

#define T_STR0 "Строка 1"
#define T_STR1 "Строка 2"

uint8_t fn0[] PROGMEM = T_STR0;
uint8_t fn1[] PROGMEM = T_STR1;

uint8_t *function_name[] PROGMEM = { (uint8_t *) & fn0, (uint8_t *) & fn1};

int main(void)
{
lcd_print_P(((uint8_t *) &function_name[1]));
}

Но не работает. Передает не строку, а какие-то другие символы. Хотя если сделать так:

lcd_print_P((uint8_t *) &fn1);

то работает. Что не так делаю?
Непомнящий Евгений
Как то так, наверное

Код
uint8_t *function_name[] PROGMEM = { (uint8_t *) fn0, (uint8_t *) fn1};


Кстати, а зачем вы типы приводите? Так
Код
uint8_t *function_name[] PROGMEM = { fn0, fn1};

разве не компилится?
ARV
Используйте готовый макросы PSTR и PGM_P. например, так:
Код
PROGMEM char str1[] = "name1"
PROGMEM char str2[] = "name2";
PROGMEM PGM_P names[] = { str1, str2};

lcd_print_P(pgm_read_word(&names[1]));


ваш код почти верный, только вы забыли, что для считывания из флеши данных надо использовать макрос pgm_read_byte или pgm_read_word
011119xx
Цитата(ARV @ Dec 3 2008, 11:55) *
Используйте готовый макросы PSTR и PGM_P. например, так:
Код
PROGMEM PGM_P names[] = {PSTR("name1"), PSTR("name2")};

lcd_print_P(pgm_read_word(&names[1]));


ваш код почти верный, только вы забыли, что для считывания из флеши данных надо использовать макрос pgm_read_byte или pgm_read_word

Спасибо, буду пробовать
ARV
извините, поспешил
правильно так:
Код
PROGMEM char str1[] = "name1";
PROGMEM char str2[] = "name2";

PROGMEM PGM_P names[] = {str1, str2};
остальное - как и говорил ранее
_Pasha
На всякий случай
avr-libc-user-manual.pdf
Поиск по ключевой фразе : Wrong!
Сразу поймете, о чем я smile.gif
011119xx
Цитата(ARV @ Dec 3 2008, 12:08) *
извините, поспешил
правильно так:
Код
PROGMEM char str1[] = "name1";
PROGMEM char str2[] = "name2";

PROGMEM PGM_P names[] = {str1, str2};
остальное - как и говорил ранее

Спасибо. Это работает.
haker_fox
Если WinAVR используется, то тема двухгодичной давности должна помочь в этом форуме))) Но немного освежить не помешает:
prog_char testString[] ="something here...";
Тогда массив testString будет размещен во флеш памяти. Обращаться к нему с помощью pgm_read_byte. Библиотека pgmspace.h
sonycman
Цитата(haker_fox @ Dec 3 2008, 13:36) *
prog_char testString[] ="something here...";
Тогда массив testString будет размещен во флеш памяти.

В версии компилятора 4.3.2 такой массив будет расположен в ОЗУ.
Необходимо прямое указание PROGMEM. Например:
Код
PROGMEM char testString[] ="something here...";

Не знаю, почему так...
_Pasha
Цитата(sonycman @ Dec 3 2008, 17:55) *
В версии компилятора 4.3.2 такой массив будет расположен в ОЗУ.
Необходимо прямое указание PROGMEM. Например:

Не верю! Winavr20081118rc2
Код
prog_char testString[] ="something here...";
int main(void){
// там один раз упомянули адрес этой строки


Код
  2e:    26 c0           rjmp    .+76     ; 0x7c <__bad_interrupt>
  30:    25 c0           rjmp    .+74     ; 0x7c <__bad_interrupt>
  32:    24 c0           rjmp    .+72     ; 0x7c <__bad_interrupt>

00000034 <testString>:
  34:    73 6f 6d 65 74 68 69 6e 67 20 68 65 72 65 2e 2e     something here..
  44:    2e 00                                               ..
defunct
Пример как полюдски выводить константы из флеш куда угодно, может кому пригодится:

Код
#include <avr/io.h>
#include <avr/pgmspace.h>

typedef unsigned char U8;

#define ignore(x)


void put(U8 ch)
{
    ignore( ch );
    //<<< ВАШ КОД ВЫВОДА ОДНОГО СИМВОЛА КУДА ТРЕБУЕТСЯ (UART/LCD и проч) >>
}


static void __pgm_print(const U8 PROGMEM *str)
{
    U8 ch;
    while ( (ch = pgm_read_byte(str++)) != 0)
        put(ch);
}


#define pgm_print(x) do {\
  static const U8 PROGMEM str[] = x;\
  __pgm_print( str );\
} while(0)



void main(void)
{
    pgm_print("hello\n");
    pgm_print("this program demonstrates an easy way of\n");
    pgm_print("printing string literals stored in flash\n");

    for(;;);
}
sonycman
Цитата(_Pasha @ Dec 3 2008, 18:31) *
Не верю! Winavr20081118rc2

Пжалста: smile.gif
Код
#include    <avr/pgmspace.h>

prog_char testString[] ="something here...";

int main(void)
{
    char a;
    PGM_P p = testString;
    do
    {
        a = pgm_read_byte(p++);
    }while (a);

    return 0;
}

и из листинга:
Код
00800060 g     O .data    00000012 testString

Тот же самый WinAVR-20081118rc2. laughing.gif

Цитата(defunct @ Dec 3 2008, 19:30) *
pgm_print("hello\n");
pgm_print("this program demonstrates an easy way of\n");
pgm_print("printing string literals stored in flash\n");

Действительно, красиво сделано smile.gif
Сергей Борщ
Цитата(sonycman @ Dec 3 2008, 15:55) *
В версии компилятора 4.3.2 такой массив будет расположен в ОЗУ.
Необходимо прямое указание PROGMEM. Например:
А если посмотреть pgmspace.h, то можно увидеть
Код
typedef char PROGMEM prog_char;
Теперь объясняйте - в чем разница?
sonycman
Цитата(Сергей Борщ @ Dec 3 2008, 19:54) *
А если посмотреть pgmspace.h, то можно увидеть
Код
typedef char PROGMEM prog_char;
Теперь объясняйте - в чем разница?

Это всё понятно. Только не мне объяснять, почему - откуда я знаю?
Выше приведён пример, в котором строка после компиляции помещается в ОЗУ.

А вот если сделать вот так:
Код
#include    <avr/pgmspace.h>

PROGMEM char testString[] ="something here...";

int main(void)
{
    char a;
    PGM_P p = testString;
    do
    {
        a = pgm_read_byte(p++);
    }while (a);

    return 0;
}

то всё в порядке:
Код
00000054 g     O .text    00000012 testString

00000054 <testString>:
  54:    73 6f 6d 65 74 68 69 6e 67 20 68 65 72 65 2e 2e     something here..
  64:    2e 00                                               ..

Попробуйте лучше вы это объяснить wink.gif
Я-то всего лишь любитель...
011119xx
А как размещать во флэш массив большой величины?
Делаю так: const uint16_t img[] PROGMEM = { здесь, например, 15000 слов }; Выдается ошибка: size of variable 'img' is too large
ARV
Цитата(011119xx @ Dec 4 2008, 14:17) *
А как размещать во флэш массив большой величины?
Делаю так: const uint16_t img[] PROGMEM = { здесь, например, 15000 слов }; Выдается ошибка: size of variable 'img' is too large

а флеши-то достаточно? может, вы пытаетесь впихнуть 30К в какую-нибудь atmega16 smile.gif
011119xx
Впихиваю в атмегу128 smile.gif
Памяти достаточно. Если массив поделить пополам, то они спокойно размещаются оба, но хотелось бы целиком.
Сергей Борщ
Цитата(011119xx @ Dec 4 2008, 13:17) *
const uint16_t img[] PROGMEM = { здесь, например, 15000 слов }; Выдается ошибка: size of variable 'img' is too large
Точно 15000 а не 16384 или больше? Для avr_gcc размер одного массива не может быть больше 32768 байт, связано это (как и у других компиляторов) с размером типа ptrdiff_t. Варианты обхода: определять массив в асм-файле, определять несколько массивов допустимой длинны в именованных сегментах и скриптом линкера обеспечить их размещение подряд, ну а доступ через указатель.
011119xx
Цитата(Сергей Борщ @ Dec 4 2008, 17:39) *
Точно 15000 а не 16384 или больше? Для avr_gcc размер одного массива не может быть больше 32768 байт, связано это (как и у других компиляторов) с размером типа ptrdiff_t. Варианты обхода: определять массив в асм-файле, определять несколько массивов допустимой длинны в именованных сегментах и скриптом линкера обеспечить их размещение подряд, ну а доступ через указатель.

Точно 23232 и точно uint16_t.
Сергей Борщ
Цитата(011119xx @ Dec 4 2008, 14:47) *
Точно 23232 и точно uint16_t.
Ну вот. 23232 * sizeof(uint16_t) = 46464 > 32768. Оно. Можете поискать на avrfreaks в форуме по gcc - там было обсуждение этого вопроса.
Для просмотра полной версии этой страницы, пожалуйста, пройдите по ссылке.
Invision Power Board © 2001-2025 Invision Power Services, Inc.