AVR Миготливий світлодіод, Програмування мікроконтролерів
Урок 5
Миготливий світлодіод
У цьому уроці ми навчимося програмувати в циклі, а також використовувати затримку виконання коду, в результаті чого світлодіод стане більш живим. Також ми попрацюємо з деякими логічними операціями та з операціями зсуву біта в байті.
Спочатку ми створимо новий проект. Створимо ми його приблизно за тією ж схемою, як і на минулому занятті, за винятком тільки, того, що назвемо ми його Test02 .
Тепер розпочнемо виправлення. Тобто ми створимо новий код, а старий у нас буде недоторканим у минулому проекті. Порт D ми повністю встановимо в 0, змінивши 1 на 0 у наступному рядку
У принципі, у нас уже всі ніжки порту за умовчанням встановлені в нуль, але все одно зробимо це для порядку.
Подальший код ми вже писатимемо в тілі нескінченного циклу і весь цей код, який ми там напишемо, буде виконуватися постійно і циклічно.
Але перш, ніж ми туди почнемо писати код, я хотів би трохи розповісти вам про логічні операції, без яких у наш час нікуди. Також вони нам знадобляться і в коді. Насамперед ми розглянемо чотири основні операції.
Логічні операції ми будемо проводити над восьмибітовими числами або байтами, які ми представимо у вигляді прямокутників, що складаються з восьми осередків. Перші три операції виконуватимуться над двома числами. Візьмемо, наприклад такі:

Усі три операції робляться побітно, тобто логічно порівнюються однойменні біти — нульовий із нульовим, перший із першим тощо.
Перша - це операція "І ", що позначається у мові C/C++ знаком "& ". Будь-який біт в результаті буде встановлений водиницю тільки в тому випадку, якщо обидвавідповідних йому біта в операндах будутьодиницями. У будь-якому іншому випадку ми отримуємонуль.
Тому результат у нас буде наступний

Тобто в одиницю у нас встановлений у нашому випадку лише п'ятий біт, тому що п'ятий біт встановлений в одиницю як у першому операнді, так і в другому.
Зроблена логічна операція - це операція "АБО ", що позначається вертикальною рисою " ". В результаті цієї операції ми отримаємоодиницю, якщо хоча б один біт у порівнюваних однойменних бітах буде встановлений водиницю. Таким чином,нуль ми отримаємо тільки тоді, коли в обох порівнюваних бітах буденуль.
Тому тут буде вже такий результат

Третій вид операції - операція "Виключає АБО ". Ця операція позначається знаком "^ ". Тут шанси у біта стати нулем чи одиницею зрівнюються. Одиницею результуючий біт стане тоді, коли порівнювані біти обов'язково будуть різними - один буденулем, інший -одиницею. А нулем буде результуючий біт тоді, коли порівнювані біти будуть однаковими.
Отже, отримаємо наступний результат

А четверта операція - операція "НЕ ", що позначається знаком тильда - "
В результаті даної операції всі біти змінюються зворотний. Тобтонуль стаєодиницею, аодиниця —нулем.Цю операцію ще називають операцієюінвертування.
Ось такий отримаємо результат

Тепер повернемося до коду. Напишемо наступну дуже незрозумілу на перший погляд команду
PORTD = (1 PORTD0));
Перший незрозумілий оператор у цій команді - це здвоєний оператор "= ". Такого родуоператорів є кілька. У разі спочатку результат, який вийде у правій частині, відразу присвоюється змінної. яка знаходиться у правій частині, а складається логічно по "АБО " зі значенням, що зберігається до цього в пермінній, яка знаходиться праворуч. Потім результат, отриманий після застосування даної логічної операції, присвоюється змінної, що знаходиться в правій частині. Також існують подібні операції типу "+= і "-= ", якими ми надалі дуже часто користуватимемося.
Тепер нам лишилося цей результат отримати. А ми навіть не знаємо, що за оператор у нас у правому виразі у вигляді стрілочок. А це один із двох варіантів бітових зрушень, які можуть здійснюватися над числами.
Бітові зрушення бувають двох видів:
">> " - зсув врівно.
Давайте зупинимося на них трохи докладніше.
Бітовий зсув зрушує всі біти числа праворуч або ліворуч на кількість положень, що знаходиться в числі праворуч. Число може бути різним. В результаті зсуву найкращі біти, що знаходяться в стороні, в яку зсуваємо зникають в нікуди, а біти, що знаходяться в протилежному боці, в які зрушуватися нема чому, тобто вони крайні, заповнюються нулями.
Давайте проробимо дані операції над певним байтом


Ну, я гадаю, зі зрушенням все ясно. Давайте проробимо цю операцію над нашим прикладом у коді
Одиниця, що стоїть ліворуч - це число, над яким проводиться операція, а не число, на яке ми зрушуємо байт побитно, як багато хто плутає. Запам'ятайте це міцно! Тобто в нашому випадку це одиниця або в двійковому вираженні0b00000001. АPORTD0 - це константа, яка визначена в макросі у файліio.h. Ось різновидиданих констант
#define PORTD7 7
#define PORTD6 6
#define PORTD5 5
#define PORTD4 4
#define PORTD3 3
#define PORTD2 2
#define PORTD1 1
#define PORTD0 0
Тобто в нашому випадку це нуль. Ось і виходить, що ми одиницю зрушуємо вліво на нуль положень. В принципі, в результаті операції нічого з нашою одиницею не відбудеться і вона також залишиться одиницею, але код стане наочним і ми бачитимемо, що ми нульову ніжку порту встановили в одиницю.
Далі ми робимо операцію "АБО" між значенням, що знаходиться в зміннійPORTD і даним результатом, що дорівнює одиниці. Так як у нас в порту D в даний момент знаходиться нуль на всіх ніжках, то ми тільки встановимо одиницю на нульовій ніжці, так як0b00000000 та0b00000001 в результаті даної операції дадуть на>0b00000001. Але якби в регістрі порту D знаходилося б якесь інше число, то ми також встановили б одиницю в нульовому биті, а інші біти не рушили б. Тобто ми в результаті команди отримали і лояльну до інших лапок операцію, і в той же час ця операція має дуже наочний і читабельний вигляд.
Взагалі, ми запалили даний світлодіод. Але перш ніж нам його погасити, ми зобов'язані застосувати відповідну затримку, тому що якщо нам одразу написати команду, що обнулює біт, то вона його обнулює практично миттєво. Для затримки є дві команди
_delay_ms ( число в мілісекундах )
_delay_us ( число в мікросекундах )
Також, щоб скористатися функціями затримки, нам необхідно підключити ще один заголовковий файл на початку модуля
#include
Ми скористаємося першою командою та застосуємо затримку на 500 мілісекунд
PORTD = (1 PORTD0));
_delay_ms (500);
Тепер можна погасити світлодіод. Робиться це за допомогою наступної команди
Тут ми бачимо, що у нас команда схожа на нашу попередню, хоч є деякі суттєві зміни. По-перше, наш логічний оператор перетворився на "І ", а також ми застосували інверсію результату праворуч.
Давайте розберемо цю команду. Результат праворуч нам відомий - це0b00000001, якщо ми його інвертуємо, то отримаємо відповідно0b11111110. Тепер його потрібно помножити логічно на значення в змінній праворуч. На даний момент там у нас також0b00000001. Відповідно отримаємо ми всі нулі, тому що порівнювані біти в операндах у нас різні. А якби було якесь інше чесло у змінній PORTD, то у нас би скинувся лише нульовий біт, решта б не рушила. Тому ось такою операцією в майбутньому ми і скидатимемо певні біти в регістрах та змінних. Також можна скидати одразу кілька бітів або встановлювати, але про це пізніше, а то й так ми надто багато вже дізналися. Залишилося нам додати ще таку ж затримку, щоб світлодіод знаходився в згаслому стані стільки ж. скільки і в тому, що світиться
_delay_ms (500);
Але це ще не все. Щоб затримка коректно працювала, ми зобов'язані ще на початку модуля або файлу main.c написати макрос, який говорить компілятору про те, з якою частотою працює наш контролер, інакше він неправильно застосує затримку і нам дасть попередження. Напишемо цей макрос
#define F_CPU 8000000
Зберемо проект. У нас помилок та попереджень немає
Тепер ми можемо подивитися результат роботи спочатку у протеусі, потім на живому світлодіоді та контролері.
Щоб нам заново не створювати схему, ми файл з проектом для проектування з папки з проектом зминулого уроку скопіюємо в папку з новим проектом і перейменуємо наTest02.pdsprj.
Запустимо його. Клацнімо подвійним клацанням по зображенню контролера і виберемо там іншу прошивку, що відповідає новому проекту, а також виставимо у властивостях відповідну частоту, інакше світлодіод блиматиме у 8 разів повільніше

Потім пройдемо справжній контролер, і також переконаємося, що світлодіод блимає і там.
Купити програматор можна тут (продавець надійний)USBASP USBISP 2.0