Добавить в корзинуПозвонить
Найти в Дзене
Николай Анатийчук

Blink на ардуино различными способами. Или облегчаем Blink.

Здравствуйте! Сегодня мы рассмотрим мигание светодиодом на ардуино. Для начала возьмём обычный blink из примеров в Arduino IDE. Как видим этот пример очень прост в написании и понимании, но давайте теперь обратим внимание на занимаемый объём памяти такой программой. Любому нормальному человеку понятно, что 924 байта флеша просто чтобы помигать светодиодом это мягко сказать многовато, да и переменных мы никаких здесь не используем, чтобы 9 байт на глобальные переменные тратить. В общем нужно искать способ как уменьшить вес кода. Первым делом мы можем заменить delay(1000) на _delay_ms(1000), также вверху нужно будет добавить #define F_CPU 16000000, данная строка сообщает функции _delay_ms() что микроконтроллер работает на чистоте 16МГц. В итоге мы получили 770 байт флеша (что на 154 байта меньше чем было) и по прежнему 9 байт занимают глобальные переменные, но нас это не устроит и мы пойдём дальше. Дело в том, что в микроконтроллере есть регистры, в нашем случае у Atmega328P

Здравствуйте! Сегодня мы рассмотрим мигание светодиодом на ардуино. Для начала возьмём обычный blink из примеров в Arduino IDE.

-2

Как видим этот пример очень прост в написании и понимании, но давайте теперь обратим внимание на занимаемый объём памяти такой программой.

-3

Любому нормальному человеку понятно, что 924 байта флеша просто чтобы помигать светодиодом это мягко сказать многовато, да и переменных мы никаких здесь не используем, чтобы 9 байт на глобальные переменные тратить. В общем нужно искать способ как уменьшить вес кода.

Первым делом мы можем заменить delay(1000) на _delay_ms(1000), также вверху нужно будет добавить #define F_CPU 16000000, данная строка сообщает функции _delay_ms() что микроконтроллер работает на чистоте 16МГц.

-4

В итоге мы получили 770 байт флеша (что на 154 байта меньше чем было) и по прежнему 9 байт занимают глобальные переменные, но нас это не устроит и мы пойдём дальше. Дело в том, что в микроконтроллере есть регистры, в нашем случае у Atmega328P их 32, все они 8 битные, хотя три последних могут быть 16 битными, но пока нам это неинтересно. Сейчас нас интересуют регистры DDRB и PORTB. Так как именно они отвечают за состояние порта B, по сути ардуиновские функции pinMode() и digitalWrite() работают именно с этими портами, просто в них ещё содержится кучу сейчас ненужного нам кода. Что разобраться с этими регистрами, нам нужна распиновка платы Arduino, в нашем случае Nano.

-5

Мы видим, что около 13 пина платы, к которой подключен светодиод, имеется прямоугольничек с надписью PB5, это обозначает что за 13 пин отвечает 5 бит регистра PORTB (PORTB5). А за переключение пина 13 в состояние входа или выхода отвечает тоже 5 бит ,но уже регистра DDRB. 1 в 5 бите регистра DDRB устанавливает пин 13 (PB5) в состояние выхода, 0 напротив устанавливает на вход, в регистре PORTB ,1 в 5 бите устанавливает высокий логический уровень пина 13, а 0 низкий. Следовательно нам надо загрузить значение 0b00100000 (в двоичной системе наглядней, счёт битов в регистре идёт от младшего к старшему) в регистр DDRB, а в PORTB через каждую секунду попеременно 0b00100000 и 0b00100000.

-6

В итоге получаем 492 байта флеша и по прежнему 9 байт занимают глобальные переменные.

А теперь удаляем void setup() и void loop(), вместо void setup() пишем функцию int main(), а вместо void loop() пишем цикл while(1) в функции int main().

-7

Мы получили 178 байт флеша и 0 байт оперативки. Но даже ещё это не всё, мы можем заменить на:

DDRB |= (1<<PB5);

PORTB |= (1<<PB5);

PORTB &= ~(1<<PB5);

-8

В итоге имеем 176 байт флеша и 0 байт оперативной памяти. Если посмотреть то мы можем и ещё уменьшить вес кода, если применим исключающее или.

PORTB ^= (1<<PB5);

-9

Теперь мы получили 162 байта флеша и 0 байт занимают глобальные переменные. И на этом мы заканчиваем.

Вывод

Сегодня мы научились рационально мигать светодиодом. Мы уменьшили на 924 - 162 = 762 байта вес флеша более чем в 6 раз), а также избавились от глобальных переменных.