Монк . - Программируем Arduino
- Название:Программируем Arduino
- Автор:
- Жанр:
- Издательство:Издательский дом Питер
- Год:2017
- ISBN:978-5-496-02385-6
- Рейтинг:
- Избранное:Добавить в избранное
-
Отзывы:
-
Ваша оценка:
Монк . - Программируем Arduino краткое содержание
Программируем Arduino - читать онлайн бесплатно полную версию (весь текст целиком)
Интервал:
Закладка:
Сохраняйте строковые константы во флеш-памяти
По умолчанию строковые константы, как в следующем примере, сохраняются в ОЗУ и во флеш-памяти — один экземпляр хранится в коде программы, а второй экземпляр создается в ОЗУ во время выполнения скетча:
Serial.println("Program Started");
Но если использовать код, как показано далее, строковая константа будет храниться только во флеш-памяти:
Serial.println(F("Program Started"));
В разделе «Использование флеш-памяти» далее в этой главе вы познакомитесь с другими способами использования флеш-памяти.
Типичные заблуждения
Многие заблуждаются, полагая, что использование более коротких имен переменных позволяет экономить память. В действительности это не так. Компилятор сам заботится об этом и не включает имена переменных в скомпилированный скетч. Другое распространенное заблуждение: комментарии увеличивают размер программы или объем потребляемой ею оперативной памяти. Это не так.
Некоторые также считают, что организация программного кода в виде множества маленьких функций увеличивает размер скомпилированного кода. Обычно этого не происходит, потому что компилятор достаточно сообразителен для того, чтобы в ходе оптимизации кода заменить вызовы функций их фактическими реализациями. Это обстоятельство помогает писать более удобочитаемый код.
Измерение объема свободной памяти
Узнать, какой объем ОЗУ занимает скетч во время выполнения, можно с помощью библиотеки MemoryFree, доступной по адресу http://playground.arduino.cc/Code/AvailableMemory.
Пользоваться этой библиотекой совсем не сложно: в ней имеется функция freeMemory, возвращающая число доступных байтов. Следующий скетч иллюстрирует ее использование:
#include
void setup()
{
Serial.begin(115200);
}
void loop()
{
Serial.print("freeMemory()=");
Serial.println(freeMemory());
delay(1000);
}
Эта библиотека может пригодиться при диагностике неожиданных проблем, которые, по вашему мнению, могут быть вызваны нехваткой памяти. Конечно же, использование библиотеки ведет к небольшому увеличению потребления памяти.
Уменьшение используемого объема флеш-памяти
По окончании процедуры компиляции скетча в нижней части окна Arduino IDE появится примерно такое сообщение:
Скетч использует 1344 байт (4%) памяти устройства. Всего доступно 32 256 байт.
Эта строка сообщает точный объем флеш-памяти в Arduino, который будет занят скетчем, благодаря чему вы всегда будете знать, насколько близко подошли к пределу в 32 Кбайт. Оказавшись близко к предельному значению, нужно позаботиться об оптимизации использования флеш-памяти. В этом вам помогут рассматриваемые далее рекомендации.
Используйте константы
Многие, стараясь дать имена контактам, определяют для этого переменные, как показано ниже:
int ledPin = 13;
Если вы не собираетесь изменять номер контакта с именем ledPin в процессе выполнения скетча, то вместо переменной можно использовать константу. Просто добавьте слово const в начало объявления:
const int ledPin = 13;
Это поможет сэкономить 2 байта ОЗУ плюс 2 байта флеш-памяти при каждом использовании константы. Для часто используемых переменных экономия может достигать нескольких десятков байтов.
Удалите ненужные трассировочные вызовы
В процессе отладки скетчей для Arduino принято вставлять в код команды Serial.println, помогающие увидеть значения переменных в разных точках программы и определить источники ошибок. Эти команды потребляют значительный объем флеш-памяти. Любое использование Serial.println требует включения в скетч примерно 500 байт библиотечного кода. Поэтому, убедившись в безупречной работе скетча, удалите или закомментируйте все такие команды.
Откажитесь от использования загрузчика
В главе 2 рассказывалось, как запрограммировать микроконтроллер непосредственно через контакты ICSP на плате Arduino с применением аппаратных программаторов. Такой подход поможет сэкономить пару килобайт, так как не требует установки загрузчика.
Статическое и динамическое размещение в памяти
Если вы, подобно автору книги, имеете опыт разработки крупномасштабных систем на таких языках, как Java или C#, вам наверняка приходилось создавать объекты во время выполнения и позволять сборщику мусора освобождать занимаемую ими память без вашего участия. Этот подход к программированию в принципе непригоден для программ, выполняющихся на микропроцессорах, которые имеют всего 2 Кбайт памяти. Ведь в Arduino просто нет никакого сборщика мусора, и, что более важно, в программах, которые пишутся для Arduino, выделение и освобождение памяти во время выполнения редко бывают необходимы.
Ниже приводится пример объявления статического массива, как это обычно делается в скетчах:
// sketch_06_04_static
int array[100];
void setup()
{
array[0] = 1;
array[50] = 2;
Serial.begin(9600);
Serial.println(array[50]);
}
void loop()
{
}
Объем памяти, занимаемой массивом, известен уже на этапе компиляции скетча, поэтому компилятор может зарезервировать для массива необходимый объем памяти. Второй пример, приведенный ниже, также создает массив того же размера, но выделяет память для него во время выполнения из пула доступной памяти. Обратите внимание на то, что версии Arduino IDE ниже 1.0.4 не поддерживают malloc.
// sketch_06_03_dynamic
int *array;
void setup()
{
array = (int *)malloc(sizeof(int) * 100);
array[0] = 1;
array[50] = 2;
Serial.begin(9600);
Serial.println(array[50]);
}
void loop()
{
}
В начале скетча определяется переменная int *array. Символ * сообщает, что это указатель на целочисленное значение (или в данном случае массив целых чисел), а не простое значение. Объем памяти, занимаемой массивом, неизвестен, пока не будет выполнена следующая строка в функции setup:
array = (int *)malloc(sizeof(int) * 100);
Команда malloc ( memory allocate — выделить память ) выделяет память в области ОЗУ, которую называют кучей (heap). В качестве аргумента ей передается объем памяти в байтах, который следует выделить. Так как массив хранит 100 значений типа int, требуется выполнить некоторые расчеты, чтобы определить размер массива в байтах. В действительности можно было бы просто передать функции malloc число 200 в аргументе, потому что известно, что каждое значение типа int занимает 2 байта памяти, но использование функции sizeof гарантирует получение правильного числа в любом случае.
После выделения памяти массивом можно пользоваться точно так же, как если бы память для него была выделена статически. Динамическое распределение памяти позволяет отложить принятие решения о размере массива до фактического запуска скетча, и это единственное преимущество данного подхода.
Однако, используя прием динамического распределения памяти, легко оказаться в ситуации, когда память выделяется, но не освобождается, из-за чего скетч может быстро исчерпать имеющуюся память. Исчерпание памяти может вызвать зависание Arduino. Но если вся память выделяется статически, такого не происходит.
Читать дальшеИнтервал:
Закладка: