AVR мигащ светодиод, програмиране на микроконтролер

Урок 5

Мигащ светодиод

В този урок ще научим как да програмираме в цикъл, както и как да използваме забавяне в изпълнението на кода, в резултат на което нашият светодиод ще стане по-жив. Ще работим и с някои логически операции и операции за изместване на битове в байт.

Първо, ще създадем нов проект. Ще го създадем приблизително по същия начин, както в миналия урок, с единственото изключение, че ще го наречемTest02.

Сега нека започнем да поправяме. Тоест, ще създадем нов код, а старият ще бъде недокоснат в предишния проект. Ще зададем напълно порт D на 0, като променим 1 на 0 в следващия ред

По принцип вече имаме всички крака на портовете, зададени на нула по подразбиране, но все пак ще го направим в името на реда.

Вече ще напишем допълнителен код в тялото на безкраен цикъл и целият този код, който напишем там, ще се изпълнява постоянно и циклично.

Но преди да започнем да пишем код там, бих искал да ви разкажа малко за логическите операции, без които няма никъде в нашия век. Те също ще ни бъдат полезни в кода. Първо ще разгледаме четири основни операции.

Ще извършваме логически операции върху осембитови числа или байтове, които ще представяме като правоъгълници, състоящи се от осем клетки. Първите три операции ще бъдат извършени върху две числа. Вземете например тези:

светодиод

И трите операции се извършват бит по бит, тоест битове с едно и също име се сравняват логически - нула с нула, първият с първия и т.н.

Първата е операцията "И ", означена в C/C++ с "& ". Всеки бит в резултата ще бъде зададен наедно само ако и дветесъответните му битове в операндите ще бъдатединици. Във всеки друг случай получавамеnull.

Следователно ще имаме следния резултат

програмиране

Тоест, в нашия случай само петият бит е зададен на единица, защото петият бит е зададен на единица както в първия операнд, така и във втория.

Извършващата се логическа операция е операцията "ИЛИ ", означена с вертикалната лента " ". В резултат на тази операция ще получимедно, ако поне един бит в сравняваните битове със същото име е зададен наедно. Така ще получимнула само когато и двата сравнени бита съдържатнула.

Ето го резултата

светодиод

Третият вид операция е операцията "XOR ". Тази операция се обозначава със знака "^ ". Тук шансовете битът да стане нула или единица се изравняват. Полученият бит ще стане единица, когато сравняваните битове са непременно различни - единият ще бъденула, другиятедно. И полученият бит ще бъде нула, когато сравнените битове са еднакви.

Така получаваме следния резултат

светодиод

И четвъртата операция е операцията "НЕ ", обозначена със знака тилда - "

", се извършва върху един байт. В резултат на тази операция всички битове се обръщат. Тоестнула ставаедно, аедно -нула. Тази операция се нарича още операцияинвертиране.

Ето резултата, който получаваме

програмиране

Сега да се върнем към кода. Нека напишем следната много неразбираема на пръв поглед команда

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 ));

_закъснение_ms(500);

Сега можете да изключите светодиода. Това става със следната команда

Тук виждаме, че имаме команда, подобна на предишната, въпреки че има някои значителни промени. Първо, нашият логически оператор се превърна в "И ", а също така приложихме инверсията на резултата вдясно.

Нека да разгледаме тази команда. Резултатът отдясно ни е известен - това е0b00000001, ако го обърнем, получаваме съответно0b11111110. Сега трябва да се умножи логически по стойността в променливата вдясно. В момента имаме и0b00000001 там. Съответно ще получим всички нули, тъй като сравняваните битове в операндите са различни за нас. И ако имаше някакво друго число в променливата PORTD, тогава само нулевият бит щеше да бъде нулиран, останалите нямаше да бъдат докоснати. Следователно с такава операция в бъдеще ще нулираме определени битове в регистри и променливи. Можете също така да нулирате няколко бита наведнъж или да зададете, но вече научихме твърде много за това по-късно или дори така. Остава да добавим същото забавяне, така че светодиодът да е в изключено състояние за същата сума. колко и в светлинния

_закъснение_ms(500);

Но това не е всичко. За да работи забавянето правилно, трябва да напишем макрос в началото на модула или main.c файла, който казва на компилатора колко често работи нашия контролер, в противен случай той ще приложи неправилно забавянето и ще ни даде предупреждение. Нека напишем този макрос

#define F_CPU 8000000

Да вземем проекта. Нямаме грешки или предупреждения

Сега можем да видим резултата от работата първо в proteus, след това на живия светодиод и контролера.

За да не създаваме повторно веригата, имаме проектен файл за proetus от папката на проекта откопирайте предишния урок в папката с новия проект и го преименувайте наTest02.pdsprj.

Нека го стартираме. Щракнете двукратно върху изображението на контролера и изберете там друг фърмуер, който съответства на новия проект, и също така задайте подходящата честота в свойствата, в противен случай светодиодът ще мига 8 пъти по-бавно

светодиод

След това ще мигаме истински контролер и ще се уверим, че светодиодът също мига там.

Можете да закупите програмиста тук (продавачът е надежден)USBASP USBISP 2.0