AVR Урок 42
Урок 42
EXINT или външни прекъсвания
И накрая, време е да се опитаме да работим с външни прекъсвания. Този урок, първо, беше много търсен, въпреки че изглежда прост на пръв поглед. Имаше много молби и нямаше как да не отговоря. Второ, в момента работим с модула LANENC28J60, който има изход, чрез който можем да получаваме прекъсвания в края на определени операции, които исках да обработя. Освен това, ако успея, исках да го споделя с вас, но без първоначално разбиране на външните прекъсвания в AVR контролера, мисля, че няма да е лесно за разбиране, меко казано. Ето защо този урок е узрял.
Тъй като случайно заключих моя контролерATMega328, разположен на евтина платка, ще работим с платкатаArduino UNO.
Не, не се притеснявайте, ние няма да работим с Arduino IDE, ние също ще работим със същото Atmel Studio, само че ще използваме Arduino като развойна платка и ще го програмираме презISP конектора.
Като цяло, докато пристигнат по-малки платки, ще пиша уроците си с Arduino UNO и ще работя със същата платка с LAN модула.
Също така това, което се оказа добро за Arduino е, че не изисква TTL-USB адаптер, тъй като вече е перфектно внедрен там в хардуера. И освен това, ние не само ще използваме USART през стандартния USB конектор на Arduino, но също така ще захранваме нашия Arduino през него.
Ще използваме и евтин USBASP като програматор. Тъй като го имам с превключвател 3.3V / 5V, след това премахвайки джъмпера от него напълно, ще го изключим напълнозахранване от програмиста към платката и ние ще програмираме нашата платка само през ISP.
Тъй като на платката Arduino има 6-пинов ISP конектор, ще използваме стандартен ISP адаптер
След като свържем програмиста към платката, ще получим тази картина
Нека свържем USB конектора към компютъра - сега имаме готов USART изход на компютъра, както и захранване
Да се върнем на нашите прекъсвания. Външните прекъсвания са такива прекъсвания, които се обработват поради появата на някакви събития на конкретен щифт на порта на микроконтролера. Има няколко такива събития. Прекъсванията на AVR контролера могат да се задействат както на нивото, така и на ръба. По ниво те стрелят, когато се види определено логическо ниво. Тоест, ако е конфигурирано задействано от логическо едно ниво, тогава ако това ниво остане на външния щифт за прекъсване, прекъсването ще се задейства циклично, докато не бъде зададено друго логическо ниво. А по фронта - когато се забелязва преходът от едно логично състояние към друго. Предната част, както знаете, може да бъде възходяща или низходяща. Казват също, че вместо възходяща, това е просто фронт, а вместо низходяща, това е рецесия. Нарича се още предна и задна предна част. Като цяло е удобно за всеки.
Контролерът има два крака за проследяване на външни прекъсвания -INT0 иINT1. Първият щифт съвпада с щифта на портаPD2, а вторият щифт съвпада сPD3
Сега малко за хардуерната организация на външните прекъсвания. Горните крака са зададени по подразбиране, но могат да се променят. За да направите това, в контролера има определени регистри. Но тази тема няма да се разглежда днес, ще работим с неякрака отгоре, така че ще разгледаме само регистрите, от които се нуждаем.
Първият регистър е управляващият регистър за тип обработено събитие -EICRA
Двойка битовеICS01 иICS00 контролира типа събития на кракаINT0, а втората -ICS11 иICS10 -INT1
Ето зависимостта на типовете събития от включването на битовеICS01 иICS00
И това е заICS11 иICS10
Съответно получаваме следната зависимост:
00 - Ниско ниво на крака,
01 - Всяка промяна на крака,
10 — падащ ръб на крак,
11 — възходящ ръб на крака.
Вторият регистър е регистърът за разрешаване на щифта за прекъсванеEIMSK
В този регистър има само два бита, които позволяват прекъсвания на съответните изводи - INT1 и INT0. Битовете се наричат така, така че няма да бъркаме.
Третият регистър е регистърът на флаговетеEIFR, задавани и нулирани при определени събития
Нямаме директен достъп до този регистър, тъй като ще работим с манипулираща функция.
Сега изглежда нещо се изясни по въпроса за външните прекъсвания.
Остава случаят за малките. Създайте и флашнете проект, който по някакъв начин ще демонстрира работата на външни прекъсвания.
Нека да стартираме Atmel Studio 7, да създадем проект с имеEXTI01, да изберем контролераATmega328P, да добавим функцията за инициализация на портport_ini към main.c, в която ще включим LED крака за изхода. Светодиодът на платката се намира на кракаB6
void port_ini ( void )
//Включете LED крака към изхода
DDRB = 0b00100000;
Нека извикаме тази функция вmain()
int main ( void )
port_ini();
докато (1)
Свържете бутона между крака PD2 (D2) и общия проводник
Нека се върнем към проекта и да напишем функция за инициализиране на външни прекъсвания. Нека настроим падащ фронт, тъй като можем програмно да издърпаме резистора, за да елиминираме неопределено състояние на крака само към захранването и ще имаме логическа 1 на крака в нормално състояние
void int_ini ( void )
//разрешаване на INT0 прекъсвания при падащ фронт
EICRA = (1
//разрешаване на външни прекъсвания INT0
EIMSK = (1
Нека извикаме тази функция в main() и не забравяйте да активиратеглобални прекъсвания
int_ini();
sei();
Нека за всеки случай поставим този крак на входа и издърпайте резистора към захранването. В тази ситуация е по-добре да издърпате резистора, тъй като може да възникне недефинирано състояние. За да направите това, добавете подходящия код към функциятаport_ini
//Активиране на пин INT0 (PD2) за въвеждане на
//Издърпайте резистора на пин INT0 (PD2) за захранване
PORTD = 0b00000100;
Също така трябва да добавим самия манипулатор на прекъсвания, в който при възникване на конфигурирано събитие на крака на порта ще светне нашият светодиод
ISR (INT0_vect)
PORTB = 0b00100000;
Нека съберем кода, флашнете контролера и опитайте да натиснете бутона
Както виждаме, нашият светодиод светва.
Сега нека се опитаме да тестваме и друг крак - INT1.
За да направите това, първо конфигурирайте този крак вport_ini()
//Активиране на пиновеи INT0и INT1 (PD2и PD3 ) към входа
(0b00001 100);
// Набиранерезисторs на щифтовеax INT0и INT1 (PD2и PD3 ) към захранването
PORTD = 0b00001 100;
След това преконфигурираме прекъсванията, като вземем предвид този етап и във функциятаint_ini()
// разрешаване на прекъсвания INT0и INT1 на спадащия фронт
EICRA =(1
//разрешаване на външно прекъсване INT0и INT1
EIMSK =(1
Но манипулаторът за този крак има свой отделен, така че ще го добавим и светодиодът в него ще изгасне
ISR ( INT1_vect )
Сега можем да свържем друг бутон към кракаPD3 (D3), като също го свържем към общия проводник с втория проводник, съберем кода, мигаме контролера и натискаме бутоните и проследяваме резултатите от промяната на нивата от светодиода
Сега, ако съберем кода и мигаме контролера, тогава първият бутон ще включи нашия светодиод, а вторият ще го изключи.
Изглежда, че има такова нещо? И фактът, че това се случва вече независимо от хода на самата програма, не е в безкраен цикъл, когато по време на писмения манипулатор при натискане на бутона може изобщо да ни няма и вече няма да е ясно дали събитието ни ще бъде обработено. Следователно, след като проучихме външните прекъсвания, направихме голяма крачка напред към независимостта на обработката на определени събития на щифтовете на портовете на микроконтролера. Разбира се, предвид нашия вече много богат опит, не ни беше много трудно да направим това.
Купете платката Arduino UNO R3тук.
Гледайте ВИДЕО УРОК (щракнете върху снимката)