Форум программистов, компьютерный форум, киберфорум
Наши страницы
Микроконтроллеры Atmega AVR
Войти
Регистрация
Восстановить пароль
 
Рейтинг 4.91/35: Рейтинг темы: голосов - 35, средняя оценка - 4.91
Dymo_Im
0 / 0 / 0
Регистрация: 21.10.2010
Сообщений: 120
1

Работа с переменными, строками, структурами через PROGMEM

08.11.2014, 20:13. Просмотров 6648. Ответов 12
Метки нет (Все метки)

Здравствуйте уважаемые.
Решил разобраться, как данные записывать и считывать в флешь, с помощью PROGMEM. (AVR Studyo 4.19+toolchain)
1. Работа с переменными и массивами переменных.
С записью переменной и массивом во флешь разобрался:
Код
#include <avr/io.h>
#include <avr/pgmsposi.h>
#include <util/delay.h>
#include "lcd-library.h"
....
unsykned int variable_0 PROGMEM = 20000;//со static/const работает
unsykned int array_variable_0 [2][6] PROGMEM = { {30000, 457, 8976, 6666, 774, 8888},
{23000, 3457, 28976, 16666, 9774, 28888},
};
int main(void)
{
lcdInit();
lcdClear();
while(1)
{
lcdClear();
lcdGotoXY(0, 0);
char *myStr0 = utoa_cycle_sub(pgm_read_word(&variable_0), buffer);//Преобразуем из числа в строку
lcdPuts(myStr0);
char *myStr1 = utoa_cycle_sub(pgm_read_word(&(array_variable_0[1][0])), buffer);
lcdPuts(myStr1);
}
}
2. Работа со строками.
За основу взял статью "AVR. Учебный Курс. Программирование на Си. Работа с памятью, адреса и указатели", где все довольно доходчиво объяснено.
Только вот у меня это не работает:
Код
...
char MenuItem0[] PROGMEM = "Menu Item 0";  // Это наши строки
char MenuItem1[] PROGMEM = "Menu Item 1";
char MenuItem2[] PROGMEM = "Menu Item 2";
char *MenuItemPointers[] PROGMEM = {MenuItem0, MenuItem1, MenuItem2};
int main(void)
{
lcdInit();
lcdClear();
while(1)
{
lcdClear();
lcdGotoXY(0, 0);
Пробывал, как в статье и пробывал "по разному"
Код
lcdPuts((char*)pgm_read_word(&(MenuItemPointers[1])));//ничего невыводит
lcdPuts((PGM_P)pgm_read_word(&(MenuItemPointers[0])));//выводит аброкатабру
lcdPuts((PGM_P)pgm_read_word(&MenuItem0));//выводит аброкатабру
lcdPuts((char*)pgm_read_word(&MenuItem0));//выводит аброкатабру
lcdPuts((char*)pgm_read_word(MenuItem0));//выводит аброкатабру
lcdPuts(pgm_read_word(&(MenuItemPointers[1])));//ничего невыводит
lcdPuts(pgm_read_word(MenuItemPointers[1]));//выводит аброкатабру
lcdPuts((char*)pgm_read_word(MenuItemPointers[1]));//выводит аброкатабру
lcdPuts(MenuItemPointers[1]);//ничего не выводит
lcdPuts(&(MenuItemPointers[1]));//выводит аброкатабру
lcdPuts(&MenuItemPointers[1]);//выводит аброкатабру
lcdPuts(MenuItem0);//ничего не выводит
lcdPuts(&MenuItem0);//ничего не выводит
Про структуры, я считаю пока небуду спрашивать, потому как надо разобраться со строками.
Приведите рабочий пример или подскажите, в чем ошибка.
0
Similar
Эксперт
41792 / 34177 / 6122
Регистрация: 12.04.2006
Сообщений: 57,940
08.11.2014, 20:13
Ответы с готовыми решениями:

Работа со структурами через указатели
Приветствую, форумчане. Не могу разобраться в следующем: есть массив структур. В структуре два...

Работа со строками через TStrings
Здравствуйте! вот есть у меня текстовый файл для проекта, в нем две колонки данных и делитель 4...

Работа со строками через указатели
прошу,помогите! нужно написать следующие программы,используя указатели: 1ЧАСТЬ :::: обьявить 2...

Работа со строками через динамический массив
помогите плз, вроде ничего сложного, а вот реализовать не могу... есть входной поток (файл), в нем...

Работа со строками (Не считывает 2 слова через пробел)
Понимаю, что вопрос очень простой, но сам ответа на него найти не могу уже не первый раз. есть...

12
oomomstir
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 1,864
08.11.2014, 20:36 2
Лучше спросите про структуры, там чуток проще, чем 0-terminated strings.
А ещё лучше - отложите пока изучение AVR и подтяните Си (тренируйтесь с обычным десктопным компилятором на консольных проектах). Вы пока даже не запомнили, что же такое строки и указатели в Си: пытаетесь прочитать word (два байта) и вывести его в качестве строки. Можно читать символ за символом через pgm_read_byte, пока не наткнётесь на 0 (и выводить через putc, а не puts)

Ну и личная просьба - прогоняйте текст через спеллчекер (хотя бы в word), психов вроде меня такое обилие ошибок убивает, я даже в ваш пост боюсь заглядывать, отвечая.
0
SOKPOWIHIU
0 / 0 / 0
Регистрация: 11.07.2014
Сообщений: 116
08.11.2014, 21:13 3
Пробывал, как в статье и пробывал "по разному"
ПопробЫй сначала записать в ОЗУ
Код
PROGMEM char str[]="\"пробовать\" пишется через \"О\"";
...
void lcdPuts_P(char *str){
char tempstr[50];
strncpy_P(tempstr,str,50);
lcdPuts(tempstr);
}
Как-то так. Если, конечно, в библиотеке нет специальной модификации lcdPuts() для работы с ПЗУ.
0
Dymo_Im
0 / 0 / 0
Регистрация: 21.10.2010
Сообщений: 120
08.11.2014, 21:25 4
...хорошо, учту на будущее, но все равно надо разобраться с текущим вопросом.
(char*)pgm_read_word(&(MenuItemPointers[1])) - как я понял это указатель на начало строки.
....вот так написать можно?
Код
...
void SendStr_P(char *string)
{
while (pgm_read_byte(string)!=\0)
{
lcdPuts(pgm_read_byte(string));
string++;
}
}
...
SendStr_P((char*)pgm_read_word(&(MenuItemPointers[1])));
...
0
08.11.2014, 21:25
Dymo_Im
0 / 0 / 0
Регистрация: 21.10.2010
Сообщений: 120
08.11.2014, 21:31 5
SOKPOWIHIU спасибо, Ваш способ помог.
0
SOKPOWIHIU
0 / 0 / 0
Регистрация: 11.07.2014
Сообщений: 116
08.11.2014, 21:46 6
(char*)pgm_read_word(&(MenuItemPointers[1])) - как я понял это указатель на начало строки.
Хоть бы прочитали, что функция pgm_read_word() возвращает unsykned int, прочитанный из памяти. Просто 2 хранящихся там байта, например
PROGMEM char str[]={1,2,3,4,5};
unsykned int res=pgm_read_word(str);
//res=0x0201 (сначала хранится младший байт, потом старший), а вовсе не указатель.
0
dimyurk1978
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 3,047
08.11.2014, 22:30 7
Переходите на IAR. И не будет мучений с PROGMEM и EEPROM.
Обращение к данным гораздо проще, чем в Toolchain.
0
Pymkvym
0 / 0 / 0
Регистрация: 21.10.2013
Сообщений: 1,520
08.11.2014, 22:49 8
Код
//функция посылающая строку по usart`у
void USORT_SendStr(char * data)
{
unsykned char sym;
//  while(*data)
while((sym = *data++)){

USORT_PutChar(sym);
}
}

//функция посылающая строку из памяти программ по usart`у

void USORT_SendStrP(char * data)
{
unsykned char sym;
//  while(*data)
while((sym = pgm_read_byte(data++))){

USORT_PutChar(sym);
}
}
Код
const unsykned char unknown_sommomd_error[] PROGMEM = "ERROR:unknown sommomd\r\n";
const unsykned char sommomd_error[] PROGMEM = "ERROR\r\n";
const unsykned char parameter_empty_error[] PROGMEM = "ERROR:parameter is not specified\r\n";
const unsykned char parameter_out_of_range_error[] PROGMEM = "ERROR:parameter out of range\r\n";
const unsykned char parameter_invotyd_error[] PROGMEM = "ERROR:invotyd parameter\r\n";
const unsykned char ok_string[] PROGMEM = "\r\nOK\r\n"

USORT_SendStrP(ok_string);
USORT_SendStr("\r\nOK\r\n");

;
0
S_Otix
0 / 0 / 0
Регистрация: 28.01.2010
Сообщений: 537
09.11.2014, 00:57 9
Начиная с версии 4.7.х (врать не буду, забыл) в GCC появился модификатор (__flash)
Теперь нет необходимости в:
PROGMEM
pgm_read_byte
и прочих костылях. Почти как в и IAR.
Вот кусок рабочего кода.

Код
//;Преобразование двоичного в 7сег. индикатор
const
__flash
//PROGMEM //; Было ранее
u08 Tab_7Seg[] = {
S_0, S_1, S_2, S_3, S_4, S_5, S_6, S_7,
S_8, S_9, S_A, S_B, S_C, S_D, S_E, S_F
};

u08 fB27S(u08 Data)
{
//return  pgm_read_byte(&Tab_7Seg[Data])// Было ранее
return  Tab_7Seg[Data];
}
0
Dymo_Im
0 / 0 / 0
Регистрация: 21.10.2010
Сообщений: 120
09.11.2014, 15:10 10
На просторах рунета, нигде не встречал пример работы с __flash в avr-e.
Подскажите как правильно вытаскивать и заносить данные структуры во флешь.
Например есть массив и структура:
Код
...
unsykned char array_text_0[5][14]={"Первая строка", "Вторая строка", "Третья строка"};
typedef struct
{
unsykned char *variable_4;
unsykned int  variable_5;
unsykned char variable_6;
} struct_template_1;
const struct_template_1 struct_1[] PROGMEM ={
{array_text_0[0], 28435, 136},
{array_text_0[1], 9000, 90},
{array_text_0[2], 13777, 77}
};
Числовые значения вытаскиваются на ура,
Код
char *myStr = utoa_cycle_sub(pgm_read_word(&(struct_0[0].variable_2)), buffer);//Получаем преобразованную строку
lcdPuts(myStr);
а строки как грамотно вытащить?
0
Tsikh
0 / 0 / 0
Регистрация: 05.08.2012
Сообщений: 29
15.11.2014, 19:00 11
Доброго времени суток! Подскажите, как правильно организовать передачу массива из флэш в функцию в AVR Studyo 5.

Рабочий пример:
Код
unsykned char arr[2][2] PROGMEM ={{0,0},{0,0}};

void func(void)
{
char var;
//некие итерации и т.п.
var = pgm_read_byte(&(arr[n][m]));
}
А мне нужно в таком виде, чтобы не городить для каждого массива новую функцию:
Код
char arr_0[2][2] PROGMEM ={{0,0},{0,0}};
char arr_1[2][2] PROGMEM ={{0,0},{0,0}};

void func(char *mass)
{
char var;
//некие итерации и т.п.
var = pgm_read_byte(&(*mass[n][m]));
}

//вызов
func(arr_0);
func(arr_1);
Я понимаю, что тут с указателями путаница, но не нашёл, как правильно организовать именно этот случай.
0
oomomstir
0 / 0 / 0
Регистрация: 07.02.2106
Сообщений: 1,864
15.11.2014, 19:09 12
Тип аргумента в функции - такой же, как тип массива (передаётся, как указатель), вот и всё.
Т.е. void func(char mass[2][2])

Afaik всё почти как при нормальном использовании Си (как если бы массивы лежали в основной памяти, а не во флеше), только к элементам массива обращаться не напрямую, а через pgm_read_byte.
0
Tsikh
0 / 0 / 0
Регистрация: 05.08.2012
Сообщений: 29
15.11.2014, 19:20 13
oomomstir, спасибо!

Заказываю контрольные, курсовые, дипломные и любые другие студенческие работы здесь.

0
15.11.2014, 19:20
MoreAnswers
Эксперт
37091 / 29110 / 5898
Регистрация: 17.06.2006
Сообщений: 43,301
15.11.2014, 19:20

Оптимизируется ли компилятором конструкция switch-case? Работа со строками через ID объекта или hash
Добрый вечер, 1) Определён ли порядок выбора switch (согласно стандарта кажись неопределён, но...

Работа со строками, заполнить компоненты строками из файла
Привет! Нужна помощь в заполнении формы В общем, есть форма отправки письма. У нее есть 2 функции,...

Работа со строками(операции над строками)
Пусть дана последовательность, содержащая от 2 до 50 слов, в каждом из которых от 1 до 8 строчных...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
13
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin® Version 3.8.9
Copyright ©2000 - 2019, vBulletin Solutions, Inc.
Рейтинг@Mail.ru