CURSUL 04

Porturi de Intrare și Ieșire

Durată: 121 min de predare Nivel: licență, anul II - recomandat după Cursul 03 Disciplină: Microcontrollere și Microprocesoare Laborator asociat: Laboratorul 02 PDF: descarcă suportul EN English version

Un microcontroler care nu poate atinge lumea din jurul lui nu este bun la nimic. Valoarea practică a sistemului se măsoară în ceea ce reușește să citească de la senzori și în ceea ce reușește să comande către actuatoare - legătura se face prin porturile de intrare și ieșire. Un pin digital pare, la prima vedere, un simplu fir pe care programul pune 0 sau 1. În spatele lui stă însă un circuit cu bistabile, tranzistoare de putere, diode de protecție, o rezistență comutabilă și un lanț de sincronizare - iar necunoașterea lui produce exact acele defecte care par inexplicabile: un buton care își schimbă starea singur, un impuls care nu se vede niciodată în program, un LED care arde portul.

1Obiectul și structura cursului6 min

Capitolul urmărește, pe rând, structura hardware a unui pin, registrele software care îl controlează, drumul semnalului dinspre exterior spre nucleu, problemele care apar pe acest drum și circuitele exterioare care se conectează în mod obișnuit la porturi. Microcontrolerul de referință rămâne ATmega328P, cu avantajul unei organizări deosebit de clare: trei registre pe port și o corespondență directă între bit și pin.

Recapitulare din cursurile anterioare
  • Un SFR e o interfață între program și un circuit periferic concret (Cursul 02)
  • Modificăm întotdeauna un singur bit dintr-un registru (|=, &=~, ^=), niciodată tot registrul, cu excepția inițializărilor (Cursurile 02-03)
Astăzi aplicăm exact aceste reguli pinilor de port, cea mai simplă și mai folosită formă de comunicare cu exteriorul.
  • Să distingeți DDRx, PORTx și PINx după rol, și să explicați de ce sunt necesare trei registre
  • Să explicați cele patru regimuri electrice ale unui pin (DDRx/PORTx) și consecințele fiecăruia
  • Să explicați metastabilitatea și rolul sincronizatorului cu două etaje
  • Să dimensionați o rezistență de pull-up sau de limitare pentru un LED
  • Să recunoașteți un conflict de funcție multiplă pe un pin, și să filtrați oscilațiile unui buton
  • Să respectați limitele de curent pe pin, pe grup și totale ale ATmega328P

2Porturile de intrare-ieșire și portul digital10 min

Porturile de intrare și ieșire (I/O, de la input/output) sunt interfețele hardware prin care microcontrolerul comunică cu perifericele externe. Un port nu conține prelucrare de semnal propriu-zisă - e locul unde o valoare logică din memorie devine tensiune pe un fir, sau invers.

Un pin e considerat de I/O dacă sensul de transfer poate fi schimbat prin program, fără intervenție asupra circuitului fizic - trăsătura care îl deosebește de un pin cu funcție fixă (alimentare, reset). Pinii nu sunt tratați individual, ci grupați, de regulă câte opt, formând un port: opt biți înseamnă exact lățimea unui registru pe o mașină pe 8 biți, deci întregul port se citește sau se scrie printr-o singură instrucțiune. Pe ATmega328P există trei porturi - B, C, D - dar numărul de pini din foaia de catalog și numărul efectiv utilizabil pe o placă concretă nu coincid: portul B are doi pini ocupați de cuarțul de 16 MHz, portul C are ultimul pin ocupat de intrarea de reset.

Pragurile logice

Portul digital clasifică orice tensiune aplicată în una din două stări. Pentru un AVR alimentat la 5 V: orice tensiune sub 0,3·VCC (~1,5 V) e citită sigur ca 0 logic; orice tensiune peste 0,6·VCC (~3 V) e citită sigur ca 1 logic. Între cele două praguri rămâne o bandă interzisă, pentru care nimic nu e garantat - rezultatul poate diferi de la exemplar la exemplar sau de la o citire la alta.

Nivelurile logice nu se transferă între sisteme alimentate diferit

Un microcontroler la 3,3 V care emite 1 logic (3,3 V) e, pentru un AVR la 5 V, peste pragul de 3 V - citirea funcționează. Invers, un AVR care emite 5 V pe intrarea unui circuit la 3,3 V îi aplică o supratensiune care îl poate distruge. Interfațarea între domenii de tensiune diferite cere divizoare rezistive sau translatoare de nivel dedicate.

Logică pozitivă și logică negativă Corespondența dintre nivelul de tensiune și semnificația logică e o alegere de proiectare, nu o lege a naturii. Logica negativă (activ = tensiune joasă) apare des tocmai pentru că montajul cu pull-up produce în mod natural 1 logic în repaus și 0 logic la apăsarea butonului. Confuzia dintre cele două convenții e una dintre cele mai frecvente cauze de comportament inversat în programele de început.

3Arhitectura unui port: structura pinului și cele trei registre10 min

Comunicarea e bidirecțională, iar bidirecționalitatea trebuie construită în hardware. Fiecare pin conține un buffer de ieșire (impune tensiune), un buffer de intrare (citește tensiunea fără s-o modifice) și o linie de activare (decide care buffer e conectat efectiv) - comandată de un bit dintr-un registru de configurare. Când bufferul de ieșire e dezactivat, pinul trece în înaltă impedanță (HiZ), aproape ca un fir întrerupt.

Cele cinci blocuri ale unui pin

interiorul microcontroleruluibit DDRxbit PORTxbit PINxetaj iesirecontratimptrigger Schmitt+ sincronizatorpull-upPINVCCGNDexterior
Structura interna a unui pin de port. Cele trei bistabile din stanga sunt bitii din DDRx, PORTx si PINx; in mijloc, etajul de iesire in contratimp si lantul de intrare; in dreapta, rezistorul de ridicare comutabil si diodele de protectie catre alimentare si masa.

Bistabilele de configurare (direcție + valoare de ieșire, memorie statică). Etajul de ieșire în contratimp (push-pull): două tranzistoare complementare, niciodată conducând simultan - sus dă curent (source), jos absoarbe curent (sink). Rezistența de pull-up comutabilă (20-50 kΩ la AVR). Diodele de protecție (spre VCC și spre masă, blocate în funcționare normală). Lanțul de intrare (trigger Schmitt + sincronizator, discutat separat).

De ce cele două tranzistoare nu conduc niciodată simultan

Ar însemna un scurtcircuit direct între alimentare și masă prin interiorul cipului. Logica de control a etajului de ieșire garantează exclusivitatea celor două stări - o defecțiune a acestei logici e una din puținele căi prin care un cip AVR se poate autodistruge electric.

Cele trei registre ale unui port

Pentru portul B: DDRB, PORTB, PINB (analog pentru C, D).

DDRx, PORTx, PINx
DDRx (Data Direction Register) - direcția: 0=intrare, 1=ieșire. După reset, toți biții sunt 0 (toți pinii pornesc ca intrări - alegerea sigură, o intrare nu poate deteriora nimic).
PORTx - dublu rol: pentru un pin ieșire, valoarea impusă pe pin; pentru un pin intrare, activează (1) sau dezactivează (0) rezistența internă de pull-up.
PINx - singurul care spune adevărul despre starea fizică a pinului, indiferent de ce a scris programul în PORTx. Nu e memorie obișnuită, ci fereastra spre bistabilul de la capătul lanțului de sincronizare - scrierea unui 1 într-un bit din PINx basculează bitul corespunzător din PORTx.
Eroarea clasică a începătorului: citirea din PORTx în loc de PINx

Un pin de intrare cu pull-up activat are în PORTx valoarea 1, dar poate avea în PINx valoarea 0, dacă butonul e apăsat. A citi PORTx pentru a afla starea unui buton face programul să raporteze imperturbabil 1, pentru că asta a scris el acolo - starea reală de pe pin nu ajunge niciodată la test. Regula practică, în trei cuvinte: DDRx pentru direcție, PORTx pentru ce vrem noi, PINx pentru ce este în realitate.

4Configurarea porturilor: prin registre și prin Arduino12 min

Configurarea direcției e primul lucru care se face într-un program de microcontroler, înainte de bucla principală - de ea depinde tot restul, inclusiv integritatea electrică a montajului (o direcție greșită poate pune față în față două surse de tensiune).

DDRxnPORTxnRegimComportament electric
00Intrare, înaltă impedanțăpinul lăsat în aer, nivel nedefinit
01Intrare cu pull-uprezistența trage spre VCC; exteriorul poate coborî la masă
10Ieșire pe 0 logicpin legat la masă, poate absorbi curent
11Ieșire pe 1 logicpin legat la VCC, poate furniza curent
Bitul global PUD din MCUCR

Când e setat, dezactivează simultan toate rezistențele de pull-up ale tuturor porturilor, indiferent de conținutul registrelor PORTx - util pentru consum minim, dar sursă serioasă de confuzie dacă rămâne setat din greșeală: montajele cu butoane par brusc să nu mai funcționeze, deși codul de inițializare pare corect.

Configurare și citire prin registre
#include <avr/io.h>

int main(void)
{
    DDRB |= (1 << PB5);             /* PB5: LED, iesire */
    DDRD &= ~(1 << PD2);            /* PD2: buton, intrare */
    PORTD |= (1 << PD2);            /* pull-up intern activat */

    while (1) {
        if ((PIND & (1 << PD2)) == 0) {   /* apasat = leaga la masa */
            PORTB |= (1 << PB5);
        } else {
            PORTB &= ~(1 << PB5);
        }
    }
}
De ce testul se face pe PIND, nu pe PORTD, și nu cu ==

PIND & (1<<PD2) izolează bitul dorit și dă fie zero, fie o valoare nenulă. Scrierea PIND == 0 ar cere ca toți cei opt pini ai portului să fie simultan pe zero - o greșeală frecventă care face condiția aproape mereu falsă.

Configurarea prin funcțiile Arduino

const int LED = 13, BUTON = 2;
void setup() {
    pinMode(LED, OUTPUT);
    pinMode(BUTON, INPUT_PULLUP);
}
void loop() {
    digitalWrite(LED, digitalRead(BUTON) == LOW ? HIGH : LOW);
}

INPUT_PULLUP face, într-un singur apel, exact ce făceau cele două linii cu DDRx și PORTx. PORTB |= (1<<PB5) se compilează într-o singură instrucțiune, un ciclu. digitalWrite traduce numărul de pin în port+bit prin două tabele din Flash, verifică și oprește un eventual canal PWM activ, dezactivează și reactivează întreruperile - zeci de cicluri. Pentru un LED comandat de buton, diferența e irelevantă; pentru un front precis sau o întrerupere care trebuie să se termine repede, devine hotărâtoare.

Potriviți regimul cu combinația de biți
Configurarea sigură a unui pin de ieșire care comandă un releu

5Transferul de date: eșantionarea semnalului9 min

Tensiunea aplicată pe pin nu ajunge instantaneu la program - drumul e tăiat în felii de ceasul sistemului. Un bistabil de tip latch, comandat de ceas, reține valoarea de pe pin o singură dată pe ciclu, la un front bine precizat. Consecința: starea pinului nu e citită continuu, ci eșantionată - programul vede ultima fotografie făcută pinului.

Întârzierea de eșantionare La AVR, întârzierea între schimbarea fizică a pinului și disponibilitatea noii valori în PINx e între jumătate și un ciclu și jumătate de ceas, în funcție de momentul schimbării față de front. La 16 MHz (62,5 ns/ciclu), întârzierea e de ordinul zecilor de nanosecunde - neglijabilă pentru butoane, deloc neglijabilă pentru un protocol sincron rapid.
Impulsurile mai scurte decât un ciclu de ceas pot fi pierdute complet

Dacă semnalul urcă și coboară între două momente de eșantionare, bistabilul nu are cum să afle că s-a întâmplat ceva - la ambele eșantionări valoarea era aceeași. Din acest motiv, impulsurile foarte scurte nu se detectează prin citirea repetată a lui PINx în buclă, ci prin mecanisme hardware dedicate: întreruperi externe pe front (Cursul 05) sau captură pe temporizator.

Exercițiu rezolvat - poate fi citit un impuls de 200 ns prin interogare?

Un encoder incremental produce impulsuri de 200 ns la turația maximă. Poate fi citit prin interogarea lui PINx într-o buclă, pe un ATmega328P la 16 MHz?

Vezi rezolvarea

Un ciclu de ceas: 1/16 MHz = 62,5 ns, deci impulsul acoperă ~3 cicluri - eșantionarea propriu-zisă l-ar putea prinde.

Problema e bucla de program: o iterație care citește PINx, maschează bitul, compară și face un salt condiționat consumă cel puțin 5-6 cicluri, adică peste 350 ns - mai mult decât durata impulsului. Există deci iterații în care impulsul se naște și moare între două citiri consecutive și se pierde.

Soluția corectă: o întrerupere externă pe front, care nu depinde de momentul în care programul apucă să citească.

6Metastabilitatea9 min

Metastabilitatea e o stare instabilă în care ieșirea unui bistabil se află într-o zonă de tranziție între cele două niveluri logice, fără a fi nici 0, nici 1, pentru o durată imprevizibilă. Se produce atunci când semnalul de intrare se schimbă chiar în momentul eșantionării.

Mecanismul intern
Un bistabil își păstrează valoarea printr-o buclă de reacție pozitivă - două inversoare legate în cerc. Bucla are două stări stabile, dar și o a treia, de echilibru instabil, în care ambele inversoare se alimentează reciproc cu aceeași tensiune intermediară - ca o bilă așezată exact în vârful unui deal: în principiu poate sta acolo, în practică va cădea, dar nu se știe dinainte nici încotro, nici după cât timp.

Bistabilul ajunge acolo dacă, la frontul de ceas, tensiunea de intrare nu e destul de departe de pragul de comutare - condiția e exprimată de foile de catalog prin timpul de stabilizare (setup time) și timpul de menținere (hold time) din jurul frontului.

Metastabilitatea nu se elimină, se face improbabilă Ieșirea din starea metastabilă e exponențială: probabilitatea de a fi încă nedecis scade exponențial cu timpul scurs de la front. Nu există un timp după care ieșirea e garantată matematic, dar există un timp după care probabilitatea devine practic nulă pe durata de viață a echipamentului - observație care stă la baza tuturor soluțiilor practice.

Cauzele: lipsa de corelație între semnalul extern și ceasul intern (un buton apăsat de un om nu respectă nicio regulă de sincronizare cu ceasul de 16 MHz) și fronturile lente (un semnal care parcurge un cablu lung petrece mult timp în zona intermediară, mărind direct probabilitatea de eșantionare acolo).

Triggerul Schmitt curăță fronturile, dar nu rezolvă metastabilitatea

Un comparator obișnuit are un singur prag - dacă semnalul traversează lent, purtând puțin zgomot, ieșirea oscilează de mai multe ori. Triggerul Schmitt are două praguri (V_hi, V_lo); diferența dintre ele, histerezisul, e o măsură a imunității la zgomot. Rezultatul: indiferent cât de lent urcă tensiunea, ieșirea triggerului face o singură tranziție, curată. Dar un front perfect abrupt care cade exact în fereastra setup-hold produce metastabilitate la fel de bine ca unul lent - pentru momentul frontului e nevoie de altceva (secțiunea următoare).

7Circuitul sincronizator8 min

Soluția pentru caracterul asincron al semnalelor externe e sincronizatorul: nu elimină metastabilitatea, ci îi acordă timp să se stingă înainte ca valoarea să ajungă la program. Se pun două bistabile în serie, comandate de același ceas, iar valoarea folosită mai departe e cea de la ieșirea celui de-al doilea.

De ce funcționează Primul bistabil eșantionează un semnal asincron și poate intra în metastabilitate. Ieșirea lui nu merge direct spre program, ci spre al doilea bistabil, care o eșantionează abia la ciclul următor. În acest interval de un ciclu întreg, primul bistabil are timp să se hotărască - probabilitatea de a fi încă nedecis după un ciclu complet e exponențial mică, deci al doilea bistabil eșantionează, practic întotdeauna, un semnal deja curat.

Ce nu garantează sincronizatorul e care valoare va fi propagată dacă schimbarea a picat exact pe front - veche sau nouă, ceea ce înseamnă doar că tranziția a fost văzută cu un ciclu mai devreme sau mai târziu, aproape întotdeauna acceptabil. Ce garantează e că programul nu va vedea niciodată o valoare care nu e nici 0, nici 1.

Întârzierea totală la intrare: d_in = d_latch + d_sinc, unde d_sinc e numărul de cicluri de propagare prin sincronizator. Cu cât acesta are mai multe etaje, cu atât scade probabilitatea de eroare, dar crește d_sinc - două etaje sunt compromisul obișnuit pentru microcontrolerele uzuale; sistemele foarte rapide sau critice pentru siguranță pot folosi trei sau mai multe.

Sincronizatorul se aplică semnalului, nu magistralei

Dacă același semnal asincron trebuie folosit în două locuri diferite din circuit, el trebuie sincronizat o singură dată, iar rezultatul distribuit. Două sincronizatoare paralele pe același semnal pot da, în cazul nefericit, rezultate diferite - circuitul ajunge într-o stare inconsistentă, cu cele două jumătăți „de acord" cu momente diferite ale aceleiași tranziții.

8Rezistențele de pull-up și de pull-down10 min

O intrare digitală neconectată la nicio sursă de semnal definită se află în înaltă impedanță (HiZ) - contraintuitiv pentru un începător, pentru care „un fir nelegat e la zero". Nu este: intrarea CMOS are o rezistență de ordinul sutelor de megaohmi, iar potențialul unui pin lăsat în aer e stabilit de orice altceva din jur (cuplaj capacitiv, rețeaua de 50 Hz, sarcina electrostatică a unei mâini apropiate) - citirile par aleatorii.

Un al doilea inconvenient: curentul din zona intermediară

Când tensiunea pe pin staționează în zona intermediară, ambele tranzistoare din etajul de intrare conduc parțial, și prin ele circulă un curent fără niciun rol util. Câțiva pini lăsați în aer pot dubla consumul în repaus al unei aplicații alimentate de la baterie. Recomandarea generală: niciun pin să nu rămână flotant.

Rezolvarea e o rezistență de pull-up (între linie și VCC, fixează repausul la 1 logic) sau de pull-down (între linie și masă, fixează repausul la 0 logic). Montajul cu pull-up și buton la masă e cel mai comun, producând logica negativă: repaus = 1, apăsat = 0 - preferat pentru că AVR-ul are pull-up intern, dar nu pull-down intern, iar traseul de masă e de obicei mai ușor de distribuit pe placă decât cel de alimentare.

Exercițiu rezolvat - curentul printr-un pull-up

Un buton e legat printr-un pull-up de 10 kΩ la 5 V. Ce curent circulă cu butonul apăsat, și ce consumă montajul dacă e ținut apăsat permanent?

Vezi rezolvarea

Cu butonul apăsat, rezistența e conectată direct între 5 V și masă: I = 5V/10kΩ = 0,5 mA. Puterea disipată: P = U·I = 5×0,5×10⁻³ = 2,5 mW - nimic pentru o rezistență de 0,25 W.

Dacă în loc de 10 kΩ s-ar folosi 100 Ω, curentul ar deveni 50 mA și puterea 250 mW - risipă inacceptabilă la baterie, cu încălzire vizibilă a rezistenței. Cu pull-up-ul intern al AVR-ului (20-50 kΩ), curentul ar fi între 0,1 și 0,25 mA.

Când pull-up-ul intern nu e suficient Linii lungi sau medii cu perturbații electromagnetice puternice (lângă un motor comandat prin PWM): zeci de kiloohmi lasă linia prea moale. Magistrale cu ieșiri în colector deschis (I2C): pull-up-ul trebuie să încarce linia suficient de rapid pentru timpii de front ai protocolului, valorile interne fiind mult prea mari. Un nivel de repaus necesar înainte ca microcontrolerul să-și execute inițializarea, sau chiar cu microcontrolerul în reset (semnalul de validare al unui driver de motor). Pull-down-ul e întotdeauna extern pe AVR, care nu are rezistențe interne de acest tip.

9Pinii cu funcții multiple7 min

Numărul de picioare ale unei capsule e limitat, în timp ce numărul de periferice pe un cip crește continuu - rezolvarea e multiplexarea funcțiilor: același pin poate fi folosit, în momente diferite, de periferice diferite. În modul obișnuit, ca pin digital simplu, se numește GPIO (general purpose input/output).

PinFuncție alternativăEfect asupra GPIO
PD0, PD1RXD, TXD (UART)preluați de modulul serial; legați și la USB pe Arduino Uno
PB2, PB5SS, MOSI, MISO, SCK (SPI)activarea SPI preia pinii; SCK e și pinul LED-ului de pe placă
PC4, PC5SDA, SCL (I2C)preluați de TWI, cu pull-up extern obligatoriu
PD2, PD3INT0, INT1rămân citibili, dar generează întreruperi la front dacă sunt activate

Configurarea acestor funcții nu se face din registrele portului, ci din SFR-urile perifericului respectiv (ex. UCSR0B pentru UART, SPCR pentru SPI). Cât timp o funcție alternativă e activă, pinul nu mai poate funcționa ca GPIO - scrierile în PORTx nu mai au efect, citirile din PINx pot să nu mai reflecte ce se așteaptă.

Conflictele clasice pe Arduino Uno

Pinii 0 și 1 (RXD/TXD): orice apel la Serial.begin confiscă acești doi pini - dacă la ei mai e legat ceva din montaj, comunicația cu calculatorul și montajul se deranjează reciproc. Funcțiile tone și analogWrite pot folosi același temporizator; biblioteca Servo preia temporizatorul 1 și dezactivează astfel PWM-ul de pe pinii 9 și 10.

Regula de lucru Înainte de a atribui o funcție unui pin, se verifică în tabelul de funcții alternative al microcontrolerului ce alte periferice îl folosesc, iar planificarea alocării pinilor se face la începutul proiectului, nu pe măsură ce se adaugă module. Sursa cea mai frecventă de erori greu de diagnosticat e exact aceasta: programul pare corect, iar pinul nu răspunde.

10Protecția pinilor digitali12 min

Pinii sunt puncte de contact între o structură de siliciu de câțiva nanometri și o lume exterioară plină de tensiuni parazite. Producătorii prevăd protecții interne, dar cu limite bine definite - depășirea lor distruge cipul.

Protecțiile interne

ESD (descărcări electrostatice): diodele de la fiecare pin spre VCC și masă deviază impulsul - protecție pentru evenimente scurte și rare, nu pentru supratensiune permanentă. Supratensiune: aceleași diode, în regim de clamping - funcționează doar dacă prin diodă circulă un curent mic (miliamperi); depășirea distruge dioda și poate ridica întreaga alimentare a cipului.

AVR-urile clasice nu au protecție la supracurent

Un scurtcircuit între un pin de ieșire pe 1 și masă produce un curent limitat doar de rezistența internă a tranzistorului - zeci de miliamperi. Rezultatul tipic nu e distrugerea imediată, ci degradarea progresivă a etajului: pinul comandă „mai slab", apoi rămâne blocat pe o valoare, iar în cele din urmă întreaga alimentare a cipului poate fi afectată.

Curentul maxim - trei limite simultane

LimităValoare (ATmega328P)Observație
pe pin40 mA absolut, ~20 mA recomandatvaloare de distrugere, nu de proiectare
pe grup de pini100 mAnu se pot aprinde opt LED-uri la 20 mA fiecare pe același grup
totală200 mAinclude nucleul, perifericele și tot ce trece prin ieșiri
Regula de proiectare Microcontrolerul nu e sursă de putere - e un element de comandă. Tot ce are nevoie de mai mult de câțiva miliamperi (relee, motoare, benzi de LED-uri, electrovalve) se comandă printr-un element intermediar: tranzistor, driver integrat, releu sau optocuplor.
Exercițiu rezolvat - rezistența de limitare pentru un LED

Un LED roșu (V_F = 2 V) trebuie comandat de la un pin la 5 V, la 10 mA. Calculați rezistența de limitare, puterea disipată și numărul maxim de asemenea LED-uri pe un grup de pini.

Vezi rezolvarea

Tensiunea de cădere pe rezistență: 5 - 2 = 3 V. R = 3V/10mA = 300 Ω. Valoarea standard imediat superioară (seria E12): 330 Ω, care dă 3/330 ≈ 9 mA.

Putere disipată: P = 3×9×10⁻³ ≈ 27 mW - o rezistență de 0,25 W e mult mai mult decât suficientă.

Pentru numărul de LED-uri: limita de grup e 100 mA; la 9 mA/LED rezultă 100/9 ≈ 11, dar acest calcul consumă toată rezerva grupului. O proiectare prudentă se oprește la jumătate - cinci sau șase LED-uri simultan pe grup. Dacă în loc de 330 Ω s-ar monta 100 Ω, curentul ar deveni 30 mA (sub maximul absolut de 40 mA) - LED-ul ar funcționa, dar pinul ar lucra permanent în zona nerecomandată, iar trei asemenea LED-uri ar depăși deja limita de grup.

Dimensionarea rezistorului serie și verificarea limitelor pinului

11Circuitele conexe: butoane, relee, LED-uri, optocuploare10 min

Porturile se conectează rareori direct la ceea ce trebuie citit sau comandat - între ele se interpun circuite care adaptează niveluri, izolează, filtrează sau amplifică.

Butoane și comutatoare: oscilația de contact

Contactele metalice nu se lipesc instantaneu - la închidere ricoșează elastic, ating și se despart de mai multe ori înainte de a rămâne în contact ferm (bouncing). Pentru un microcontroler care citește pinul de un milion de ori pe secundă, o singură apăsare devine o rafală de zeci de tranziții.

Filtrare hardware sau software Hardware: un filtru RC (R=10 kΩ, C=100 nF dau τ=1 ms) - funcționează mai bine cu trigger Schmitt la intrare, prezent oricum pe AVR. Software (soluția preferată, nu costă nimic în componente): după fiecare tranziție observată, se repornește un cronometru; starea e declarată stabilă numai după ce a rămas neschimbată un interval întreg (tipic 20-30 ms) - astfel rafala de oscilații, oricât de lungă, e tratată ca un singur eveniment.
if (citire != stareAnterioara) ultimaSchimbare = millis();
if ((millis() - ultimaSchimbare) > INTERVAL) {
    if (citire != stareStabila) {
        stareStabila = citire;
        /* aici se trateaza apasarea, o singura data */
    }
}
stareAnterioara = citire;

Relee

Un releu nu se comandă niciodată direct de la un pin: bobina consumă 30-100 mA (peste maximul absolut al unui pin), iar la întreruperea curentului, energia stocată în câmpul magnetic produce un vârf de tensiune inversă de sute de volți.

Dioda de recuperare (flyback) nu e opțională

Montajul corect folosește un tranzistor de comutație și o diodă de recuperare în paralel cu bobina, catodul spre plus. La întreruperea curentului, dioda intră în conducție și oferă un drum închis prin care curentul din bobină se stinge, limitând vârful de tensiune la o cădere de diodă. Omiterea ei e una din cele mai frecvente cauze de distrugere a montajelor cu sarcini inductive - iar efectul nu apare neapărat imediat, ci după un număr de comutări.

LED-uri, afișoare multiplexate, optocuploare

Legarea mai multor LED-uri în paralel pe aceeași rezistență e o eroare: LED-urile nu au exact aceeași V_F, cel cu V_F mai mic preia disproporționat din curent, se încălzește, îi scade și mai mult V_F - proces care duce la distrugerea lui. Fiecare LED cere rezistență proprie.

La afișoare cu mai multe cifre, segmentele omoloage sunt legate împreună, catozii comuni comandați individual - programul ciclează suficient de repede (peste ~50 Hz/cifră) încât persistența retiniană să vadă toate cifrele aprinse simultan. Prețul: luminozitatea medie scade proporțional cu numărul de cifre, compensat prin creșterea curentului instantaneu peste valoarea continuă admisă.

Optocuplorul (LED + fototranzistor izolate optic) se folosește pentru izolare galvanică - protejează microcontrolerul de tensiuni periculoase din partea de putere și rupe buclele de masă. Pe partea de intrare se tratează ca un LED obișnuit; pe partea de ieșire, fototranzistorul se comportă ca un comutator spre masă, folosit natural cu un pull-up, la fel ca un buton.

Ce reține proiectantul Toate aceste circuite răspund acelorași întrebări: cine impune nivelul liniei când nu-l impune nimeni altcineva (pull-up); de unde vine curentul necesar sarcinii (element intermediar de putere); ce se întâmplă cu energia unei sarcini inductive la deconectare (diodă de recuperare); cât durează evenimentul de detectat față de perioada de eșantionare (întrerupere, nu interogare). Un pin de microcontroler nu e nici sursă de putere, nici izolator, nici filtru - tot ce depășește rolul lui de element logic trebuie construit în jurul lui.

12Erori frecvente4 min

  • „Citesc starea unui buton din PORTD, e mai simplu." Fals - PORTD conține ce a scris programul (comanda sau bitul de pull-up), nu starea reală de pe pin. Programul va raporta imperturbabil ce a scris el acolo, indiferent ce face butonul. Orice citire a unei intrări se face din PINx, niciodată din PORTx.
  • „Un pin nefolosit, lăsat nelegat, nu deranjează cu nimic." Fals - un pin flotant are un potențial nedefinit, stabilit de zgomotul din jur, cu citiri aparent aleatorii și consum suplimentar prin conducția parțială a ambelor tranzistoare de intrare. Configurați explicit orice pin nefolosit ca intrare cu pull-up, sau ca ieșire pe o valoare fixă.
  • „Un releu se comandă direct de la un pin, ca un LED." Fals de două ori - bobina depășește curentul maxim pe pin, iar la întrerupere generează un vârf de tensiune inversă de sute de volți, care poate distruge tranzistorul de comandă și ajunge, prin diodele de protecție, la alimentarea microcontrolerului. Folosiți întotdeauna un tranzistor de comutație plus o diodă de recuperare în paralel cu bobina.

13Rezumat și glosar5 min

Un port grupează opt pini pentru a permite accesul printr-o singură instrucțiune. Fiecare pin are trei registre - DDRx pentru direcție, PORTx pentru comandă (sau pull-up, pe intrare), PINx pentru starea reală - și le distinge un rol logic independent: nu se pot contopi în unul singur fără a pierde informație. Semnalul de intrare e eșantionat, nu citit continuu, ceea ce introduce o mică întârziere și poate pierde impulsuri mai scurte decât un ciclu de ceas. Eșantionarea unui semnal asincron chiar pe front poate produce metastabilitate - rezolvată nu prin eliminare, ci prin sincronizator cu două etaje, care o face improbabilă. Un pin flotant e nedefinit, nu zero; o rezistență de pull-up sau pull-down îi dă o stare de repaus. Multiplexarea funcțiilor confiscă un pin de la rolul de GPIO cât timp perifericul asociat e activ. Limitele de curent - pe pin, pe grup, totale - nu sunt negociabile, iar orice sarcină care depășește câțiva miliamperi cere un element intermediar de putere.

GPIO
pin cu scop general, în opoziție cu o funcție periferică alternativă.
HiZ
înaltă impedanță - starea unui pin ai cărui bufere de ieșire sunt dezactivate.
Metastabilitate
stare instabilă a unui bistabil, între cele două niveluri logice, cu durată imprevizibilă.
Trigger Schmitt
comparator cu histerezis, care curăță un front lent sau zgomotos.
Bouncing
oscilația de contact a unui buton mecanic la închidere sau deschidere.
Diodă de recuperare
diodă de flyback montată în paralel cu o sarcină inductivă, pentru limitarea vârfului de tensiune la deconectare.

14Întrebări de verificare7 min

  1. Explicați de ce un port AVR are nevoie de trei registre distincte și descrieți o situație în care valoarea din PORTx diferă de cea citită din PINx pentru același pin.
  2. Un pin are DDRD bitul 4 pe 0 și PORTD bitul 4 pe 1. În ce regim se află, ce nivel se citește în repaus, și ce se întâmplă dacă un contact exterior îl leagă la masă?
  3. De ce citirea unui pin e întârziată față de schimbarea fizică a tensiunii, și cât durează această întârziere pe un ATmega328P la 16 MHz?
  4. Ce e metastabilitatea, prin ce mecanism intern se explică, și de ce nu poate fi eliminată complet, doar făcută improbabilă?
  5. Comparați rolul triggerului Schmitt cu rolul sincronizatorului cu două etaje - care cauză a metastabilității rezolvă fiecare?
  6. Enumerați trei situații în care pull-up-ul intern al AVR-ului nu e suficient și explicați de ce, pentru fiecare.
  7. Un LED verde (V_F=2,1 V) trebuie alimentat la 12 mA de la un pin la 5 V. Calculați rezistența de limitare, alegeți valoarea standard și determinați puterea disipată.

15Direcții de aprofundare2 min

Cursul următor trece de la interogarea manuală a unui pin la mecanismul hardware care rezolvă exact problema impulsurilor scurte ratate: sistemul de întreruperi - vectori, priorități, latență și capcanele scrierii unei rutine de tratare corecte.

Registrele, exemplele de configurare și montajele din acest curs devin montaj real în Laboratorul 02.