Как создать файл pgm
Часто бывает нужно сохранить в памяти микроконтроллера большой объём данных, которые не будут меняться в процессе работы, например:
- Калибровочный массив
- Текст названий пунктов меню
- Просто какой-то текст
- Посчитанная тригонометрия (синус, косинус)
- Изображения для дисплея (bitmap)
- И многое другое
Запись
Ключевое слово (модификатор переменной) PROGMEM позволяет записать данные во Flash память. Синтаксис такой:
Всё! Данные, в показанном случае массивы тип_данных будут помещены во Flash память. PROGMEM может работать со всеми целочисленными типами (8, 16, 32, 64 бита), float и char. Важный момент! Модификатор PROGMEM можно применять только к глобальным (определённым вне функций) или статическим (глобальным или локальным, но со словом static ) переменным! Читай урок про типы данных, если забыл. Полный список возможностей pgmspace можно посмотреть в документации.
Чтение
Если с записью всё очень просто (добавляется ОДНО ключевое слово), то с чтением всё гораздо интереснее: оно осуществляется при помощи специальной функции. Основная функция чтения из progmem – pgm_read_тип(адрес) . Мы можем использовать вот эти 4:
- pgm_read_byte(data); – для 1-го байта (char, byte, int8_t, uint8_t)
- pgm_read_word(data); – для 2-х байт (int, word, unsigned int, int16_t, int16_t)
- pgm_read_dword(data); – для 4-х байт (long, unsigned long, int32_t, int32_t)
- pgm_read_float(data); – для чисел с плавающей точкой
Одиночные числа
Что здесь важно помнить: читая отрицательные числа (например типы int и long ) нужно обязательно приводить тип, потому что PROGMEM хранит числа в беззнаковом представлении. Обратите внимание на чтение signed_data из примера выше, без приведения к int число выводилось некорректно!
Одномерные массивы
С массивами чисел всё весьма ожидаемо:
Читай урок по массивам в блоке базовых уроков программирования.
Двумерные массивы
При создании двумерного массива нужно обязательно указывать размер хотя бы одной из размерностей!
Массив массивов
Можно хранить несколько массивов в одном, т.н. таблица ссылок.
Строки
PROGMEM позволяет сохранять строки как массивы символов, char :
Чтение осуществляется посимвольно, при чтении обязательно приводим тип к char . Также вы могли заметить, что для вычисления длины массива символов мы использовали функцию strlen_P() , это аналог strlen() (см. урок про строки), но специально для PROGMEM строк. Полный набор инструментов для работы со строками в PROGMEM можно посмотреть в документации, их там много.
Массивы строк
Задача усложняется, не правда ли? =) Можно пойти другим путём: создать char буфер, в который скопировать всю строку из PROGMEM при помощи функции strcpy_P() , которая копирует указанные данные из PROGMEM в обычный массив. Получаем обычный массив символов, который можно даже напрямую вывести в порт:
Рассмотрим ещё пример, в котором будем выводить строку из памяти без тяжёлых дополнительных функций. Также этот пример корректно работает при выводе через цикл (в отличие от предыдущих примеров), за пример спасибо Виктору Струговцу:
Функцию для печати строк в сериал или на дисплей из PROGMEM можно вынести в отдельную функцию. Финальный пример:
[ОБНОВЛЕНИЕ!] Чуть исправленный финальный пример, работает более корректно:
Полный набор инструментов для работы со строками в PROGMEM можно посмотреть в документации.
F() макро
Читайте также: