Int0 în colțul avr întunecat al foii de date, viața embederelor

Pe această caracteristică a comportamentului de întrerupere externă în AVR, atenția mea a fost trasă de un coleg pe forumul Rtmip Radiochat. Întrebarea ma interesat și am făcut o mică cercetare, ale cărei rezultate sunt oferite cititorilor de mai jos.







Desigur, înainte de a începe cercetarea, avem nevoie de muzica potrivită - rareori lucrez în tăcere.

Deci, esența chestiunii. După cum se știe, întreruperile (toate, și nu numai în AVR) sunt aranjate după cum urmează: există registre de control, valorile din ele permit / dezactivează / dezactivează local întreruperile de interes; există registre de steaguri - atunci când are loc un eveniment, care este destinat pentru a declanșa o întrerupere, pavilion de întrerupere este un interes în hardware armat. atunci dacă întreruperile sunt activate la nivel global, tranziția la handler este efectuată imediat și, dacă este dezactivată la nivel global, tranziția spre handler este efectuată după starea activă a pavilionului de interes imediat ce întreruperile sunt rezolvate din nou.

întrerupere externă INT0, servind ca subiect al acestui articol poate fi generat în mai multe cazuri, în special la pulsul din față a piciorului, dezintegrarea impulsului de a schimba starea și nivelul scăzut de pe picior. Și aici începe o interesantă - în cazul în care se citește în fișa tehnică, se poate citi că Bude Întrerupere configurat de un nivel scăzut, pavilionul său este întotdeauna șters.

De ce? Și ce zici de chemarea unui manipulant? Și ce se întâmplă dacă întreruperea are loc într-un moment în care întreruperile sunt interzise la nivel global? Cum știe controlorul ce a fost? Și va ști?

Pentru a răspunde la aceste întrebări, am descoperit aspectul, am scris un mic test, al cărui cod este enumerat mai jos, și a efectuat mai multe experimente.

1. Da, când configurați o întrerupere a nivelului, panoul de întrerupere este întotdeauna resetat.

2. În același timp, dacă întreruperile sunt activate la nivel global, întreruperea este apelată fără a seta steagul! Miracole!

3. Dacă nivelul de pe picior sa întâmplat în momentul în care întreruperea a fost interzisă (și a dispărut înainte de rezoluție), evenimentul va fi pierdut. Controlerul nu știe despre asta, spre deosebire de modurile de răspuns la schimbarea față / jos / nivel.

Desigur, ieșirea este corectă nu numai pentru INT0, ci pentru INT1 - ele sunt identice.

Care este sensul profund al acestui regim? Dacă te uiți la lucrurile filosofice, se poate presupune că modul de sensibilitate s-a adăugat nivelul numai în scopul de a afișa controler de la o putere scăzută, deoarece marginea întrerupere / toamna / schimbare nu funcționează atunci când ceasul este oprit, dar nivelul de întrerupere lucrează și trezește cu succes MC.







Dar, pentru a forța dispozitivul în modul activ și poate fi orice întrerupere a PCINT set. De ce avem nevoie de o prelucrare ciudată INT0? Răspunsul poate fi găsit dacă citiți foaia de date despre ceva fosil din seria AVR; de exemplu, pe AT90S1200. În acei ani, dar nu au existat PCINT ultramoderne, dar au fost moduri destul de redus de energie și nevoia de a iesi din ele sunt încă într-un alt mod decât resetarea sistemului - care a venit cu un truc viclean pentru a INT0. Acum, acest lucru este, evident, nimic mai mult decât un tribut adus de compatibilitate, deoarece întreruperea nivelului general de incomod - funcționează în mod constant, până la nivelul actual (o șansă de potențial pentru a închide controler), și, de obicei reacția necesită o stare de picioare schimbare nume - apăsarea butonului, operația senzor care altceva de acest fel. Deoarece, de fapt, foarte puțini oameni acordă atenție caracteristicilor descrise.

Mai jos este codul pentru test. Este scrisă în stilul "coșmarului Vga" - în C, este saturată de directive de compilare condiționată, înlocuire macro și chiar conține câteva numere magice, în general am fost desenată. 😀 program de testare permite întreruperea INT0 în diferite moduri și în diferite moduri, în funcție de anumite directive preprocesor. Pentru modurile 1 și 2 (teste de întrerupere și semnalizare), este necesară o rezistență externă de tracțiune și butonul modul 3 (test de întrerupere în timpul interdicției globale de întrerupere) funcționează autonom.

Corecția corectă a unui singur drapel arată ca EIFR = _BV (INTF0); Cu toate acestea, în acest exemplu nu este esențial.

Și vezi ce o fată cu ochelari cântă ...

Ok, deci hai să facem asta:
Înainte de blocarea întreruperilor, adăugați:
PORTC = EIFR;
_delay_us (50);
PORTC = 0;
și după blocare, eliminați sei ();
Firește, trebuie să configurați portul C pe ieșire.

Crede-mă, vei fi foarte surprins!

Ceea ce ați numit interdicția de întrerupere int0, nu se întâmplă nimic altceva decât - anularea handler-ului, întreruperea, la nivel hardware.

mască; / * mod greșit! * /
Operatorul de biți "nu" (

) va promova, de asemenea, valoarea în mască la un int. Pentru a păstra o valoare de 8 biți, tastați înaintea operatorului "nu":
var = (caracterele nesemnate)

și mai mult, astfel:
EICRA = _BV (ISC01) | _BV (ISC00); // TESTED_MODE_MASK;

nu, trebuie mai întâi să dezactivați întreruperile.

Nu a observat imediat actualizarea articolului 🙂 Acum totul este corect. (despre EIFR | = _BV (INTF0)).

Într-un fel legat întotdeauna întrerupe evenimentele. Un eveniment este o schimbare a sistemului. Fața în ascensiune, frontul care se încadrează, sunt toate modificări ale sistemului. Aceasta înseamnă că acestea sunt evenimente. Deci, ele se încadrează în paradigma întreruperii. Totul este logic. Și dacă nu se schimbă nimic în sistem, unde este evenimentul? Toată viața de pe unitatea de picior nivel (zero) - acest lucru nu este un eveniment, este o stare constantă. Răspunde la starea de echilibru - acest lucru este ceva prostesc și smacks de incompetență. Prin urmare, de asemenea, nu înțeleg semnificația întreruperilor-în-nivel. Din punctul meu de vedere, acesta este un fel de "anacronism". De asemenea, cred că dezvoltatorii AVR controler a fost dificil, în primul rând pe trăgaci port de intrare microcontroler care ar „Platoon“ eveniment.

Da, se pare că acest lucru nu este într-adevăr făcut dintr-o viață bună. Dar, apropo, așa cum am fost din nou impusă de Rtmip. în mega8, de exemplu, nu există nici un PCINT. Prin urmare, singura cale din afară de a trezi MK, fiind într-o stare de somn, este o întrerupere atât de ciudată sau resetarea sistemului.

EIFR | = _BV (INTF0); // Ștergeți steagul







Trimiteți-le prietenilor: