В предишния ни урок научихме за мигането на светодиод с помощта на PIC микроконтролер и изградихме същата схема на платката Perf. След това използвахме PICkit 3, ICSP и MPLAB IPE за изхвърляне на програмата върху нашата платка Perf. Сега, в този урок ще напреднем към себе си, за да използваме повече щифтове на PIC микроконтролера. Ще използваме 7 изхода (светодиоди) и един вход. За този урок ще използваме старата платка Perf (показана по-долу) и ще добавим berg пръчки, за да извадим необходимите щифтове на втората LED платка. В края на този урок ще генерираме последователност от мигащи светодиоди с помощта на PIC микроконтролер PIC16F877A и ще се научим как да използваме множество входове и изходи, някои основи на „for“ цикъл и извикване на функции.
Светодиодната платка не е нищо друго, освен друга перфектна платка, върху която ще спояваме светодиодите с текущ ограничаващ резистор (показан по-долу). Също така ще добавим бутон, за да инициира мигането на светодиода за последователност.
Електрическа схема:
PIC микроконтролер PIC16F877A LED мигащ последователен код и работно обяснение:
Пълният код е даден по-долу (проверете в края), тук ще го получим през ред по ред. Този код ще започне да свети светодиоди последователно при натискане на бутона. За да разберете последователностите, моля, гледайте видеоклипа в края на урока. Бих ви препоръчал да сравните изхода, показан във видеото, с кода по-долу и да се опитате да разберете програмата.
Нека разгледаме кода ред по ред. Първите няколко реда са за настройка на битове за конфигурация, които бяха обяснени в предишния урок, така че засега ги пропускам. Най-добрият начин да разберете всяка програма е да започнете от основната ( void main () ) функция, така че нека направим това
TRISB0 = 1; // Инструктирайте MCU, че PORTB щифтът 0 се използва като вход за бутон. TRISD = 0x00; // Инструктирайте MCU, че всички изводи се извеждат PORTD = 0x00; // Инициализираме всички щифтове до 0
Думата TRIS се използва, за да се определи дали щифтът се използва като вход / изход, а думата PORT се използва, за да се направи пин високо / ниско. Линията TRISB0 = 1 ще направи 0- ия щифт на ПОРТ B като вход. Това ще бъде нашият бутон. Линиите TRISD = 0x00; PORTD = 0x00; ще направи всички изводи на порт D като изход и ще присвои начална стойност LOW на тези изводи.
Тъй като казахме, че B0 се използва като вход, ще свържем единия край на бутона към щифта B0, а другия край към земята. Дотогава, когато натиснем бутона, щифтът ще се задържа на земята, както е показано на схемата за свързване по-горе. Но за да се случи това, трябва да използваме издърпващ резистор, така че щифтът да се държи високо, когато бутонът не е натиснат. Издърпващ резистор е нещо подобно.
Но нашият PIC MCU има вътрешен слаб издърпващ резистор, който може да бъде активиран от софтуер по този начин, спестявайки много неприятности (когато трябва да бъдат свързани повече бутони).
Какво е слаб издърпващ резистор?
Има два типа издърпващ резистор, единият е Слаб издърпване нагоре, а другият е Силен издърпване нагоре. Слабите издърпващи резистори са с висока стойност и по този начин позволяват преминаването на слаб ток, а силните издърпващи резистори са с ниска стойност, което позволява на силен ток да тече. Всички MCU използват предимно слаби издърпващи резистори. За да активираме това в нашия PIC MCU, трябва да разгледаме нашия лист с данни за OPTION_REG (регистър на опциите), както е показано на снимката по-долу.
Както е показано, битът 7 се занимава със слабия издърпващ резистор. Трябва да се направи нула, за да го активирате. Това се прави от OPTION_REG <7> = 0 . Това конкретно се занимава с бита 7, оставяйки останалите битове до стойностите им по подразбиране. С това влизаме в нашия цикъл while, където той проверява дали бутонът е натиснат с помощта на if (RB0 == 0). Ако условието е изпълнено, извикваме нашата функция с параметри 1, 3, 7 и 15.
примигване (1); // FUNCTION CALL 1 с параметър 1 sblink (3); // ФУНКЦИОНАЛНО ПОЗВИЧАНЕ 3 с параметър 3 sblink (7); // ФУНКЦИОНАЛНО ПОЗВИКАНЕ 7 с параметър 7 sblink (15); // FUNCTION CALL 4 с параметър 15
Защо използваме функции?
Функциите се използват за намаляване на броя на редовете в нашия код. Това е, което повечето от нас биха знаели. Но защо трябва да намаляваме броя на редовете, особено когато става въпрос за програмиране на MCU. В причина за това е ограниченото пространство в паметта ни програма. Ако не оптимизираме правилно кода, може да ни свърши паметта. Това ще бъде полезно, когато напишем дълги страници с кодове.
Всяка функция ще има дефиниция на функция ( sblink (int get) в нашия случай) и функция Call ( sblink (1) в нашия случай). Не е задължително да има декларация за функция, за да я избегна, поставих дефиницията на функцията си преди да извикам функцията в основната си функция.
Параметрите на функцията са стойността, която ще бъде предадена от извикването на функцията към дефиницията на функцията. В нашия случай целочислените стойности (1, 3, 7, 15) са параметрите, които се предават от извикването на функция, а променливата "get" получава стойността на параметрите в дефиницията на функцията, за да ги обработи. Функцията може да има повече от един параметър.
След като функцията бъде извикана, ще бъдат изпълнени долните редове в дефиницията на функцията.
за (int i = 0; i <= 7 && RB0 == 0; i ++) {PORTD = get << i; // LED движение Left Sequence __delay_ms (50); } за (int i = 7; i> = 0 && RB0 == 0; i--) {PORTD = get << i; // LED движение Left Sequence __delay_ms (50); }
Сега този ред изглежда странен: PORTD = get << i . Ще обясня какво всъщност се случва тук.
"<<" е оператор за лява смяна, който премества всички битове в лявото си положение. Сега, когато извикаме функцията sblink (int get) с параметър '1' като sblink (1), тя ще направи стойност на 'get' като 1, която в двоичен файл е 0b00000001. Следователно този ред ще бъде като PORTD = 0b00000001 << i .
Стойността на "i" ще варира от 0 до 7, тъй като сме използвали 'for loop' за (int i = 0; i <= 7 && RB0 == 0; i ++). Стойността на „i“ от 0 до 7 ще промени резултата по следния начин:
Както можете да видите, ние включихме по един светодиод (отляво надясно), като оставихме останалите OFF. Следващият 'for loop' за (int i = 7; i> = 0 && RB0 == 0; i--) , също ще направи същото, но този път светодиодът ще бъде включен отдясно наляво в последователност, като започнахме от 7 и слязохме до 0. Използвахме забавяне от 200ms, за да можем да визуализираме включването и изключването на светодиода.
Сега, когато предадем стойност 3 във функцията sblink (int get) , така че функцията sblink (3) ще бъде изпълнена, което прави стойността на "get" като 0b00000011, следователно резултатът на PORTD ще бъде:
Така че сега този път два светодиода ще бъдат включени по всяко време с помощта на sblink (3). По същия начин за sblink (7) и sblink (15), три и четири светодиода ще светнат последователно. След като това е направено, ние ще направим всичко индикаторът да бъде на този ред PORTD = 0xFF . Проверете видеото по-долу за пълна демонстрация.
Надявам се, че сте разбрали кода и по този начин сте се научили как да използвате функциите, цикъл „for“ и „while“, за да получите желаните резултати. Сега можете да промените кода, за да получите различната си последователност на мигащите светодиоди. Продължете да компилирате кода си и да го изхвърлите на вашия MCU и да се насладите на резултата. Можете да използвате раздела за коментари, ако закъсате някъде. Тук съм прикачил и симулационните и програмните файлове.
Това е засега, в нашия следващ урок ще научим как да използваме таймери PIC16F877A, вместо да използваме функции за забавяне. Можете да разгледате всички уроци за PIC микроконтролер тук.