Использование PROGMEM для экономии оперативной памяти
Мне удалось поместить и получить массив символов во флэш-память Arduino с помощью PROGMEM массивы символов.
Я создаю свое приложение, используя файлы заголовков с определением/реализацией класса, и хотел бы хранить строки в одном файле заголовка.
Если я определю другой массив символов PROGMEM, ни один из них не сможет быть выполнен. Другими словами, эти PROGMEM представляют собой глобальные массивы с точки зрения компилятора Arduino. Они компилируются, но не отображаются.
Вот мой тестовый код:
lcd.clear();
lcd.print(*strFlashDebug[0]); // в CDebug
lcd.setCursor(0,1);
lcd.print(*strFlashTrack[0]); // в CTrack
Если я помещу оба определения в один и тот же заголовочный файл, он будет работать только с одним включенным lcd.print, а не закомментированным.
Похоже, что можно определить и скомпилировать несколько массивов PROGMEM, но фактически можно использовать только один. Какое объяснение?
@Vaclav, 👍1
Обсуждение2 ответа
Определение переменной PROGMEM (т. е. объявление) выделяет память во FLASH. Вам необходимо использовать предложение extern в заголовочном файле и физическое объявление в коде C, связанное с вашим кодом. Это также выгодно для потенциальных свойств статического класса.
Также проверьте, принимает ли lcd.print() массив PROGMEM, т. е. определена и вызвана перегруженная процедура.
Обратите внимание, что я рекомендую использовать гораздо более эффективное форматирование строк с помощью файловых потоков (FILE) и fprintf_P().
Для PROGMEM важно знать, что чип AVR, который вы используете, не имеет ни одного плоское адресное пространство. Т.е. он не использует архитектуру фон Неймана; вместо этого он использует определенную версию так называемой Гарвардской архитектуры: она имеет отдельные адресные пространства для оперативной памяти и программной памяти. и ЭСППЗУ. Все они начинаются с 0. Это означает, что, хотя разыменование нулевого указателя технически все еще является неопределенным поведением в C++, оно может быть (и часто является) совершенно допустимым в коде Arduino.
Краткая версия: если у вас есть указатель PROGMEM, любая функция, которой вы его передаете, должна работать с указателями PROGMEM. lcd.print
нет, и, насколько я могу судить, функция не может каким-либо образом обнаружить, что это не указатель ОЗУ. Вам придется вызвать другую функцию, если она изначально есть.
См. PROGMEM (справочник по Arduino) для примеров использования данных PROGMEM.< /п>
Чтобы дополнить это прекрасное описание, вы можете в качестве обходного пути временно скопировать в ОЗУ данные PROGMEM, которые вам нужно передать в lcd.print()
, и передать ему эту копию. Функция-обертка, скажем, lcd_print_PMEM(), может инкапсулировать детали, а используемая оперативная память будет выделяться буквально только на время этого вызова., @JRobert
- Как использовать SPI на Arduino?
- Как решить проблему «avrdude: stk500_recv(): programmer is not responding»?
- Как создать несколько запущенных потоков?
- Как подключиться к Arduino с помощью WiFi?
- avrdude ser_open() can't set com-state
- Как узнать частоту дискретизации?
- Что такое Serial.begin(9600)?
- Я закирпичил свой Arduino Uno? Проблемы с загрузкой скетчей на плату
Пожалуйста, опубликуйте также определения своих массивов или, еще лучше, полный компилируемый пример с достаточным количеством кода, чтобы проиллюстрировать проблему., @user2973