CURSUL 02

Arhitectura unui Microcontroler

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

Cursul trecut a privit microcontrolerul din afară. Acum îl deschidem. Răspundem la o întrebare care pare simplă, dar nu este: ce se întâmplă, fizic și logic, între momentul în care scriem o linie de cod și momentul în care un LED se aprinde. Parcurgem patru straturi - reprezentarea informației (biți, octeți, hexazecimal), memoria (registre, SRAM, Flash, EEPROM), unitatea centrală (ALU, registrul de stare, stiva) și ceasul - folosind, ca de fiecare dată, cifrele concrete ale ATmega328P.

1Obiectul și structura cursului6 min

Răspunsul trece prin patru straturi. Primul e reprezentarea informației - modul în care o mărime din lumea reală devine un șir de zerouri și de unu. Al doilea e memoria - locul în care acele șiruri stau și așteaptă. Al treilea e unitatea centrală de procesare - mașina care le citește, le transformă și le scrie înapoi. Al patrulea e ceasul - semnalul periodic care dă tuturor acestor operații ritmul lor.

De ce merită înțelese temeinic aceste patru straturi Un inginer care le înțelege poate citi orice foaie de catalog și poate depana orice montaj; unul care nu le înțelege rămâne prizonierul funcțiilor gata făcute din biblioteci și se blochează la prima problemă care nu seamănă cu exemplele.
Recapitulare din Cursul 01
  • Un microcontroler încorporează procesor, memorie și periferice pe același siliciu
  • ATmega328P: arhitectură AVR, 32 KB Flash, 2 KB SRAM, 1 KB EEPROM, 16 MHz
Astăzi deschidem fiecare dintre aceste cifre și vedem exact ce înseamnă.

Rezultate ale învățării

  • Să convertiți o valoare între binar, zecimal și hexazecimal, și să identificați biții activi
  • Să distingeți registrele de control de cele de stare, și să comandați un pin prin registre
  • Să comparați SRAM, Flash și EEPROM după volatilitate, granularitate și cicluri de scriere
  • Să explicați rolul indicatorilor din SREG și mecanismul depășirii de stivă
  • Să comparați arhitectura von Neumann cu Harvard și să explicați pipeline-ul pe două etaje al AVR
  • Să calculați numărul de instrucțiuni pe secundă și memoria SRAM disponibilă pentru o aplicație

2Bitul, octetul și cele trei scrieri10 min

Un microcontroler nu știe ce e un număr, o literă sau o temperatură. Tot ce știe e că într-un anumit punct al circuitului tensiunea e apropiată de alimentare sau apropiată de masă - această alegere binară e singura informație elementară pe care hardware-ul o poate păstra fără ambiguitate, și poartă numele de bit.

De ce două stări, nu zece Dacă am codifica zece nivele într-un domeniu de 5 V, fiecare nivel ar ocupa o jumătate de volt, iar orice zgomot de comutație ar putea transforma un 6 într-un 7. Cu două stări, 0,4 V înseamnă sigur zero și 4,2 V înseamnă sigur unu; între ele există o zonă largă, interzisă, care absoarbe zgomotul - o marjă esențială pentru un dispozitiv care lucrează lângă un motor sau într-o hală industrială.

Grupul fundamental de opt biți se numește octet (byte) - 2⁸ = 256 valori distincte, suficient pentru alfabetul latin (ASCII) și exact rezoluția uzuală a unui ADC simplu. Multiplii se formează în puteri ale lui doi: 1 KB = 1024 octeți, nu 1000.

Trei scrieri pentru aceeași valoare

BazăAvantajDezavantaj
Binară (0b...)singura în care se vede pinul directlungă, opt caractere per octet
Zecimalăsingura în care putem judeca măriminicio legătură vizibilă cu biții
Hexazecimală (0x...)fiecare cifră acoperă exact 4 biți - trecere mecanică spre binartrebuie memorate cifrele A-F
Exercițiu rezolvat - conversie și identificarea biților activi

Un registru conține valoarea binară 1011 0100. Exprimați-o în zecimal și hexazecimal, și precizați care biți sunt activi.

Vezi rezolvarea

Numerotăm biții de la dreapta la stânga, începând cu 0: bitul 7=1, 6=0, 5=1, 4=1, 3=0, 2=1, 1=0, 0=0.

Zecimal: 2⁷+2⁵+2⁴+2² = 128+32+16+4 = 180

Hexazecimal: împărțim în două grupe de 4 biți - 1011 = 8+2+1 = 11 = cifra B; 0100 = 4. Rezultă 0xB4. Verificare: 11×16+4 = 180. ✓

Biții activi sunt 7, 5, 4 și 2. Dacă acest octet ar fi fost scris într-un registru de direcție a unui port, cei patru pini corespunzători ar deveni ieșiri, ceilalți patru ar rămâne intrări.

MSB și LSB
Bitul 0 e cel mai puțin semnificativ (LSB - schimbarea lui modifică valoarea cu o unitate). Bitul 7 e cel mai semnificativ (MSB - schimbarea lui modifică valoarea cu 128). În foile de catalog, bitul 7 se desenează în stânga, bitul 0 în dreapta - la fel ca la scrierea unui număr zecimal.
Lucrul pe biți e limbajul natural al microcontrolerului Un procesor de calculator manipulează structuri de date complexe și lasă hardware-ul în seama sistemului de operare; un microcontroler manipulează pini, iar un pin nu are decât două stări, deci un bit. Aprinderea unui LED, citirea unui buton, pornirea unui numărător - operația de fond e mereu aceeași: schimbăm un singur bit dintr-un octet aflat la o adresă cunoscută.

3Registrele și registrele cu funcții speciale11 min

Un registru e o celulă de memorie de foarte mare viteză, integrată chiar în interiorul unității centrale sau al unui modul periferic, la care procesorul are acces imediat - construit din bistabile așezate lângă unitatea aritmetică, astfel încât citirea sau scrierea să nu ceară un ciclu de magistrală. Tocmai pentru că sunt scumpi în suprafață de siliciu, registrele sunt puține, în timp ce memoria e ieftină și abundentă.

De ce nu se poate calcula direct între două locații de memorie O operație aritmetică nu se poate face direct între două locații de memorie: valorile trebuie mai întâi aduse în registre, prelucrate acolo, iar rezultatul dus înapoi. Această asimetrie explică de ce un program care mută mereu date între memorie și registre e mult mai lent decât unul care își ține variabilele de lucru în registre cât mai mult timp.

După funcție, registrele se împart în patru familii: de date (operanzi și rezultate), de adresă (pe AVR, perechile X, Y, Z permit parcurgerea unui tablou cu incrementare automată), de control (setări care determină comportamentul unui modul) și de stare (raportează condiții).

Control vs. stare - sursa unei confuzii frecvente la începători

Un registru de control e scris de program și citit de hardware: noi punem o comandă, circuitul o execută. Un registru de stare e scris de hardware și citit de program: circuitul raportează ce s-a întâmplat, noi luăm cunoștință. A încerca să pornim un convertor scriind în registrul lui de stare e la fel de zadarnic ca a încerca să pornim un motor mișcând acul turometrului.

Registrele cu funcții speciale (SFR)

Nu sunt locuri de depozitare, ci interfețe - fiecare e legat prin fire fizice la un circuit intern concret. Pe ATmega328P, fiecare port e deservit de trei registre: DDRx (direcția: 1=ieșire, 0=intrare), PORTx (nivelul de ieșire, sau activarea pull-up-ului pentru intrare) și PINx (citirea stării electrice reale).

DDRB |= (1 << PB5);   /* PB5 devine iesire */
DDRD &= ~(1 << PD2);  /* PD2 devine intrare */
PORTD |= (1 << PD2);  /* activez pull-up-ul intern pe PD2 */

PORTB |= (1 << PB5);  /* aprind LED-ul */
PORTB &= ~(1 << PB5); /* sting LED-ul */
PORTB ^= (1 << PB5);  /* inversez starea LED-ului */

if ((PIND & (1 << PD2)) == 0) {   /* buton apasat = nivel 0 */
    PORTB |= (1 << PB5);
}

(1 « PB5) construiește o mască: 0b00100000. |= face un SAU bit cu bit - bitul 5 devine 1, restul rămân neatinși. &= cu masca negată prin ~ face un ȘI cu 0b11011111 - bitul 5 devine 0, restul neatinși. ^= face un SAU-EXCLUSIV, care inversează exact bitul acoperit de mască.

De ce nu scriem niciodată PORTB = 0b00100000

Prima formă scrie toți cei opt biți, stingând tot ce era aprins pe ceilalți șapte pini ai portului. Într-un program mic, unde portul B servește un singur LED, greșeala nu se vede. Într-un program în care portul B mai comandă un releu și o linie SPI, efectul apare abia după săptămâni, sub forma unui defect intermitent imposibil de reprodus. Regula: se modifică bitul dorit, nu se rescrie registrul - cu excepția inițializărilor, unde chiar dorim o stare completă.

4Memoria unui microcontroler11 min

Flash - 32 KBvectori intreruperecod aplicatie.textbootloader0x00000x7FFFSRAM - 2 KBregistre + I/O.dataglobale initializate.bssspatiu liberstiva0x01000x08FFEEPROM - 1 KBparametripraguri, calibrarisupravietuiesc opriiscriere lenta (3,3 ms)~100.000 cicluri
Cele trei memorii ale unui ATmega328P, la scara relativa. Stiva creste in jos, dinspre adresa cea mai mare a SRAM, catre variabilele globale care cresc in sus - zona punctata dintre ele este tot ce le desparte.

Memoria se împarte, după destinație, în memorie de program (instrucțiunile, trebuie să reziste la întreruperea alimentării) și memorie de date (variabile, rezultate intermediare, stiva - se modifică permanent, poate fi volatilă).

Memorii volatile

SRAM (static RAM) folosește o celulă din 4-6 tranzistoare, montate ca două inversoare în buclă - bucla se menține singură cât timp există alimentare, deci nu are nevoie de împrospătare și lucrează la viteze mari. Prețul: o celulă SRAM ocupă de câteva ori mai mult siliciu decât una DRAM, motiv pentru care se folosește acolo unde viteza contează și cantitatea e mică - memoria cache a procesoarelor și memoria de date a microcontrolerelor. DRAM folosește un condensator și un tranzistor - celula e mică (ieftină pe bit), dar sarcina se scurge, deci conținutul trebuie împrospătat periodic printr-un controler dedicat; e tipul folosit pentru memoria principală a calculatoarelor.

Memorii nevolatile

TipRescriereUtilizare tipică
MaskedROMimposibilă (mască la fabricație)firmware fixat la volum foarte mare
PROMo singură dată (punți distruse)serii mici, date de identificare
EPROMcu radiație ultravioletăprototipuri, sisteme mai vechi
Flashpe pagini (blocuri), zeci de mii de ciclurimemoria de program a microcontrolerelor
EEPROMpe octet, ~o sută de mii de cicluriparametri de configurație, calibrări
EEPROM-ul nu se scrie într-o buclă

Numărul de cicluri de scriere e limitat (~100.000 pe locație), iar viteza de scriere e mică (ordinul milisecundelor pentru un octet). Un program care salvează o valoare în EEPROM la fiecare trecere prin bucla principală va epuiza celula în câteva ore de funcționare - dacă bucla rulează la câțiva kHz, epuizarea vine în minute, nu în ani.

Memoria Flash e nevolatilă și reprogramabilă electric, dar ștergerea nu se poate face pe locații individuale, ci pe blocuri întregi (pagini) - de aceea se spune că ștergerea e neselectivă. Suportă însă un număr mare de cicluri (ordinul zecilor de mii pentru memoriile de program), motiv pentru care majoritatea microcontrolerelor actuale o folosesc pentru stocarea programului: permite reprogramarea în circuit, deci actualizarea firmware-ului la un produs deja livrat.

5Unitatea centrală: ALU, SREG, stiva12 min

Pipeline pe doua etaje: de ce AVR executa o instructiune pe ciclu

Unitatea centrală de procesare (CPU) aduce instrucțiunile din memorie, le interpretează și le execută, generând semnalele care pun în mișcare restul circuitului. Se împarte în unitatea aritmetică și logică (ALU) și unitatea de control.

ALU și registrele generale

ALU primește la intrare unul sau doi operanzi și un cod de operație, produce un rezultat și un set de indicatori. Operațiile sunt puține și elementare: adunare, scădere, comparație, ȘI, SAU, SAU-EXCLUSIV, negare, deplasări, incrementare, decrementare - tot ce înseamnă calcul complicat se construiește din acestea, prin program.

De ce AVR execută cod C mult mai eficient decât arhitecturile cu acumulator Arhitecturile clasice foloseau un registru privilegiat unic (acumulatorul), care participa obligatoriu la orice calcul. AVR are 32 de registre generale (R0-R31), oricare putând juca rolul de operand sau destinație - compilatorul poate păstra simultan mai multe variabile în registre, fără să le mute înainte și înapoi în memorie. Ultimii șase registre au și funcție dublă: perechile R27:R26, R29:R28, R31:R30 formează registrele de adresă pe 16 biți X, Y, Z, pentru adresare indirectă a memoriei de date (Z poate adresa suplimentar memoria de program, pentru tabele de constante în Flash).

Registrul de stare (SREG)

La fiecare operație aritmetică, ALU actualizează SREG, ale cărui biți se numesc indicatori (flags): Z (zero), C (carry - transport ieșit din bitul cel mai semnificativ), N (negative - copiază bitul de semn), V (depășire cu semn), S (semn corectat, N⊕V), H (transport între nibble-uri), T (bit de uz general), I (validarea globală a întreruperilor - fără el pe 1, nicio întrerupere nu e luată în seamă).

Indicatorii se modifică la aproape fiecare instrucțiune

O instrucțiune de salt condiționat nu se uită la valori, ci la indicatori: comparația scade în gol cei doi operanzi și lasă indicatorii să spună dacă rezultatul a fost nul, negativ sau cu transport. Dacă între o comparație și saltul care depinde de ea se strecoară o altă operație, rezultatul saltului devine imprevizibil - în C nu ne preocupă (se ocupă compilatorul), dar în asamblare e una dintre cele mai frecvente surse de erori, alături de uitarea salvării SREG la intrarea într-o rutină de întrerupere.

Unitatea de control și stiva

Numărătorul de program (PC) conține adresa următoarei instrucțiuni - se incrementează automat după fiecare aducere; salturile și apelurile funcționează scriind o valoare nouă în PC, singurul mecanism de ramificare.

Stiva (stack)
Zonă din memoria de date, regulă ultimul-intrat-primul-ieșit, cu vârful indicat de perechea SPH:SPL. Folosită automat la apelul unei funcții (adresa de întoarcere), pentru variabile locale ce nu încap în registre, și pentru contextul salvat la intrarea într-o întrerupere.
Depășirea de stivă - un defect greu de diagnosticat

Pe AVR, stiva începe la adresa cea mai mare a SRAM și crește în jos; variabilele globale ocupă adresele mici și cresc în sus. Dacă programul are prea multe variabile, apeluri pe prea multe niveluri, sau o recursivitate care nu se oprește, cele două zone se suprapun - stiva scrie peste variabile sau invers. Rezultatul: un microcontroler care se comportă haotic, se resetează singur sau execută cod de la o adresă absurdă, cu simptomul apărând departe de cauza reală.

Ciclul unei instrucțiuni: puneți etapele în ordinea execuției

6Magistrale, von Neumann și Harvard11 min

Unitatea centrală comunică cu memoria și perifericele prin magistrale (bus): de adrese (unidirecțională, determină capacitatea maximă adresabilă - o magistrală de n linii adresează 2ⁿ locații), de date (bidirecțională, lățimea ei dă numele arhitecturii - „pe 8 biți" înseamnă magistrala de date internă de 8 biți) și de control (comenzi de citire/scriere, ceas, întreruperi).

von Neumann vs. Harvard

În von Neumann, o singură memorie comună pentru date și instrucțiuni, o singură magistrală. Execuția cere minimum două etape (aducere+decodificare, apoi execuție), iar cele două accese se îmbulzesc pe același drum - fenomen numit gâtuirea von Neumann. Avantaj: flexibilitate - programul poate să își modifice propriul cod.

În Harvard, spațiile de memorie pentru instrucțiuni și date sunt separate fizic, fiecare cu magistrala lui proprie - aducerea unei instrucțiuni și accesul la o dată pot avea loc simultan.

Trei avantaje care decurg unul din altul Performanța crește (magistralele nu se concurează); lățimea fiecărei magistrale se alege independent (pe AVR: 16 biți pentru program, 8 pentru date); și devine posibilă execuția cvasiparalelă - în timp ce o instrucțiune se execută, următoarea e deja adusă. Din acest motiv, pe AVR majoritatea instrucțiunilor se execută într-un singur ciclu de ceas.

Pipeline și hazarduri

Ideea de a suprapune etapele de execuție se numește pipeline, prin analogie cu o bandă de asamblare - mai multe instrucțiuni sunt simultan în lucru, fiecare într-o altă etapă.

Ciclul 1Ciclul 2Ciclul 3Ciclul 4
Instr. 1ExtrageDecodeazăExecută
Instr. 2ExtrageDecodeazăExecută
Instr. 3ExtrageDecodează

Situațiile care opresc banda se numesc hazarduri: de date (o instrucțiune are nevoie de rezultatul uneia anterioare neterminate), de control (la ramificări, rezultatul condiției nu e cunoscut când instrucțiunea următoare a fost deja extrasă - dacă saltul se face, instrucțiunile aduse degeaba se aruncă) și structural (două instrucțiuni cer aceeași resursă simultan).

Pe AVR, pipeline-ul are doar două etaje

Aducere și execuție. Consecința hazardului de control se vede direct în tabelele de sincronizare din foaia de catalog: o instrucțiune de salt condiționat durează doi cicluri dacă saltul se face, și un singur ciclu dacă nu se face - pentru că în primul caz instrucțiunea deja adusă trebuie aruncată. Un detaliu mărunt, dar el explică de ce durata unei bucle scrise cu grijă nu e perfect constantă.

7Setul de instrucțiuni: RISC față de CISC8 min

Setul de instrucțiuni e mulțimea comenzilor de bază pe care un microcontroler le înțelege - definit în siliciu, prin structura decodificatorului, și constituie granița dintre hardware și software.

ClasăExemple AVREfect
Aritmetice, logiceADD, SUB, AND, EOR, LSLoperează pe doi registre, actualizează SREG
Transfer de dateMOV, LDI, LD, STmută un octet între registre sau memorie
DecizieRJMP, BRNE, RCALL, RETmodifică PC, condiționat sau nu
La nivel de bitSBI, CBI, SBICpun/testează un singur bit, fără a atinge restul octetului

RISC față de CISC

Un procesor RISC recunoaște operații puține și uniforme; operațiile complicate se obțin combinându-le, deci un program RISC e mai lung în număr de instrucțiuni - dar instrucțiunile, simple și de aceeași dimensiune, se decodifică rapid și se execută, în majoritate, într-un singur ciclu. Aceasta face execuția previzibilă, esențial în sistemele de timp real.

Un procesor CISC are un set bogat (peste optzeci de instrucțiuni), multe specializate, diferite ca format și durată - un program CISC e mai scurt, avantaj când memoria era scumpă, dar durata fiecărei instrucțiuni variază și decodificarea e complicată.

De ce AVR alege RISC Familia AVR are 131 de instrucțiuni, aproape toate codificate pe 16 biți și executate într-un singur ciclu - alegerea care explică, mai bine decât orice altceva, raportul favorabil între viteză și consum al acestor circuite.
Potriviți conceptul cu explicația corectă

8Arhitectura ATmega328P10 min

ATmega328P folosește o arhitectură Harvard modificată: spațiile de program și date sunt separate, ca în Harvard, dar există o cale (instrucțiunea LPM, registrul Z) prin care unitatea centrală poate citi constante din memoria de program - fără ea, un tabel de constante ar trebui copiat în SRAM la pornire, consumând inutil o resursă rară.

Trei memorii, cu roluri distincte: Flash de 32 KB (16384 cuvinte de 16 biți, deci PC-ul are exact 14 biți), împărțită în secțiunea de aplicație și secțiunea bootloader (câteva sute de octeți, primește programul nou pe serială); SRAM de 2 KB, cu spațiul de adrese unificat (32 registre generale, apoi 64 registre I/O, apoi 160 registre I/O extinse, abia apoi SRAM propriu-zisă - de aceea PORTB se comportă în C ca o variabilă obișnuită); și EEPROM de 1 KB, cu spațiu de adrese separat, accesată prin trei registre dedicate.

SRAM-ul mic e constrângerea reală, nu Flash-ul Codul compilat pentru AVR e dens - o aplicație de complexitate rezonabilă încape confortabil în 32 KB. Cei 2 KB de SRAM sunt însă epuizați cu o ușurință surprinzătoare: acolo stau simultan toate variabilele globale, toate variabilele locale active, toate bufferele, și stiva. Un singur tablou de 500 de întregi pe 16 biți ocupă 1000 de octeți - jumătate din memorie. Un șir de caractere scris direct în cod e copiat implicit în SRAM la pornire, împreună cu toate celelalte șiruri constante.
Exercițiu rezolvat

Un program păstrează ultimele 300 de măsurători (întregi pe 16 biți) și un buffer serial de 128 octeți. Estimați SRAM-ul liber pe un ATmega328P.

Vezi rezolvarea

Tabloul: 300 × 2 = 600 octeți. Bufferul: 128 octeți. Total: 728 octeți.

Din 2048 disponibili: 2048 - 728 = 1320 octeți rămași - aparent.

Din acești 1320 trebuie scăzute: variabilele globale ale bibliotecilor (pe o placă Arduino cu serial, frecvent peste 200 octeți), șirurile constante copiate în SRAM, și, mai ales, spațiul pentru stivă în cel mai defavorabil lanț de apeluri, inclusiv la intrarea în întreruperi.

Concluzia: marja reală nu e de 1320 de octeți, ci de câteva sute. Dacă cerința ar crește la 800 de măsurători, tabloul singur ar ocupa 1600 de octeți și proiectul nu ar mai încăpea - soluții: reducerea rezoluției la 8 biți unde precizia permite, o medie mobilă în loc de istoricul complet, sau memorie externă.

Simptomul unei SRAM epuizate nu e un mesaj de eroare

Compilatorul nu poate ști cât de adânc se va apela stiva în timpul execuției - simptomul e comportamentul haotic descris la stivă. Obișnuința sănătoasă: verificați mereu, după compilare, raportul de utilizare a memoriei, și tratați o ocupare a SRAM peste ~75% ca pe un semnal de alarmă.

9Circuitul oscilator și ciclul de instrucțiune11 min

Fără semnalul de ceas, microcontrolerul nu e defect, ci îngheață: PC-ul nu mai avansează, instrucțiunile nu mai sunt aduse. Un microcontroler căruia i s-a oprit ceasul consumă foarte puțin - principiul modurilor de economie de energie.

SursăPrecizie tipicăObservații
Oscilator RC interncâteva procentefără componente externe, variază cu tensiunea și temperatura
Rezonator ceramiccâteva părți la mietrei terminale, condensatoare integrate, cost mic
Cristal de cuarțzeci de părți per milionnecesită două condensatoare de sarcină, standard când timpul contează

Un cristal de cuarț oscilează la frecvența lui proprie de rezonanță mecanică (efect piezoelectric), determinată de dimensiuni - nu de tensiune sau temperatură, deci extrem de stabilă. ATmega328P are un oscilator RC intern de 8 MHz, calibrat din fabrică, divizat implicit cu opt (pornește la 1 MHz dacă nu i se spune altceva); sursa de ceas se alege prin biții de configurație permanentă (fuses).

Când contează precizia Un LED cu întârziere de o secundă și o eroare de 3% nu se observă. Un ceas de timp real cu aceeași eroare derivă aproape o oră pe zi. Cazul cel mai sever e comunicația serială asincronă: receptorul UART nu primește niciun semnal de ceas, se sincronizează pe frontul de start și eșantionează cu propriul lui ceas - marja tolerabilă pentru un cadru de zece biți e de ordinul a două procente pentru abaterea totală. Un oscilator RC necalibrat se află exact la limita acestei marje, de aici comunicația care „merge pe masa de laborator și cade în cameră rece". Motivul pentru care Arduino Uno folosește un cristal extern de 16 MHz.
Exercițiu rezolvat - instrucțiuni pe secundă

ATmega328P funcționează cu un cristal de 16 MHz. Estimați numărul de instrucțiuni pe secundă și durata unei instrucțiuni simple.

Vezi rezolvarea

T = 1/(16×10⁶) = 62,5 ns

Majoritatea instrucțiunilor AVR se execută într-un singur ciclu, deci o adunare între doi registre durează 62,5 ns, iar microcontrolerul execută aproximativ 16 milioane de instrucțiuni pe secundă (16 MIPS) - o limită superioară: accesele SRAM cer doi cicluri (125 ns), salturile condiționate unul sau două, înmulțirea hardware doi cicluri.

Consecință practică: o buclă care comută un pin prin instrucțiuni la nivel de bit are nevoie de câteva cicluri pe iterație, deci frecvența maximă generată prin program e de ordinul a câteva sute de kilohertzi. Pentru semnale mai rapide sau mai precise nu se folosește programul, ci modulele hardware de numărare (Cursul 06).

Ceasul, ciclul de instrucțiune și deriva oscilatorului

10Alimentarea microcontrolerului8 min

ATmega328P acceptă un domeniu larg de alimentare, aproximativ 1,8-5,5 V - dar domeniul de tensiune și frecvența maximă sunt legate: tranzistoarele comută mai lent la tensiune mică, deci la 16 MHz circuitul are nevoie de minimum ~4,5 V, iar la 1,8 V frecvența maximă garantată scade la câțiva megahertzi. A alimenta la 3,3 V și a ceasa la 16 MHz e o abatere de la specificație care poate funcționa pe masa de laborator și poate ceda la temperaturi extreme.

De ce condensatoarele de decuplare nu sunt opționale

Un microcontroler nu consumă curent uniform - la fiecare front de ceas, zeci de mii de tranzistoare comută simultan și cer un vârf de curent mult mai mare decât media. Orice conductor are inductanță parazită, iar u = L·di/dt: un vârf de curent foarte scurt înseamnă un di/dt foarte mare, deci o cădere de tensiune apreciabilă chiar pe firele de alimentare.

Condensatorul de decuplare, legat direct între pinii de alimentare și masă, la câțiva milimetri de capsulă, constituie un mic rezervor local care furnizează instantaneu vârful de curent, fără să treacă prin inductanța traseelor. Consecințele lipsei lui sunt greu de diagnosticat, tocmai pentru că sunt intermitente: resetări aparent aleatorii, citiri analogice zgomotoase, comunicație serială cu erori rare, comportament care se schimbă când atingi placa cu mâna.

Regula practică fără excepție: câte un condensator ceramic de 100 nF la fiecare pereche VCC-GND, cât mai aproape posibil de pinii circuitului, plus un electrolitic de ~10 µF la intrarea alimentării pe placă, pentru variațiile mai lente. Pe ATmega328P regula se aplică atât perechii VCC-GND, cât și AVCC-GND (partea analogică); pinul AREF cere și el propriul condensator, pentru că zgomotul de pe tensiunea de referință se regăsește direct în rezultatul conversiei analog-numerice.

Poziționarea contează la fel de mult ca valoarea Un condensator de decuplare așezat la doi centimetri de circuit, pe partea cealaltă a plăcii, își pierde aproape complet eficacitatea - inductanța traseului până la el anulează avantajul.

11Un exemplu de conectare6 min

Ce trebuie legat la un ATmega328P scos din pungă pentru ca el să funcționeze? Răspunsul e surprinzător de scurt: o sursă de alimentare stabilizată și un modul de sincronizare. Restul pinilor deservesc aplicația, nu circuitul.

Montajul minimal: alimentarea de 5 V la VCC/AVCC, masa la GND, condensatoarele de decuplare de 100 nF lângă fiecare pereche; sursa de ceas (cristal de 16 MHz cu două condensatoare de sarcină de ~22 pF, sau nimic dacă se folosește oscilatorul intern); pinul RESET, activ pe nivel coborât, ținut la alimentare printr-o rezistență de pull-up de ~10 kΩ (lăsat în aer, captează zgomot și provoacă resetări aleatorii); și, dacă se folosește ADC-ul, un condensator de decuplare propriu pe AREF.

Programul minimal de verificare a unui montaj nou
int main(void)
{
    DDRB |= (1 << PB5);   /* PB5 configurat ca iesire */
    while (1) {
        PORTB ^= (1 << PB5);           /* inverseaza starea pinului */
        for (volatile long i = 0; i < 200000L; i++) {
            ; /* intarziere aproximativa, prin bucla goala */
        }
    }
    return 0;
}

Dacă LED-ul clipește, alimentarea e bună, ceasul oscilează, resetarea nu se activează singură și programul a ajuns în memorie. Dacă LED-ul stă aprins fix, cel mai probabil microcontrolerul e blocat în resetare. Dacă nu se întâmplă nimic, problema e la alimentare sau la ceas. Dacă LED-ul clipește mai rar sau mai des decât se aștepta, ceasul funcționează la altă frecvență decât cea presupusă - fuse-urile nu sunt configurate pentru sursa de ceas dorită.

De ce contorul e declarat volatile

Fără volatile, compilatorul constată că bucla nu produce niciun efect vizibil și o elimină complet la optimizare - întârzierea dispare. Cuvântul volatile interzice această optimizare, obligându-l să citească și să scrie efectiv variabila la fiecare iterație. Aceeași problemă apare la orice variabilă modificată într-o rutină de întrerupere și citită în programul principal (Cursul 05).

12Erori frecvente4 min

  • „PORTB = 0b00100000; e echivalent cu PORTB |= (1 << PB5);, doar mai clar." Fals - prima formă rescrie toți cei opt biți, stingând orice altceva era aprins pe port. Efectul apare abia după săptămâni, când portul mai comandă și alte periferice. Modificați întotdeauna doar bitul dorit (|=, &=~, ^=), cu excepția inițializărilor complete.
  • „32 KB de Flash sunt limita reală a unei aplicații AVR." Aproape întotdeauna nu - codul compilat e dens și încape confortabil în Flash. Constrângerea reală sunt cei 2 KB de SRAM, epuizați rapid de tablouri, buffere și stivă. Verificați raportul de utilizare a SRAM după fiecare compilare, nu doar Flash-ul.
  • „Fără condensator de decuplare, montajul merge oricum - l-am testat pe masă." Funcționarea pe masa de laborator nu garantează nimic - efectele lipsei decuplării sunt intermitente și apar tipic la temperatură, vibrații sau sarcină electrică diferite. Puneți întotdeauna 100 nF cât mai aproape de fiecare pereche VCC-GND, fără excepție.

13Rezumat și glosar5 min

Informația elementară e bitul; opt biți formează un octet, scris echivalent în binar, zecimal sau hexazecimal - ultima fiind convenția foilor de catalog, pentru corespondența exactă cu grupele de patru biți. Registrele sunt celule de memorie rapide lângă unitatea centrală; registrele cu funcții speciale sunt interfețele prin care programul comandă direct perifericele, cu distincția esențială control (scris de program) / stare (scris de hardware). SRAM e volatilă și rapidă, Flash și EEPROM sunt nevolatile dar cu cicluri de scriere limitate. Unitatea centrală conține ALU (cu registrul de stare SREG) și unitatea de control (cu numărătorul de program și stiva, a cărei depășire produce comportament haotic greu de diagnosticat). Arhitectura Harvard, cu magistrale separate pentru program și date, permite pipeline-ul pe două etaje al AVR și execuția majorității instrucțiunilor într-un singur ciclu - motiv pentru care AVR e RISC. ATmega328P are 32 KB Flash, 2 KB SRAM (adevărata constrângere) și 1 KB EEPROM. Precizia sursei de ceas contează critic pentru comunicația serială asincronă, iar condensatoarele de decuplare nu sunt opționale.

SFR
Special Function Register - interfața între program și un circuit periferic concret.
SREG
registrul de stare al AVR, cu indicatorii Z, C, N, V, S, H, T, I.
Depășire de stivă
stiva și variabilele globale se suprapun în SRAM, cu efecte haotice.
Arhitectură Harvard
memorii de program și de date separate fizic, cu magistrale proprii.
Pipeline
suprapunerea etapelor de execuție a instrucțiunilor succesive.
Hazard
situație care oprește temporar pipeline-ul (de date, de control, structural).
RISC
set de instrucțiuni mic și uniform, executat previzibil, de regulă într-un ciclu.

14Întrebări de verificare6 min

  1. Valoarea unui registru e 0x6D. Scrieți-o în binar și zecimal și precizați biții activi.
  2. Care e diferența funcțională dintre un registru de control și unul de stare?
  3. De ce arhitectura Harvard permite execuția majorității instrucțiunilor AVR într-un singur ciclu, spre deosebire de von Neumann?
  4. Ce e un hazard de control, și cum explică el durata variabilă a unui salt condiționat pe AVR?
  5. Comparați SRAM, Flash și EEPROM după volatilitate, granularitatea ștergerii și numărul de cicluri de scriere.
  6. Un ATmega328P e ceasat la 8 MHz. Calculați perioada ceasului și numărul aproximativ de instrucțiuni pe secundă.
  7. Explicați, pornind de la u = L·di/dt, de ce lipsa condensatoarelor de decuplare produce resetări aparent aleatorii.

15Direcții de aprofundare2 min

Cursul următor trece de la structura internă la procesul propriu-zis de programare: lanțul de compilare, de la codul sursă la biții din Flash, formatul Intel HEX, structura memoriei Flash cu bootloader-ul, și modurile de programare (ISP, prin bootloader).

Registrele, biții și schema de conectare din acest curs devin montaj real în Laboratorul 01B, lucrarea pregătitoare dedicată lucrului direct cu biți și registre.