struct array и PROGMEM - как записать структуру массива и сам строковый массив в Flash-память
- Войдите на сайт для отправки комментариев
Чт, 27/09/2018 - 17:52
Добрый вечер! Прошу знатоков подсказать правильное задание структуры строковых массивов и задание значений элементов массива с записью в Flash-память, нужно для экономии динамической памяти Arduino Nano.
Код, который применяю:
#include <avr/pgmspace.h> struct listUsr_t { const char phoneNum[13]; const char phonePass[5]; const char phonePDU[13]; }; listUsr_t users[20] = { { "+70000000000", "0000", "000000000000" }, { "+71111111111", "0000", "000000000000" }, { "+78881234567", "0000", "000000000000" }, { "+78882345678", "0000", "000000000000" }, { "+78883456789", "0000", "000000000000" }, { "+78884567890", "0000", "000000000000" }, { "+78885678901", "0000", "000000000000" }, { "+78886789012", "0000", "000000000000" }, { "+78887890123", "0000", "000000000000" }, { "+78888901234", "0000", "000000000000" }, { "+78880123456", "0000", "000000000000" }, { "+78881123456", "0000", "000000000000" }, { "+78881234567", "0000", "000000000000" }, { "+78881345678", "0000", "000000000000" }, { "+78881456789", "0000", "000000000000" }, { "+78881567890", "0000", "000000000000" }, { "+78881678901", "0000", "000000000000" }, { "+78881789012", "0000", "000000000000" }, { "+78881890123", "0000", "000000000000" }, { "+78881901234", "0000", "000000000000" } }; void setup() { Serial.begin(9600); Serial.println(sizeof(users)); } void loop() { ; }
Размер данных возвращается 620 байт, что соответствует действительности 13+5+13=31*20=620.
Подскажите, пожалуйста, как этот массив записать в Flash-память, при помощи pgmspace.h - я не могу разобраться, к сожалению... Заранее благодарен за помощь!
Записать строковый массив без структуры - нет проблем:
Нужен массив со структурой...
а const listUsr_t PROGMEM users[20] = .... не решает?
а const listUsr_t PROGMEM users[20] = .... не решает?
Огромное спасибо! Я не мог понять почему ругается компилятор - PROGMEM ставил в разные места, объявляя массив со структурой, но забывал про const, теперь, массив со структурой задается и располагается в Flash-памяти... еще раз - спасибо!
https://www.arduino.cc/reference/en/language/variables/utilities/progmem/
https://www.arduino.cc/reference/en/language/variables/utilities/progmem/
Спасибо! Я эту статью прочитал несколько раз, и не мог понять причину, искал в сторону pgmspace.h и синтаксиса этой библиотеки, а оказалось, я не правильно объявлял элемент, его нужно было как const объявлять.
По ссылке strarbit более правильный способ, ибо запихивание массива строк в pgmspace несколько специфичная задача.
Вроде вчера в другой теме было тоже самое и вновь опять #25
По ссылке strarbit более правильный способ, ибо запихивание массива строк в pgmspace несколько специфичная задача.
Именно из-за специфичности задачи я и обратился к помощи более опытных коллег. Задача состоит в том, чтобы в 2048 байта уместить код с многими логическими функциями, и прочим кодом, отвечающим за контроль работы привода.
Вроде вчера в другой теме было тоже самое и вновь опять #25
Я читал ветку, на которую Вы ссылаетесь, там не совсем аналогичная задача обсуждалась...
Записать строки с необходимыми данными в Flash-память получилось, это очень сильно сэкономило память контроллера. Однако, теперь у меня новый тупик, я не могу считать строки, считывается только первый символ и все... вот код:
При этом компилятор выдает предупреждение: "warning: invalid conversion from '__FlashStringHelper*' to 'char' [-fpermissive]", и в монитор Serial-порта выводится только первый символ строки, записанной в Flash-память, куда копать не могу разобраться, прошу помощи!!!
вы пытаетесь считывать строку в переменную val, которая обьявлена как char - то есть имеет размер 1 символ. Что же еще туда может считаться, кроме 1 символа?
Я это понимаю, в глубине души, однако, при попытке задать размер строкового массива
компилятор возвращает ошибку и прекращает компиляцию: "error: incompatible types in assignment of '__FlashStringHelper*' to 'char [5]'", у меня тупик, если честно...
Использовать strcpy_P ещё не пробовал, но это не путь, т.к. strcpy_P требует объявлять переменные, как глобальные, а глобальные переменные "скушают" память, динамическую, и вся экономия при помощи PROGMEM будет зря... Заранее благодарен, если подскажите правильный код для решения моей задачи.
Ну, вам нужно свыкнуться с мыслью, что "в ноль" вы потери не выведете.
Просто радуйтесь тому, что строки, расположенные в progmem не будут перегружаться в RAM и не будет двойного удара по ресурсам.
И мне все еще кажется, что в PGM вы засунули неправильно. Почитайте статью по ссылке strarbit - там есть специальный раздел "Array of string". Нужно делать именно так, во всех деталях, с раздельными объявлениями строк в PGM, а потом сборе в общий массив. Может сейчас компилятор и умничает, а года два назад такой способ, как приведен у вас, лично мне никак не помогал экономить.
Использовать strcpy_P ещё не пробовал, но это не путь, т.к. strcpy_P требует объявлять переменные, как глобальные
во-первых, это не так - strcpy_P работает и с локальными переменными. Во-вторых, даже если использовать глобальную переменную буфера - то для strcpy_P она нужна всего одна на все ваши строки в ПРОГМЕМ, так что удар по ресурсам не так уж и велик.
Вам надо еще раз внимательно перечитать ссылки, которые вам дали выше. Вам кажется, что они не про ваш случай, что он уникален - но он получается уникальным именно потому, что вы подходите к хранению строк неправильно. Сделайте как по ссылке и все получится.
Если речь идет о том, что сначала необходимо задать строковые массивы, потом создать таблицу с указанием на созданные строковые массивы и считывать при помощи pgm_read_dword или pgm_read_word в буфер или созданную переменную (почему-то пишется, что только глобальную), то это я знаю, но в таком случае не будет структуры... НО и без структуры можно обойтись, весь проблемный для меня вопрос, это то, что один из строковых массивов имеет длину 250 символов, и если даже, я сделаю, как написано в описании работы (ссылка предложенная выше по этому обсуждению, то у меня получиться 20% сразу долой из памяти контроллера, это для меня не решение задачи.
Кроме того, как объяснить тот факт, что код вида:
Этот код выводит в монитор Serial-порта все строки правильно... значит в Flash-память они помещены тоже правильно... Кто может помочь - буду благодарен!!!
Ну-ну. Похоже это башня из доминошек. Лишний чих и сново-здорово.
НО и без структуры можно обойтись, весь проблемный для меня вопрос, это то, что один из строковых массивов имеет длину 250 символов,
весь массив 250 символов или КАЖДЫЙ элемент 250?
Если у вас отдельный элемент 250 символов - то как ни старайся, вам придется копировать его в память. Или выводить по частям. Может в таком случае вы просто не тот контроллер взяли? В Меге 8к памяти, а в СТМ32 - аж целых 20к, стоит посмотреть на них.
Вообще, по-моему вы взялись за проект. слишком сложный для вашего уровня. Так ли уж необходимо запихивать в Нано эту базу данных с телефонами? Может без нее обойтись?
Этот код выводит в монитор Serial-порта все строки правильно... значит в Flash-память они помещены тоже правильно... Кто может помочь - буду благодарен!!!
если этот код работает - используйте его
Ну, вобщем, советовать как лучше решить задачу, смысла которой не знаешь, абсолютно бессмысленно.
Почему вы решили, что нельзя создать стуктуру с указателями на PGM-строки - мне тоже не особо понятно. Переменных в 250 символов я тут у вас не вижу.
весь массив 250 символов или КАЖДЫЙ элемент 250?
Если у вас отдельный элемент 250 символов - то как ни старайся, вам придется копировать его в память. Или выводить по частям. Может в таком случае вы просто не тот контроллер взяли? В Меге 8к памяти, а в СТМ32 - аж целых 20к, стоит посмотреть на них.
Вообще, по-моему вы взялись за проект. слишком сложный для вашего уровня. Так ли уж необходимо запихивать в Нано эту базу данных с телефонами? Может без нее обойтись?
если этот код работает - используйте его
каждый по 250 символов....
использовать код - я не могу понять, как сравнить строку записанную в Flash-память со строкой в динамической памяти, сравнивать нужно строки длиной 13 и 5 символов, соответсвенно строка 13 символов сравнивается со строкой из 13 символов, 13-й символ это \0, завершающий.
Строки из 250 сивловов используются для отправки сообщений при помощи модуля SIM800, в PDU режиме, кодировать в скетче, опять же, много памяти расходуется...
Менять тип контроллера пока не готов, интересно добиться результата и реализовать задачу на нано, т.е. уместив код скетча в 2048 байт...
использовать код - я не могу понять, как сравнить строку записанную в Flash-память со строкой в динамической памяти
https://www.nongnu.org/avr-libc/user-manual/group__avr__pgmspace.html#gab0c75b8cce460448b747c29231da847c <<The strcmp_P() function is similar to strcmp() except that s2 is pointer to a string in program space
Ну, вобщем, советовать как лучше решить задачу, смысла которой не знаешь, абсолютно бессмысленно.
Почему вы решили, что нельзя создать стуктуру с указателями на PGM-строки - мне тоже не особо понятно. Переменных в 250 символов я тут у вас не вижу.
Структуру я создал и строковые массивы с заданной структурой я записал в флеш-память (в коде, прикрепленном мной это видно). Правильность записанных строковых массивов проверяю, пока, пуьем вывода в монитор Serial-порта (также, видно в моем коде).
Задача состоит в том, что при входящем вызове (модуль SIM800), средствами модуля определяем номер телефона, и необходимо сравнить определившийся номер с номерами из массива, номера из массива перебираем при помощи цикла for, если хоть один номера из массива совпадает, то выполняется действие (digitalWrite pin), если не один номер не совпал, то отбой звонка, примерно такая стоит задача.
Строки в 250 символов (максималная длина) это сообщения в PDU режиме для того же модуля, они ни с чем не сравниваются, с их использованием собираются смс-сообщения на русском языке (PDU mode).
Я не могу разобраться, как сравнить строку 13 или 5 символов в флеш-памяти с соответсвующей строкой в динамической памяти контроллера, за помощь или подсказку буду очень признателен!
Ну, может как-то так (на МК не заливал)?
Ну, может как-то так (на МК не заливал)?
Спасибо огромное!
Я тоже смотрел описание этого макроса - буду пробовать использовать сравнение из PGM, по результатам отпишусь, ещё раз - спасибо!
Строки из 250 сивловов используются для отправки сообщений при помощи модуля SIM800, в PDU режиме, кодировать в скетче, опять же, много памяти расходуется...
Кодируйте динамически
Ну, может как-то так (на МК не заливал)?
Доброе утро! Ещё раз спасибо! Код залил на МК - всё работает, память отбирается соответственно переменным, все ОК! Код не много дополнил, в связи с тем, что определение номера идет в String:
Логику и действия с пинами МК - это уже готово, практически, главная задача была уместиться в отведенные 2048 байт памяти МК. На данный момент, все константы с номерами, паролями, текмстовыми сообщениями в нескольких форматах, загружаются в флеш-память, расход динамической памяти 10%, ранее было 52%, экономия присутствует...
Ещё раз спасибо всем за помощь и консультации!
Теперь остался один непонятный для меня момент в работе с PGM. Как сравнить строки из ОЗУ и Флеш, разобрался с общей помощью, а как "вытащить" строку из флеш-памяти, чтобы "собрать" необходимый пакет в строку, из нескольких строк, несколько частей составной строки находится в ОЗУ в виде локальных переменных в конкретной функции, а некоторые части составной строки находятся в флеш-памяти.
Подскажите как "вытащить" строку из флеш-памяти в локальную переменную в ОЗУ или сразу добавить в составную строку часть из флеш-памяти???
Памяти не хватает!!!
Памяти не хватает!!!
У меня все хватает, логику поменяйте, в пн могу скинуть часть скетча.
Памяти не хватает!!!
буду признателен!
1) У класса String имеется свойство, дающее указатель типа char* - копировать не надо в буфер.
2) По ссылке на nongnu перечислены все функции, работающие с pgm - например strncpy_p()
буду признателен!
Там относительно просто, используется буфер для исходного сообщения размером максимум 70 байт (максимум для одного смс по русски по стандартам) в однобайтовой кодировке, например win1251. Отсылает сначала заголовки pdu, потом цикл по буферу и каждый символ на ходу переводите UCS2 кодировку и отсылаете.
У меня объем всего скетча вроде половины (не помню точно - в пн скажу) памяти уно со следующим функционалом: приём ( в т ч длинных) и отправка смс в pdu формате, обработка присылаемых команд, работа с олед дисплеем, отображение напряжения питания модема, аптайм и пр.
И да - привыкайте работать со строками char - пригодится
как и обещал, часть скетча (4 файла из 5), вдруг пригодится:
как и обещал, часть скетча (4 файла из 5), вдруг пригодится:
Спасибо! Такое большое количество команд мне не потребуется для решения моей задачи, все равно - спасибо! Но, опять же, у Вас в коде задется все путем, описанным в ссылках по работе с PGM. У меня же, задается путем объявления структуры, а затем уже записью значений переменных структуры массивов в Flash-память МК.
Со сравнением, с общей помощью разобрался, остался вопрос, как поместить содержимое из Flash-памяти в динамическую память, присвоив значение переменной из Flash-памяти переменной в динамическую память... Код не работает:
Модет кто-то подскажет, что не так я делаю...
мошт, надо strсpy_P использывать, а не strcat? (Но это неточно)
traveler , мне кажеться вам нужно на классы переходить, в PGM харнить все списками, т.е. телефоны отдельный список, ПИН коды отдельным и т.д. Соотвественно когда в экземпляре класса необходимы данные непосредственно из progmem - динамически вытаскивать оттуда данные.
P.S. Классы не люблю, дело вкуса, но в вашей задаче вообще бы не использовал ни классы ни структуры, 4 функции по вытаскиванию данных из pgm и все.
мошт, надо strсpy_P использывать, а не strcat? (Но это неточно)
Я и strcpy_P и strcat_P - пытался использовать... не работает код и все...
мошт, надо strсpy_P использывать, а не strcat? (Но это неточно)
Я и strcpy_P и strcat_P - пытался использовать... не работает код и все...
наверное что то вы недопонимаете......
и образец вам кинули, и литературы много....
http://arduino.ru/forum/programmirovanie/ocherednoi-raz-progmem#comment-...
наверное что то вы недопонимаете......
и образец вам кинули, и литературы много....
http://arduino.ru/forum/programmirovanie/ocherednoi-raz-progmem#comment-...
Ещё раз повторюсь, я хотел использовать структуру, все ссылки и вся литература описывает без структур... Мне нужна просто подсказка, вернее, правильный синтаксис строки, которая считает переменную из Flash в RAM, все... Сравнить переменные из Flash с переменными из RAM, уже знаю как, а как "вытащить" переменную из Flash и записать ее в локальную переменную функции в RAM - не знаю, поэтому мне нужна просто подсказка с синтаксисом оператора, который позволит выполнить такой перенос...
наверное что то вы недопонимаете......
и образец вам кинули, и литературы много....
http://arduino.ru/forum/programmirovanie/ocherednoi-raz-progmem#comment-...
Ещё раз повторюсь, я хотел использовать структуру, все ссылки и вся литература описывает без структур... Мне нужна просто подсказка, вернее, правильный синтаксис строки, которая считает переменную из Flash в RAM, все... Сравнить переменные из Flash с переменными из RAM, уже знаю как, а как "вытащить" переменную из Flash и записать ее в локальную переменную функции в RAM - не знаю, поэтому мне нужна просто подсказка с синтаксисом оператора, который позволит выполнить такой перенос...
Т е ссылка которую я дал - там примера чтения в ram вы не увидели?
А хранить в структуре адрес на строку в pgm вы тоже не догадались?
:(
Ещё раз повторюсь, я хотел использовать структуру, все ссылки и вся литература описывает без структур... Мне нужна просто подсказка, вернее, правильный синтаксис строки, которая считает переменную из Flash в RAM, все...
"подсказок" правильного синтаксиса извлечения строк из флеша тут уже дали не одну и не две...
у вас проблема не со структурой. а вообще с пониманием того, как хранятся строки и массивы во флеше. Возьмите для начала проимер без структур - с массивами и добейтесь того, чтобы он работал. Синтаксис извлечения строк из структуры ТОТ же, что и из массива строк.
А потом - когда у вас чужие примеры заработают - пробуйте перейти к структуре, если она вам так нужна. Непонятно, почему вы за нее так держитесь - экономия памяти при использовании структур и массивов во флеше абсолютно одинаковая.
посмотрел выше - в сообщ #22 sadman41 давал вам пример сравнения строки из флеша и оперативки. Посмотрите внимательно - как у него сделано обращение к полю вашей структуры и как у вас. Сравните внимательно! - у вас там ошибка
Хотя.. все равно же не найдете.Ладно, подскажу - когда вы обращаетесь к своей строке во флеше, вы непонятно зачем выполняете операцию взятия адреса & от массива. Причем вы так делали еще в самом начале ветки и я вас уже поправлял. Поймите - имя массива это и так адрес его первого элемента, а когда вы еще ставите перед ним & - получается "адрес от адреса" - что ерунда.
В прошлом сообщении я был прав - ваши проблемы от непонимания того, как устроены структуры и массивы. Вам бы сначала учебник почитать.
Конечно, же, увидел, НО, в примере, который Вы предложили, как раз таки нет структуры...
Я не держусь за структуру массива, но и понять, действительно не могу, каков должен быть принцип адресации в структуре, в массиве, в массиве строк и его структуре... к сожалению... времени на изучения с нуля, тоже нет...
Честно говоря, я не понимаю, как в структуру "запихнуть" адрес на строку, да и зачем, если сравнить можно и с той структурой, что имеется, то почему нельзя перенести из Flash в RAM...
посмотрел выше - в сообщ #22 sadman41 давал вам пример сравнения строки из флеша и оперативки. Посмотрите внимательно - как у него сделано обращение к полю вашей структуры и как у вас. Сравните внимательно! - у вас там ошибка
Хотя.. все равно же не найдете.Ладно, подскажу - когда вы обращаетесь к своей строке во флеше, вы непонятно зачем выполняете операцию взятия адреса & от массива. Причем вы так делали еще в самом начале ветки и я вас уже поправлял. Поймите - имя массива это и так адрес его первого элемента, а когда вы еще ставите перед ним & - получается "адрес от адреса" - что ерунда.
Я постараюсь сейчас разобраться с указателем...
В прошлом сообщении я был прав - ваши проблемы от непонимания того, как устроены структуры и массивы. Вам бы сначала учебник почитать.
Просто нет на это времени, я ведь не с целью продажи или какого-то бизнеса, просто для себя, для удобства хочу собрать устройство для управления воротами... Как хобби, если хотите... Со временем - разберусь с азов, сейчас времени нет, если появиться время, с азов разберусь...
к сожалению... времени на изучения с нуля, тоже нет...
простите, но после таких заявлений здесь обычно посылают - жестко, матом - и общение заканчивается. Это что за наглость - у вас, видите ли, нет времени это изучать - а у нас. выходит, куча времени чтобы обьяснять вам одно и тоже по 3-4 раза?
Еще раз - работа во флеше со структурой и с массивом отличается минимально и делается одними и теми же командами. Все ссылки, обьясняющие работу с массивом - подходят и для структуры. Вы этого не видите только потому, что вообще слабо знаете программирование...
Такой код, также не работает...
Такой код, также не работает...
Я наверное последний отвечу в этой ветке, т к вы не хотите понимать - неоднократно вам сказали для начала забыть о структуре и сделать тупо выборку из progmem, в конце концов - тупо блин скопируйте из моего скетча несколько строк описания и несколько строк процедуры выборки, вывести в монитор и все.
Вот такой код, возвращает знаки, но не строку...
Такой код, также не работает...
вы похоже, втупую пробуете разные комбинации операторов... опять val описано неправильно.
Так вы программу не напишете. Садитесь за учебники - ваши ворота подождут. Тем более если это хобби, как вы пишете - значит просто сделаете ворота не сейчас. а через полгода-год, когда разберетесь.
Не мог пройти мимо, даже нану новую вытащил из упаковки. Конечно, сообщество меня изругает...
И еще я не совсем уверен, что sizeof можно напускать на такого жука... Ну, если что - поправят.
Почему-то в данном примере помещение строковых констант прямо в массив эквивалентно помещению в массив ссылок на строковые константы (как на arduino.cc), но попытка перетащить данный пример в реальный скетч почему-то дает разные результаты по компиляции. Надо будет этот вопрос изучить. Может компилятор умничает опять.
char val[] = "" - это чего, зарезервировали нуль байт памяти, а потом туда строку копируете? Вы там надеюсь, игрушку-пердушку собираете, а не управление газовым котлом...
вы похоже, втупую пробуете разные комбинации операторов... опять val описано неправильно.
Так вы программу не напишете. Садитесь за учебники - ваши ворота подождут. Тем более если это хобби, как вы пишете - значит просто сделаете ворота не сейчас. а через полгода-год, когда разберетесь.
тут переписал не правильно, указал длину...