Você está na página 1de 229

Ale, creierae pentru toi ...

Victor ADSCLIEI

2012

[Pagin intenionat lsat goal]

Lucrarea de fa nu are asociat un ISBN (cod unic acordat oricrei cri din lumea asta) pentru c ea nu a trecut niciodat pe la o editur literar. Prin urmare, singurul motiv pentru care acest manuscris se poate numi carte i nu o aduntur de cuvinte i idei o reprezint dimensiunea sa extins. Totui, pentru a fi ct de ct coreci n aceast privin, prezenta lucrare va face des referire la sine prin termenul de crulie.

Lucrare scris n perioada Toamn 2011 Var 2012. Versiunea curent de referin : 1.0 .

Licena aleas pentru acest material este aceea de Creative Common License de tip
BY - NC - SA, iar dac textul nu v impresioneaz, atunci poate imaginea ei o va face : . Trecnd peste complicciunile legale, exist patru lucruri importante ce trebuie s le tim la acest tip de licen i anume : 1. Aceast licen face parte din clasa LICENELOR GRATUITE. Cu alte cuvinte, materialul de fa se distribuie GRATUIT, iar dac ai pltit pentru a intra n posesia acestuia, v sftuiesc s v cerei banii napoi. 2. Nu avei voie s tragei foloase bneti/economice de pe urma acestei lucrri. 3. Trebuie s m recunoatei pe mine, Victor ADSCLIEI, drept autorul acestui manuscris, a crei proprietate intelectual mi aparine n integralitate. 4. Dac folosii coninut explicit din aceast lucrare, trebuie s o facei integrndu-l ntr-o licen asemntoare cu aceasta i indicnd totodat autorul segmentului folosit.

Finalmente vreau s mulumesc n special familiei mele i lui Ale, fiina, pentru nelegere i sprijinul acordat n tot acest timp de furire a cruliei.

n loc de prefa
Bun! i mulumesc c ai achiziionat acest produs 100% gndit, elaborat, lucrat i construit n Romnia, ara mam a majoritatea dintre cei ce citesc aceste rnduri de moment ce, nu-i aa, nelegei aceste rnduri. Asta este bine i de ateptat de moment ce rioara noastr a nscut o mulime de persoane de geniu dealungul secolelor sale. Nume de mndrie precum Traian Vuia, Aurel Vlaicu, Hermann Oberth, Grigore Moisil, Conrad Haas, George Emil-Palade, Constantin Brncui i alii au rsrit de pe aceste meleaguri i au mpins graniele necunoscutului dnd nu numai romnilor, dar mai ales umanitii noi inuturi de contemplaie i confort existenial. Spun mai ales pentru c sunt muli cei dintre noi care nu numai c nu-i mai cinstensc, dar nici mcar nu i-i amintesc. Motivele sunt multe, dar situaia de fapt rmne : orict ne-am plcea s credem contrariul, plim de pe scena progresului! Sunt sigur c muli dintre noi ne vom ntreba la un moment dat : acetia suntem noi i asta meritm ? Stimate cititor, i mulumesc pentru c exiti. Sper s gseti n Ale o posibilitate de a nva cte ceva despre ceea ce ne poate conferi vremurile noastre n materie de progres tehnologic. S nvai, s nelegei i s extindei Acestea sunt devizele micului experiment ce l-ai gsit n cutie alturi de aceaste cuvinte. mi doresc ca Ale s fie pentru tine o porti spre un inut mai curat moral, mai integru uman i mai performant dect vremurile ce le purtm. Spor, Autorul

Cuprins
,dar ce este mai exact Ale?.......................................................................6 ,dar ce avem n cutie ?...............................................................................6
Crulia .......................................................................................................................7
Cui i este adresat ?...................................................................................................... 7 Cum s o parcurgei ?.................................................................................................... 7

Plcua........................................................................................................................8 CD-ul............................................................................................................................8

O lume a calculatoarelor..........................................................................9
Un pic de istorie .....................................................................................................11 O maimuic deteapt.........................................................................................13 Marele salt...............................................................................................................17 Chiar comunicm prin figuri geometrice cu un calculator ?...........................19 Am ajuns la memorii..............................................................................................24 Ce tiu calculatoarele s fac ?............................................................................25 Universul lor n universul nostru ........................................................................38 Ale intr pe scen...................................................................................................41 Microcreieraul Ale................................................................................................47
Memoria microcreieraului........................................................................................48 Instruciunile cunoscute de Ale ... ..........................................................................51

Un pic despre modulele lui Attiny25 .................................................................63 Ale cunoate lumea!..............................................................................................64


[1s] Ale, f nimic!......................................................................................................... 65 [2s] Iniializarea registrelor generale pe Ale..........................................................67 [3s] Ale ne salut .................................................................................................... 69 [4s] Ale ne salut mai frumos i mai complet....................................................77 [4.1s] O dovad c Ale gndete..............................................................................84 [5s] Ale, mai ncet!....................................................................................................... 85 [5.1s] Unde este stiva ?............................................................................................... 89 [6s] Alte 2 exemple interesante cu LED-uri............................................................91 [7s] Ale, suntem aici!................................................................................................... 95 [8s] Ale, tot aici suntem ...................................................................................... 102 [9s] i dac totul este bine, s continum .......................................................104 [10s] ntrzieri mai bune.......................................................................................... 106 [11s] Fr ntreruperi, v rog .............................................................................112 [12s] Alt ntrerupere, acelai ceas0.....................................................................118 [12.1s] Atenie la ntreruperi!.................................................................................122 [13s] ntreruperi, din nou i din nou ......................................................................125 [14s] Cnd una nu este suficient .....................................................................126 [15s] Cnd milisecundele nu sunt suficiente ...................................................129 [16s] Un ceas mai capabil ....................................................................................136 [17s] mpreun facem lucruri frumoase ...........................................................141

[18s] Cinele, cel mai bun prieten al omului i nu numai ..................................146 [19s] i pe mine cine m-a resetat ?.........................................................................150 [20s] Eco Ale!............................................................................................................. 153 [21s] Un psAle i o Ale. Ceau Ale!...........................................................................157 [22s] Ale, tii cumva ce temperatur este ?..........................................................160 [23s] Lui Ale nu-i trebuie ochelari..........................................................................171 [24s] Din nou, napoi de unde am plecat ..........................................................173
[Jocul 1] PIG...................................................................................................................................... 176 [Jocul 2] 36....................................................................................................................................... 177

O alternativ la ceea ce tim .........................................................................178


nfrumusearea codului prin includeri externe....................................................180 nfrumusearea codului cu ajutorul limbajului C ................................................181

Felicitri! Ai reuit .........................................................................................184


ai ajuns la final!.................................................................................................... 184 ,dar jocul continu ................................................................................................ 185

Extensii de coninut..............................................................................189
1) Instruciuni de instalare a aplicaiei psAle ................................................189 2) Instruciuni de folosire a aplicaiei psAle...................................................193 3) Rspunsuri posibile la problemele propuse...............................................200
Ce tiu calculatoarele s fac ?...............................................................................200 [1s] Ale, f nimic!....................................................................................................... 200 [2s] Iniializarea registrelor generale pe Ale........................................................201 [3s] Ale ne salut....................................................................................................... 201 [4s] Ale ne salut ... mai frumos i mai complet...................................................202 [4.1s] O dovad c Ale gndete............................................................................203 [5s] Ale, mai ncet!..................................................................................................... 204 [5.1s] Unde este stiva ?............................................................................................. 208 [6s] Alte 2 exemple interesante cu LED-uri..........................................................208 [7s] Ale, suntem aici!................................................................................................. 208 [8s] Ale, tot aici suntem .......................................................................................... 210 [9s] i dac totul este bine, s continum ..........................................................211 [10s] ntrzieri mai bune.......................................................................................... 211 [11s] Fr ntreruperi, v rog .................................................................................212 [12s]Alt ntrerupere, acelai ceas0 .....................................................................212 [12.1s] Atenie la ntreruperi!.................................................................................213 [13s] ntreruperi din nou i din nou .......................................................................214 [14s] Cnd una nu este suficient .........................................................................215 [15s] Cnd milisecundele nu sunt suficiente .......................................................216 [16s] Un ceas mai capabil ........................................................................................217 [17s] mpreun facem lucruri frumoase ...............................................................217 [18s] Cinele, cel mai bun prieten al omului i nu numai ..................................219 [19s] i pe mine cine m-a resetat ?.........................................................................219 [20s] Eco Ale!............................................................................................................. 220 [21s] Un psAle i o Ale. Ceau Ale!...........................................................................220

[22s] Ale, tii cumva ce temperatur este ?..........................................................220 [23s] Lui Ale nu-i trebuie ochelari..........................................................................221 [24s] Din nou, napoi de unde am plecat ..............................................................222

4) Scurt fi a registrelor de control a lui Attiny25.....................................225 4) Schema electric condensat a plcuei.....................................................227

,dar ce este mai exact Ale?


Ale reprezint, ceea ce ar numi oamenii din domeniu, o plac de dezvoltare pentru microcontrolere de uz general (n cazul nostru produse de o firm numit Atmel). Nu v facei griji dac nu nelegei toat fraza aceasta. Nici eu nu am neles-o cnd am cunoscut aceast lume de aceea voi ncerca s o reformulez un pic : Proiectul i permite s nelegi modul n care i se deschide ua la magazin atunci cnd apari n dreptul ei i i exprimi intenia de a intra/iei, modul n care pufitoarele de deodorant de camer i lanseaz doza de parfum n ncperea respectiv atunci cnd ea simte micare sau la intervale regulate de timp, n funcie de preferinele personale, sau chiar modul n care se trag jaluzelele automat n funcie de poziia soarelui pentru a permite s intre n camer cantitatea de lumin dorit. Desigur c v-am prezentat doar nite arome ale capacitii proiectului. Pe lng acestea, vei vedea practic cum putem construi un ceas electric, cum funcioneaz termometrele electrice i cum ne putem construi jocuri personale, iar exemplele pot i, cu siguran, vor continua. Bun, poate c Ale nu dispune de resursele fizice pentru a ndeplini chiar toate aceste sarcini, dar cu toate acestea, Ale va pune bazele nelegerii acestor produse ca soluii date de o inteligen i de o latur electric, ambele gndite, construite i implementate de noi. La urma urmei, ce poate fi mai frumos dac nu un frigider care poate s comunice cu aragazul pentru a v face zilnic micul dejun ? Este o idee, dar Ale poate fi un prim pas spre a o transpune n realitate. S ncepem

,dar ce avem n cutie ?


Cutiua ar trebui s conin, sper, urmtoarele elemente : 1. Aceast crulie, 2. CD-ul cu aplicaii, documentaie util i versiunea electronic a acestei crulii, 3. Plcua Ale precum i un 4. Cablu de date USB1 pentru a comunica i a alimenta plcua. Dac lipsete oricare dintre aceste elemente v rog frumos s m contactai pentru a rezolva problema. Putei face acest lucru printr-o scrisoare electronic (e-mail) trimis la adresa admin@tuscale.ro. Este dreptul vostru! Toate aceste elemente sunt necesare pentru a utiliza mediul i a nva plus, haidei s recunoatem : cititul fr un pic de practic este un lucru poate neatractiv, dar sigur plictisitor! n continuare vom explica fiecare component n parte pentru a arta de ce toate ne sunt necesare

prescurtarea vine din englezescul Universal Serial Bus i reprezint un mijloc de comunicaie suportat de majoritatea calculatoarelor moderne

Crulia
Materialul din care citii aceste cuvinte conine explicaii i exemple ce au rolul de a ghida cititorul, adic pe dumneavoastr, spre a nva s foloseasc plcua Ale att n materie de electronic, dar mai ales pe latur de aplicaii inteligente, scrise chiar de noi! Totul pentru a ne face viaa mai uoar. Astfel, plcua va constitui baza nelegerii. Odat cu aceste cunotine fixate, imaginaia va fi urmtoarea limit, fiind capabili s construii aproape orice v va nscoci trtcua. Vei vedea n alt ordine de idei, tot n aceste pagini vei putea gsi informaii utile despre posibilitile de lucru cu plcua i, mai ales, cu creieraul plcuei, vei mai putea gsi informaii referitoare la coninutul CD-ului (le vom aborda imediat) precum i informaii utile legate de modul de folosire al aplicaiei personalizate (ce poart numele de psAle). Ca i strucur, lucrarea este mprit n 3 pri : 1. ncepem cu o scurt discuie despre istoria acestor mainrii miraculoase numite calculatoare, apoi vom apela la un exemplu uor de neles pentru a explica modul lor general de operare. 2. Mergem mai departe i vom ncepe ncet - ncet discuia despre plcu i mai ales despre exemple practice ce se pot evidenia cu ajutorul plcuei, iar 3. n final vom discuta un pic despre direcii viitoare de orientare. Pe la sfritul cruliei vei gsi o serie de seciuni A, i era s uit : dac vor exista situaii n care vei ntlni cuvinte a cror semnificaie nu o vei cunoate precum cuvntul aplicaie, nu v facei griji. Ele v vor fi clarificate atunci cnd le vom discuta pe-ndelete n seciunile lor speciale.

Cui i este adresat ?


Materialul de fa a fost gndit astfel nct s fie citit i neles de ctre oricine dorete s ptrund sau mcar s cunoasc acest domeniu. Este o lucrare ce i propune s v cldeasc o temelie i s v ajute s folosii aceast baz pentru a construi lucruri practice, lucruri frumoase. n general dac avei 6 - 7 clase de coal general nu vei avea prea mari dificulti n a parcurge acest material. Dac avei mai puini aniori, atunci citind aceste rnduri dai dovad de o curiozitate admirabil. Totui, n acest caz v recomand s avei o persoan mai n vrst prin preajm pentru a clarificara eventualele nedumeriri.

Cum s o parcurgei ?
Dei materialul are o construcie progresiv, crulia a fost gndit s poat fi parcurs uor i ct de ct independent pe cele 3 seciuni n funcie de gradul dumneavoastr de absorbie a materialului i de nivelul dumneavoastr actual de cunotine. Totui, pentru o nelegere complet, eu v sftuiesc s luai paragrafele n ordine mai ales dac este prima dat cnd auzii de aceast tem. Expunerea cruliei, vei vedea, a fost gndit asemeni unei poveti, limitnd elementele complicate pe ct posibil.

Ca i elemente importante vei gsi, din loc n loc, 3 tipuri de iconie fiecare cu o semnificaie bine stabilit : Cum arat? Ce nseamn ? Aceast iconi ne arat c urmeaz o zon de ntrebri sau exerciii propuse pentru a fi rezolvate i a fixa teoria nvat n respectiva seciune. Apare, de obicei, la sfritul seciunilor cu aplicaii practice. Ne prezint un indiciu de rezolvare sau nelegere a unui exerciiu. Se gsete, de cele mai multe ori, pe lng o regiune de ntrebri sau exerciii. Informaia prezentat de aceast iconi este deosebit de important i ar fi bine a nu se uita.

Plcua
Unul dintre elementele cheie ale pachetului l constituie plcua de testare Ale. Dac v ntrebai de ce am ales acest nume, aflai c exist un motiv special pentru aceast alegere, unul de natur sentimental. n plus, Ale este un nume uor de pronunat i de memorat. Plcua reprezint modalitatea prin care putem verifica ce am nvat fixnd astfel mai bine cunotinele proaspt dobndite. Ea lucreaz mpreun cu crulia i CD-ul pentru a completa i uura introducerea noastr n acest univers al automaticii1. Ca i posibiliti ale plcuei, va exista o seciune special care va aborda acest subiect n suficient de mare detaliu. Precizm totui c avem destule opiuni prin care putem creea lucruri foarte interesante.

Important : Avei grij cum umblai cu plcua! Nu turnai lichide pe ea i nu o supunei la ocuri puternice pentru c exist riscul de a o strica i asta nu e bine! Tot aici trebuie precizat totui c nu exist riscul pericolului de electrocutare, dar avei grij ca atunci cnd o alimentai cu tensiune prin cablul USB s o punei pe o suprafa uscat i neted. Orice consecin rezultat n urma unei ntrebuinri a plcuei n afar limitelor impuse de acest material aparin n totalitate deintorului i nu creatorului intelectual al plcuei!

CD-ul
Un alt element important n acest pachet (da, ntr-adevr, TOTUL este important!) l constituie CD-ul. Pe el vei gsi att programul psAle prin care putei comunica cu plcua ct i alte diverse materiale de citit, majoritatea scrise n limba englez. Am s plasez aici mai ales documente pe care consider c le vei gsi utile n situaii viitoare, atunci cnd bagajul vostru de cunotine, dar mai ales curiozitatea va atinge un punct suficient de cuteztor. Pentru mai multe detalii privind instalarea i utilizarea lui psAle, vedei seciunile de la final. Acestea fiind zise, haidei s trecem direct i s ncepem discuia noastr cu o prim privire napoi n istorie
1

aa se mai numesc aceste soluii complete : electronic + programare

O lume a calculatoarelor
Trim ntr-o perioad foarte interesant a umanitii. V putei nchipui c, acum nu foarte mult timp, ntr-o vreme n care nu existau alte medii de transmitere a informaiei dect prin viu grai (aici m refer la sate n mod special, dar nu numai), oamenii credeau c subiectele tiin i descoperiri sunt pe cale de a se nchide ? Ce nsemna asta ? Ei bine, ei credeau c tot ce se putea afla despre Univers era deja tiut i c urma doar o perioad de perfecionare a cunotinelor acumulate. Asta se ntmpla undeva la sfritul secolului XIX (mai puin de 200 de ani, cu doar 4 sau 5 generaii n urm!). Nimic nu a fost adevrat n secolul ce a urmat, umanitatea a explodat tiinific i tehnologic: Am perfecionat medicina cu medicamente dedicate i tehnici noi de intervenie care au salvat nenumrate viei i au eradicat nenumrate boli, Ne-am desprins de la sol i am ajuns n aer, spaiu i chiar pe lun, Am descoperit i mbuntit sisteme de predicie a vremii, Procesele industriale s-au rafinat astfel nct producia de bunuri a ajuns n toate cele patru coluri ale pmntului, Am micorat lumea prin tehnici noi de comunicaii cum ar fi telefonul, radioul, televiziunea i, recent, internetul, Pmntul a devenit o hart fizic pe care putem urmri prezena oricrui obiect cu o precizie de civa zeci de centimetri (aa numita tehnologie GPS1), Am descoperit teorii prin care ne-am fixat mai bine rolul nostru n Univers Am privit mai departe ca oricnd de gogoaa Sistemului nostru Solar n cutarea altor lumi pe care, spre bucuria noastr, le-am i gsit Acestea sunt doar cteva din progresele ncepute de noi n ultimul secol. Spun doar cteva pentru c mi-ar fi mai uor s enumr domeniile neafectate de progres dect cele afectate. Dac stau bine i m uit n jur nu vd niciun obiect care s nu fi beneficiat de aceste mbuntiri. De la umilul caiet fabricat din hrtie reciclat de cea mai bun calitate (a progresat i contiina ecologic, dar o omitem din considerente ne-tehnice) pn la aparatele electrocasnice din buctrie sau sufragerie ... totul a nsemnat progres. Cu toate acestea ns, umanitatea, n marea domeniilor mbuntite de tiin, nc nu a reuit s rezolve probleme mai sensibile precum rzboiul, foametea i srcia rilor din lumea a III-a. Paradoxal este faptul c problemele acestea exist nu pentru c nu tim s le rezolvm ci pentru c nu vrem s le rezolvm! Modelul nostru actual de trai are soluii timide i, n general, fr susinere n aceste probleme. Nu vom insista prea mult pe aceste aspecte, dar vreau s fim contieni c ele exist. Am putea chiar spune c unul dintre motivele fundamentale care a inspirat aceast crulie s-a gsit n acest domeniu. Probabil c cele cteva sute de mii de ani ce au trecut i care ne-au adus ca i specie la condiia noastr actual afecteaz mult mai mult natura uman dect cele cteva sute de ani de

provine din englezescul Ground Positioning System sau, n romn, sistem de poziionare prin satelit.
1

progres. S nu uitm c suntem, fundamental, animale i c singura diferen dintre noi i alte animale tradiionale precum maimuele o reprezint inteligena, uneori i lipsa ei ... Revenind la ale noastre: cu toate acestea niciuna din aceste mbuntiri nu ar fi substanial dac nu ar exista una care s le umbreasc pe toate. Cunoscnd specificul acestor gnduri, bnuiesc c avei o idee despre ce a putea invoca aici. Desigur c aici m refer la umilul calculator. Calculatorul, unealta cea mai de pre a societii actuale fr de care, s recunoatem, dac ar exista un cataclism care s strice toate calculatoarele de pretutindeni asemntor celui ce a ras dinozaurii de pe faa pmntului acum multe milioane de ani, umanitatea ar intra instantaneu n declin. Att de profund am ajuns noi s depindem de aceast ultim gselni a progresului. Treaba nu este deloc uoar ... Da ... calculatorul reprezint unealta care conduce, mpreun cu omenirea, lumea n care trim. De la ceasul electronic de pe mn la roboii spaiali sau din hale de asamblare sau sli de operaie i de la banalul semafor electric la televizor/frigider/main auto i chiar i, mai nou, pixuri, nimic din toate acestea nu ar fi posibile astzi fr calculator. Medii de socializare, internetul, canale de comunicaii, site-uri, Google!, totul prin calculator. De fapt un alt scop al calculatorului este acela de a creea alte calculatoare. tiu c este greu de neles, dar cum credei c la fiecare un an i jumtate, inteligena calculatoarelor se dubleaz ? Credei c omul ar putea face asta prin tradiionala foaie cu pix ? Este evident, lumea a ajuns predominant a lor, iar noi suntem creatorii. Calculatorul este unealta, iar noi creatorii Ct de profund este aceast expresie i totui, ct de adevrat! Cu toate acestea, credei c aceste mainrii ar fi capabile de unele singure s fac ceva util ? mi amintesc unul dintre profesorii mei afirmnd : Calculatorul este sclavul ideal!. Da, aa este un sclav prostu, dar obedient i extrem de rapid. Vrei s i se rezolve o ecuaie ? Introduci datele, apei un buton si Evrika1!: rezultat instant! i-e foame ? Nimic mai simplu. Deschizi calculatorul, introduci datele i Voila2!: calculatorul i face o pizza! Sau ? poate exagerez. Poate calculatorul pe care l avei nu tie s gteasc sau s spele, dar fii siguri c exist i astfel de calculatoare. La urma urmei, aa cum ziceam, e greu s gseti domeniu n care, sub diferite forme, s nu fie implicat vreun calculator. n acest sens m gndesc c s-ar gsi ceva triburi n Africa sau din savana amazonian crora nu le-ar fi util o astfel de mainrie. La urma urmei, omul creeaz unelte pentru a-l ajuta s rezolve probleme, ori mi-e greu s gsesc probleme pe care respectivele grupuri nu le-ar putea rezolva dect cu ajutorul unui calculator.

se pronun evrica i reprezint o exprimare celebr folosit de un la fel de celebru filozof i inventator grec Arhimede 2 se pronun voala i este o expresie franuzeasc ce se traduce simplu prin privete
1

10

Un pic de istorie ...


Ei bine, poate nu v vine s credei, dar calculatorul, ca i idee, nu este una ce se ncadreaz n perioada celor 200 de ani discutat mai sus. Asemeni multor altor invenii, calculatorul, ca i concept exista cu mult naintea descoperirii curentului electric (sngele ce curge prin calculatoarele moderne). Vom face o mic excursie n timp i vom apela la un pic de istorie pentru a ne ghida. tiu c subiectul acestei cri este unul predominant tehnic, dar rezistai alturi de mine : voi aminti doar nite repere interesante, demne de inut minte. Primul calculator mecanic a fost inventat de matematicianul Blaise Pascal n 1642 la vrsta de 19 ani! Calculatorul tia s realizeze adunri, scderi, nmuliri i mpriri. Era, am putea spune, o versiune mult mai simpl a ceea ce noi numim azi calculator de buzunar. Motivarea aleas de Pascal atunci cnd a construit mainria a fost aceea de a-l ajuta pe tatl su s in evidena muncii sale. Cu toate c tia s fac operaiile elementare a unui calculator de buzunar, invenia lui Pascal nu arta a nimic din ceea ce azi recunoatem ca fiind un calculator. Convingei-v singuri :

Era practic o cutie mecanic pe care se introduceau numere i operaii matematice simple i se extrgeau rezultate. S nu uitm totui faptul c asta se ntmpla acum mai bine de 350 de ani n urm! Mai bine de 150 de ani mai trziu, n 1801, Joseph Marie Jacquard inventa n Frana un rzboi de cusut care, cu ajutorul unor cartele perforate ce conineau informaii despre tiparele complicate ale custurilor, reuea s automatizeze producia de obiecte tricotate i n acest fel s trag n jos preul produselor sale. Peste noapte tiparele complicate i exotice nu mai erau destinate numai celor din nalta societate, ele devenind accesibile i altor categorii sociale. n imaginea urmtoare putei s vedei cartelele lui Jacquard :

11

Apoi, n 1837, folosind cartelele lui Jacquart i ideea lui Pascal, Charles Babbage, proiecteaz o mainrie ce avea s reuneasc toate principiile fundamentale ce se gsesc azi n calculatoare : o cutie numit i unitate care putea face calcule matematice, posibilitatea de a implementa salturi n execuia codului, posibilitatea implementrii de cicluri i ceea ce azi numim: memorie intern. (Dac exist termeni din acesia care vi se par strini, nu v facei griji!: i vom aborda pe ndelete un pic mai ncolo.) Observai v rog ct de timpuriu a fost debutul mainilor de calcul pe scena istoriei. Cu toate acestea, abia pe la jumtatea secolului trecut au nceput calculatoarele s fie produse i utilizate pe scar larg. De ce credei c s-a ntmplat aa ? Nu era vorba de problema multiplicrii componentelor destinate unui calculator (lucru problematic dac ne gndim c Pascal a propus calculatorul su n 1642) sau de utilitatea unei astfel de mainrii ci, paradoxal, motivul pentru care primele calculatoare nu s-au rspndit a fost unul de ncredere. Oamenii pur i simplu nu aveau ncredere n rezultatul produs de astfel de mainrii! Calculatoarele erau vzute asemeni unor bestii exotice : potrivite pentru atracii de circ, dar din pcate, doar att! Erau prea puine persoane care aveau ncredere ntr-o soluie generat de o main fr a se ntreba dac ntr-adevr rezultatul obinut este cel corect. Acesta a fost motivul din pricina cruia calculatoarele iniiale nu au prins la public. Chiar dac rezultatul operaiei era cel corect, nimeni nu demonstrase c respectiva valoare nu era doar ntmpltoare i c, la o nou reevaluare, maina nu va scoate un rezultat nou, diferit de cel iniial. Vedei voi, faptul c o soluie exist nedemonstrat nu garanteaz c ea va fi i folosit. Ba din contra oamenii nu folosesc ceea ce nu neleg. Un contraexemplu ar fi calculoarele personale date pe mna copiilor din ziua de astzi. Copil fiind, nu-i pas cum este construit o astfel de main atta timp ct i ofer ceea ce caui : jocuri, medii de socializare, etc. Principial lucrurile nu ar trebui s fie aa, iar proverbul lui Carl Sagan (autor) : Am aranjat lucrurile astfel nct nimeni nu mai nelege concepte de tiin i tehnologie. Aceasta reprezint o reet de dezastru. S-ar putea s-l evitm o perioad, dar mai devreme sau mai trziu, ignorana ne va ucide. surprinde, n opinia mea, capcanele unei astfel de gndiri. Aceast tendin se observ, din pcate, i la persoane mature. Revenind i sumariznd: faptul c nu foloseti ceea ce nu nelegi este o gndire corect. Noi, ca fiine raionale, dac utilizm ceva pentru a ne rezolva o problem precum o soluie pe care o cumprm sau n care investim resurse, ne ateptm ca respectivul proiectant de soluie s ne asigure c nelegem la un nivel confortabil cum funcioneaz unealta utilizat. n acest sens, pe baza a ceea ce cunoatem referitor la problem, dorim s prezicem un oarece rezultat n care s avem ncredere c este corect. Cnd era vorba despre calculatoare ns, nimeni nu-i putea asuma riscul de a garanta o astfel de soluie. Cum credei c s-a rezolvat acest lucru ? n anii 30, un geniu matematic pe nume Alan Mathison Turing, demonstreaz pe baza unor fundamente logice, c mainile de calcul pot fi considerate de ncredere. Pe baza lucrrii sale i odat cu apariia i rspnirea curentului electric, comunitatea tiinific precum i interesul pentru tiina calculatoarelor litaralmente explodeaz. n anii ce vor urma, calculatorul va cunoate o continu transformare. Astfel,

12

dac la nceput, primele calculatoare erau de dimensiuni uriae ocupnd ntregi hangare, erau nzestrate cu performane hilare n comparaie cu modelele curente i se vindeau la preuri aa de mari nct numai armatele i le puteau permite. Odat cu evoluia tehnologic lucrurile au nceput s se schimbe rapid. Descoperirea tranzistorului i a circuitului integrat a condus la realizarea unor maini de calcul cu dimensiuni din ce n ce mai mici, cu viteze din ce n ce mai mari i preuri din ce n ce mai reduse ajungnd ca n anii 80 s poat fi achiziionate chiar i de ctre persoane particulare. E inutil s amintim aici c aceast evoluie a evenimentelor nu a ncetinit nici n zilele noastre. Ba din potriv, am ajuns s depindem de calculatoare acum mai mult ca niciodat. Iar restul, dup cum se spune, este istorie

O maimuic deteapt
Acum c am parcurs un pic nite repere istorice, vom ncerca s analizm o astfel de mainrie pentru a nelege modul ei de funcionare. i cum am putea face asta mai uor dac nu printr-un joc ? Imaginai-v c suntei prieteni cu o maimuic (bine hrnit i ngrijit) i c avei posibilitatea de a o nva lucruri, n special aciuni. O vei convinge s v asculte ? Eventual stimulnd-o cu ceva, poate o recompens precum o banan sau alt aliment. Cu puin noroc, o vei putea nva s v fac curat prin cas sau mai tiu eu ce. Totui, de dragul discuiei, imaginai-v c suntei capabili s o nvai s se uite pe o band. n acest sens considerai c avei o band (fie) alb, lung i fragmentat n 10 figuri geometrice aezate una lng alta.Pentru nceput vom considera c pe respectiva band se afl doar dreptunghiuri. S spunem c fiecare band are 10 dreptunghiuri, cam aa :

Odat ce maimuica va primi banda, va ncepe de la dreptunghiul 1 i va executa mereu aceeai secven de aciuni : a. Privete dreptunghiul i. dac este umplut cu negru se oprete i ntinde mna dup recompens, iar ii. dac nu este negru, avanseaz banda mai departe astfel : 1. dac banda s-a terminat se oprete fr a cere nimic sau 2. dac nu, continu cu aciunea descris la punctul a. Ct de util ar fi o astfel de ndeletnicire ? Pi cunoscnd faptul c maimuica este asculttoare, voi, ca i supraveghetori ai putea cronometra ct i-a luat ei s ndeplineasc sarcina respectiv precum i dac pe banda n cauz a gsit un dreptunghi negru. S presupunem c avem un ceas i c notm momentul n care i dm banda maimuicii. Odat nmnat banda, fptura va realiza ceea ce a fost nvat i anume : va analiza fiecare dreptunghi i se va opri numai la ntlnirea unuia dintre cele 2 cazuri : fie s-a ajuns la un dreptunghi colorat negru, fie s-a terminat banda i nu a existat niciun astfel de dreptunghi. Dac dorim s msurm timpul scurs ntre primirea benzii i oprirea maimuicii vom vedea c, n funcie de locul unde se afl dreptunghiul negru situat pe band, vom nregistra perioade diferite de timp.

13

S lum un exemplu concret. Prespunuem c fia noastr arat n felul urmtor : La ntlnirea acesteia, maimuica ar face dup cum a fost nvat : va derula banda dreptunghi cu dreptunghi pn la ntlnirea dreptunghiului negru dup care se va opri. Ceea ce descriem aici, dragii mei, este la un nivel elementar, comportamentul unei mainrii. Noi am nvat maimuica i maimuica, n funcie de banda primit, a aplicat ce a fost nvat. S inem minte acest aspect pentru c ne vom mai ntlni cu el pe parcursul cruliei. Desigur c odat gsit dreptunghiul negru i dm recompensa binemeritat, dar ce-ar fi dac am face un pic situaia mai util ? Cu toii am vzut mcar o dat (la intrarea n magazine, n scri de bloc sau n curi) un bec inteliget care , atunci cnd este sear i simte micare, se aprinde pre de cteva secunde dup care se stinge din nou. Nu ar fi interesant dac am nva maimuica noastr s mimeze un astfel de comportament ? Vom face exact acest lucru ... Este evident faptul c nu este suficient ceea ce tie acum maimuica. Nu apare niciun bec n descrierea comportamentului ei! n acest sens trebuie s modificm un pic secvena de aciuni. Imaginai-v c n momentul n care maimuica primete banda, ea va apsa pe un buton (care n exemplul nostru va aprinde becul). i va continua secvena de aciuni pn cnd va gsi primul dreptunghi negru (considerm c ntotdeauna va exista cel puin un astfel de dreptunghi negru pe band) moment n care va apsa pe acelai buton, dar de data aceasta stingnd becul. Dac lum n calcul faptul c fiecare analiz urmat de o deplasare a benzii consum timp (cum este i normal), cu ct dreptunghiul opritor este mai la sfrit, cu att mai mult va sta respectivul bec aprins. Maimuica ar face, n esen, ce ar face i un bec inteligent. S urmrim din nou un exemplu. Considerm c o privire urmat de o deplasare consum 3 secunde (avem o supermaimuic). Notm aceast lucru prin t =3s , iar banda care i-o dm maimuicii arat n felul urmtor :

Conform celor discutate anterior, ea va lua banda, va aprinde becul i o va derula de 5 ori consumnd t5=35=15s nainte de a stinge becul din nou. Acum se poate vedea mai bine acest comportament de bec inteligent. Observai v rog cum poziia dreptunghiului negru influeneaz numrul de secunde n care becul este pornit. Dac am dori s mrim acest timp, nu ar trebui s facem altceva dect s i dm maimuicii o nou band cu un dreptunghi negru poziionat mai spre sfrit. Cu alte cuvinte, odat nvat (partea cea mai dificil), este suficient s schimbm secvena de figuri i obinem un cu totul alt comportament. Observm aici o alt caracteristic a calculatoarelor: ele sunt nvate s recunoasc simboluri atunci cnd sunt create i nu pot fi dezvate. Comportamentul lor este dat doar de modul n care sunt combinate figurile geometrice pe band. Rmnem la acelai exemplu, dar lum un alt caz :

n aceast situaie becul se va stinge dup ce vor trece t8=38=24s de la primirea benzii. Desigur c acelai lucru se poate realiza i dac dorim un timp mai scurt de aprindere, caz n care dreptunghiul negru ar fi fost poziionat undeva mai pe la nceput.

14

Odat cu aceste noi deprinderi, maimuicii i vor crete cu siguran ansele la gsirea unui loc de munc, dar parc poate mai mult. S nu uitm c avem deaface cu o super maimuic. Dac aa stau lucrurile, de ce s ne oprim aici cu nvatul ? Un singur dreptunghi, fie el i colorat, pare un pic prea puin pentru potenialul animluului. Putem fi mai creativi de-att nu credei ? S complicm un pic lucrurile... De aceast dat vom considera c banda respectiv poate s conin 4 tipuri de figuri geometrice. Fiecare element introduce o aciune ce va fi executat atunci cnd respectiva figur va fi ntlnit de maimu. Pe lng aceast modificare, vom presupune c maimua dispune acum, pe lng ntreruptorul ce acioneaz becul iniial, de alte 2 ntreruptoare ce acioneaz o sonerie i o u de garaj. S vedem care sunt cele 4 tipuri de figuri i ce reprezint ele : 1. 2. La ntlnirea acestei figuri, maimua va apsa pe sonerie. Acest figur i va comunica maimuei s apese pe ntreruptorul uii ce deschide garajul. Figura aceasta i va comunica maimuei s atepe 2 secunde nainte de a continua s interpreteze banda. Dreptunghiul i va pstra interpretarea din exemplul anterior cu o mic precizare : La ntlnirea dreptunghiului umplut cu culoarea neagr, maimua va opri execuia i va nchide toate ntreruptoarele apsate pn atunci.

3. 4.

Dispunnd de aceste noi aciuni, am putea crea scenarii mai complexe pentru maimuica noastr. Un astfel de scenariu ar fi urmtorul : 1. Ateapt 2 secunde 2. Deschide ua de la garaj 3. Ateapt 4 secunde 4. Apas soneria 5. Ateapt 2 secunde 6. Oprete-te i nchide toate ntreruptoarele pornite Transpunnd aceast secven de instruciuni pe o band am obine urmtoarea reprezentare grafic : Important : Dac vom considera timpul de citire i avansare ca fiind, asemeni precum exemplul original : , atunci timpul efectiv de ateptare dat de ntlnirea figurii va fi de t +2s=3s+2s=5s . De asemenea, v rog observai cum numrul de aciuni introduse de noile figuri geometrice mresc numrul de scenarii care pot fi duse la capt de maimu. Totui, acest numr nu este unul nelimitat. El este la rndul su impus de numrul total de figuri suportate de band (n cazul nostru, 10). Odat cu aceste noi capaciti, maimuica noastr ar fi cu siguran cea mai deteapt maimu din lume. Putem mai bine ? Putem. Mereu se poate mai bine! Ce-ar fi dac am

t=3s

15

introduce nite aciuni mai speciale care afecteaz nsi modul de comportare al fpturii atunci cnd aceasta deruleaz banda. La ce m refer prin asta ? Pi s vedem Am putea nva maimua s recunoasc o nou figur : care va nsemna sari peste urmtoarea figur geometric dac am ateptat cel puin 8s pn am ajuns aici. Dac acest lucru nu este adevrat, continu citirea i interpretarea urmtoarei figuri de dup . Cu alte cuvinte i vom conferi maimuicii ocazia de a nu mai inspecta figura ce urmeaz dup aceast nou form, dar doar dac a ateptat pn a ajuns aici un numr de cel puin 8 secunde. Nu ne interseaz peste ce figur sare, atta timp ct condiia de salt este ndeplinit. Desigur c pentru aceasta maimuica va trebui s tie ct a ateptat. Putem s o ajutm s fac acest lucru. i vom da un carnet i un creion i o vom lsa s scrie ori de cte ori ateapt, numrul de secunde pe care trebuie s-l sar nainte de a mai face o avansare de band cu interpretare. Cu alte cuvinte, carneelul i va spune maimuicii dac ndeplinete sau nu condiia de a sri peste urmtoarea instruciune atunci cnd va ntlni figura .

Deja se complic lucrurile, dar exemplele mereu ajut. Vom considera urmtoarea band :

Este aceeai band din exemplul precendent n care am mai adugat 2 figuri evideniate printr-un chenar punctat. Ce se va ntmpla n aceast situaie ? Ei bine, pn la ntlnirea simbolului , maimuica va citi 4 de ceea ce va determina ca pe caieel s ajung s noteze faptul c a ateptat 42=8s . Cum condiia noii figuri a fost ndeplinit (nu uitai condiia este satisfcut atunci cnd timpul ateptat este de cel puin 8s), urmtoarea figur de dup oprire. care este un nu va fi executat, srind direct la dreptunghiul de

Ce se ntmpl aici ? Un lucru foarte tare! Haidei s mai lum un exemplu s vedem i un caz de ne-salt. Vom considera urmtoarea fie :

n aceast situaie, 3 x

= 3 x 2s = 6s au fost notate de fptur la momentul ntlnirii

simbolului ceea ce nu este suficient pentru a realiza aciunea de salt pentru c, evident, cele 6 secunde acumulate sunt mai puine dect cele 8 secunde de care are nevoie condiia de salt. Astfel, urmtoarea instruciune ce se va executa va fi ntrziere de 2s. adic o

16

Partea foarte interesant este aceea c, indiferent dac se realizeaz saltul sau nu, instruciunile garanteaz c va exista o ntrziere de cel puin 2 secunde dup depirea grupului. Cum se poate ntmpla aa ceva ? Exist, n funcie de valoarea de adevr a condiiei lui , doar 2 cazuri de execuie a secvenei prezente : 1. dac saltul va fi executat, garania merge chiar pn la 8 secunde pentru c asta este condiia de salt a lui , iar 2. n caz contrar, dac lum situaia n care condiia celor 8 secunde nu este ndeplinit, atunci saltul nu este realizat i instruciunea de dup simbolul citit i executat. Acest lucru face ca aplicaia s ntrzie 2 secunde. este

Aadar, n orice situaie s-ar afla codul, prima instruciune de dup , oricare ar fi ea, ar avea certitudinea c pn s se ajung la ea au trecut cel puin 2 secunde indiferent de instruciunile ce se aflau naintea blocului! Acest indiferent este o afirmaie foarte ndrznea i puternic deopotriv pentru c ne permite s creem, dac nevoia o cere, secvene mult mai uor de analizat i neles. Pstrai aceast idee pentru c o vom regsi atunci cnd vom lucra cu plcua! Tocmai ai vzut o secvent din ceea ce sunt instruciunile de control. Ele reprezint un concept foarte puternic pentru calculatoare dup cum vom vedea pentru c ne permit s lum decizii n secvena noastr de figuri/simboluri. Acestea fiind spuse, posibilitile de combinare ale figurilor geometrice sunt muuult mai multe. Maimuica noastr a crescut de la a urmri nite dreptunghiuri pe o fie simpl la a nota informaii i a nelege simboluri complicate care-i dicteaz nsi modul su de manevrare a benzii. tii cum se spune : la coal mult, salar mai mare! Se pune problema, angajator fiind, dac exist o alternativ pentru maimuica noastr. O alternativ care s diminueze costurile deoarece, nu-i aa, acesta este scopul nostru ca angajator : minimizarea cheltuielilor (ex. salarii) i creterea profitului. Dei maimuica nu cere dect banane, se poate mai bine ? Surpinztor, dar exist o alternativ la maimuica noastr ...

Marele salt
tiu ce putem face : nlocuim maimuica cu un calculator! Ce credei, avem suficiente cunotine s o facem ? Poate o s vi se par ciudat, dar exemplul cu maimuica a fost ales pentru a schia o introducere n modul de operare al calculatorului personal (PC1) precum i a majoritii calculatoarelor ce exist la ora actual n lumea asta. Pentru ce am avut nevoie noi, a fost suficient.

Personal Computer. n traducere : calculator personal

17

Vom ncepe prin a ncerca s creionm o mic definiie a ceea ce poate fi un calculator. Pentru a nelege mai bine lucrurile, vom folosi ce am nvat din exemplul cu maimua. Aadar, putem considera calculatoarele ca fiind unelte (maimue) ce pot fi programate (nvate - n cazul nostru) s execute o serie de instruc iuni nirate una dup alta (pe un spaiu asemntor benzii) pentru a ob ine un rezultat dorit (imitarea comportamentului unui bec inteligent, de pild). Altfel spus: calculatoarele sunt, asemeni multor alte unelte create de om, nite mainrii ce pot fi nvate aciuni pentru a ne face viaa mai uoar. Puterea calculatoarelor n acest scop o reprezint chiar aceast capacitate de a fi nvate. Dac un televizor sau o lantern au ntrebuinri fixe, calculatoarele reprezint exact opusul. n funcie de caz, putem s ne jucm, s lucrm pe el sau s inem evidena cheltuielilor personale, sau orice altceva, toate pe un singur dispozitiv, acelai dispozitiv! Acestea fiind spuse, mergem mai departe i evideniem direct legtura dintre exemplul nostru cu maimuica i un PC ntr-o form tabelar :
Din universul maimuei ... Maimua Banda de figuri geometrice Figurile geometrice ntreruptoarele Carneelul n universul calculatorului Calculatorul Memoria de instruciuni Instruciunile propriu-zise Zonele specializate de execuie Memoria de date

ntr-adevr, dac ar fi s transpunem grafic cele 2 entiti, am putea obine ceva asemntor cu urmtoarele imagini : Super Maimuica Calculatorul real

, ceea ce este suficient pentru a observa o destul de mare asemnare ntre cele 2 noiuni.

18

Uitndu-v pe aceste desene, am mai spus-o, dar e bine de repetat : nu v batei prea mult capul cu nelegerea termenilor. i vom lmuri n paginile urmtoare. n schimb, ncercai s v fixai o coresponden ntre lumea animluului nostru i calculatorul. Acum vom aborda fiecare echivalen n parte, fiecare n afar de calculator maimuic desigur. Motivul? : Calculatorul reprezint suma tutuoror elementelor descrise n tabelul de mai sus. Prima i prima dat ne vom ocupa de limbaj ...

Chiar comunicm prin figuri geometrice cu un calculator ?


Ei bine, nu chiar. Cine ar vrea una ca asta? Dac stm bine i ne gndim, ar fi incomod s trebuiasc s desenm ori de cte ori am dori s ne verificm corespondena electronic de pild. Ceea ce se ntmpl ntr-un calculator este un pic mai diferit i mai simplu oarecum. Echivalentul figurilor geometrice ntr-un calculator l reprezint nite coduri date de numere nmagazinate n sistem binar1. O astfel de secven binar este i urmtoarea :

010111000101101001110110001
Calculatorul folosese sistemul binar ca baz de referin pentru c i este cel mai uor de neles. Sistemul binar ne d posibilitatea de a creea numere alctuite doar din simbolurile/cifrele 0 i/sau 1. Practic, folosind grupri unice, de astfel de simboluri putem defini echivalentul figurilor geometrice pentru maimuic. Aceast secven unic le confer o proprietate remarcabil: pot fi interpretate ca i numere obinuite! Ce vreau s spun prin aceasta ? S lum toate secvenele posibile de numere binare alctuite din 2 simboluri :

00 01 10 11
Dup cum vom vedea, putem da o interpretare mai util acestor secvene. Spre exemplu, pentru 0 0 putem spune c aceast secven nseamn 0 n lumea noastr, extern calculatoarelor, 0 1 nseamn 1, 1 0 2, 1 1 3. Regula de interpretare nu este dificil i o vom discuta imediat. Mai nti s vedem ce sunt defapt numerele, aa cum le tim noi. Spre deosebire de sistemul binar, noi oamenii utilizm un alt sistem de numeraie i anume cel zecimal. Elementele acestuia sunt, aa cum bine ne-am dat seama, cifrele :

0123456789
Dac n notaie binar un numr poate s conin doar 2 simboluri2, sistemul zecimal prezint posibilitatea definirii i utilizrii a 10 cifre : 0, 1, 2, 3, 4, 5, 6, 7, 8 i 9. Un exemplu de numr scris n sistem binar ar putea fi 1001 sau 010010, iar un exemplu de numere scrise n sistem zecimal ar putea fi 1275 sau 93712034.

1 2

se mai numete i baza 2 de la cele 2 simboluri ce-l definesc {0, 1} binar = 2

19

Tot n sistem binar, o band de figuri geometrice s-ar prezenta n urmtoarea manier :

0011

0001

0001

0111

0001

...

n aceast nou notaie, calculatorul nu are de a face cu figuri geometrice, ci lucreaz cu coduri formate prin alturarea simbolurilor binare 1 i 0. Spre exemplu, el ar putea ti c 0001 nseamn stop, iar 0011 nseamn aprinde bec. Cum? Ei bine, aceste coduri sunt alese de cel ce proiecteaz calculatorul. Important de amintit este faptul c, n calculatoarele moderne, dimensiunea minim a unui cuvnt binar este de 8 simboluri sau un multiplu de 8. Un simbol binar poart denumirea de bit, iar 8 bii unii formeaz un octet1. Cu alte cuvinte, noi, ca i utilizatori ai calculatoarelor, nu avem, n mod obinuit, acces direct la biii unui sistem ci la pacheele a cror dimensiune fix ne este impus. Astfel, cu noile cunotine dobndide, banda de mai sus ar arta mai degrab n felul urmtor :

00000011

00000001

00000001

...

Din cauza faptului c 8 este o cifr par, un alt sistem numeric ce se utilizeaz n calculator este sistemul hexazecimal2. Simbolurile ce alctuiesc vocabularul acestui sistem sunt :

01234567890ABCDEF
Un exemplu de numr corect scris n acest sistem ar putea fi 90 sau 85, dar i B3 sau chiar FC. Observai v rog cum numerele pot fi scrise cu ajutorul literelor. 10 cifre nu sunt deajuns pentru cele 16 simboluri aa c s-a apelat la litere din alfabet. Motivul pentru care se folosete aceast baz (16) este acela c ajut la nelegerea mai uoar a octeilor. Practic, orice octet se poate scrie prin alturarea a 2 simboluri din vocabularul hexazecimal. Modul de traducere dintr-o baz de numeraie n alta l vom aborda n subseciunile ce urmeaz.

Trecerea hexazecimal

binar

Aceast trecere se poate realiza foarte simplu, iar procedeul este urmtorul: considerm un octet ca fiind mprit n 2 regiuni de cte 4 bii fiecare. Pentru fiecare grupare de 4 bii rezultai ne uitm n tabelul urmtor i i nlocuim cu simbolul hexazecimal asociat :
Simbol hexazecimal 0 1 2 3 4 5 6 7
1 2

Grupare de bii asociat 0000 0001 0010 0011 0100 0101 0110 0111

sau byte n literatura de specialitate hexa = 16 simboluri

20

8 9 A B C D E F

1000 1001 1010 1011 1100 1101 1110 1111

Astfel, pentru numrul binar 11010010 am gsi c prima jumtate de octet 1101 are n tabel asociat simbolul D, iar urmtoarea jumtate 0010 are asociat simbolul 2. Prin urmare, secvena binar 11010010 are echivalentul n sistem hexazecimal pe gruparea (sau numrul) D2. De observat este faptul c procedeul merge i invers : dac avem un numr n notaie hexazecimal, l putem transpune n echivalentul su binar tot pe baza tabelului. Exemplu : dorim s exprimm n binar numrul B7. Facem asta lund simbolul B i cutnd de data asta echivalentul su n binar care este 1011. La fel facem i pentru simbolul 70111. Alturm cele 2 jumti i avem rspunsul n binar : B7 = 10110111. Simplu. De fapt, aa cum v spuneam, acesta este unul din motivele pentru care se folosete acest sistem de numeraie n lumea calculatoarelor : este foarte simplu s trecem o valoare din sistem binar i viceversa. Acest lucru nu se poate spune i despre transformarea din sistem binar n zecimal (i invers), dup cum vom vedea n continuare.

Trecerea zecimal binar


Dac la conversia din hexazecimal n binar, procedeul era aproape identic cu traducerea din binar n hexazecimal, lucrurile se schimb cnd intr pe scen sistemul zecimal (n baza 10). Pentru sistemul zecimal, nu exist un tabel frumos din care s scoatem simbolurile aa cum am vzut n cazul anterior. n schimb, exist procedee matematice pentru ambele direcii de transformare. S discutm mai nti conversia din binar n zecimal. Vom discuta procedeul direct pe un exemplu pentru a-l nelege mai bine. S considerm c dorim s transfomm numrul binar 11010010 n echivalentul su zecimal. Pentru asta vom nota poziia fiecrui bit din numrul binar de la dreapta la stnga ncepnd cu indexul 0. Astfel, vom avea :
7 6 5 4 3 2 1 0

11010010
n continuare ne vom folosi de urmtorul tabel : Poziie Valoare 7 128 6 64 5 32 4 16 3 8 2 4 1 2 0 1

21

i acum vine matematica : Ne uitm deasupra fiecrei cifre binare de 1 i adunm din tabel valoarea asociat acelei poziii din cadrul numrului binar. Dac explicaia este prea greoaie, propun s vedem concret : Avem 1 pe poziiile 1, 4, 6 i 7. Pe poziiile 0, 2, 3, 5 avem 0. Ne uitm n tabel i adunm valorile ce le gsim pe poziiile 1, 4, 6 i 7 i acesta este rezultatul. Cu alte cuvinte 11010010 (n baza 2) = 2 + 16 + 64 + 128 = 210 (n baza 10). S mai lum un exemplu : 10110111. S-i scriem poziiile biilor :
7 6 5 4 3 2 1 0

10110111
Acest numr are 1 pe poziiile 0, 1, 2, 4, 5 i 7. Prin urmare 10110111 n baza 2 sau, folosind o notaie mai scurt, 101101112 este egal cu 1 + 2 + 4 + 16 + 32 + 128 = 183 n baza 10 sau, folosind aceeai notaie, 18310. i exemplele pot continua Desigur, tabelul este bun doar dac dorim s transpunem numere de maxim 8 bii, dar cu puin perspicacitate, el poate fi uor extins i aplicat i pe un numr mai mare de bii. Totui, de amintit este faptul c n aceast crulie, 8 bii ne vor fi suficieni n majoritatea cazurilor (poate chiar toate)! Ok, haidei s gndim acum invers : s presupunem c avem un numr scris n baza 10 (cum este de cele mai multe ori cazul) i dorim s-l transformm ntr-o valoare cunoscut de calculator. Ce facem ? Procedeul este un pic chiar mai complicat, dar l vom clarifica printr-un exemplu. S presupunem c numrul ce vrem s-l transformm n baza 2 este 183, acelai ca rezultatul anterior, ceea ce ne d posibilitatea de a verifica dac conversia din binar n zecimal am realizat-o corect. Revenind: Avem 183 (n baza 10). Cum l transformm n baza 2? Ei bine, rezultatul l aflm prin mpriri repetate la 2 i notarea resturilor. Atunci cnd valoarea ctului va ajunge la 0, vom lua resturile n ordinea invers a scrierii lor i acela ne va fi rezultatul. Concret :

Se observ cum ctul fiecrei mpriri la 2 ajunge, n urmtoarea etap, dempritul, rezultnd un rest (1 sau 0) n proces. Procedeul continu pn cnd respectivul ct ajunge 0. Rezultatul transpunerii se obine prin luarea invers a resturilor i formarea unui numr binar din ele. ntr-adevr, dup cum putem observa pe desen, rezultatul obinut este identic cu cel din conversia binarzecimal, deci putem concluziona c am procedat corect.

22

Haidei s mai lum un exemplu. Considerm, de data aceasta, numrul 13 la care dorim s-i aflm echivalentul n binar. Procedm identic ca mai sus i obinem :

Ceea ce, dac facem proba din binarzecimal, reprezint un rezultat corect. Dar stai un pic! Rezultatul este pe 4 bii, cum se va regsi el ntr-un calculator dac am spus adineauri c aceast mainrie, orice calculator modern, nu cunoate s lucreze dect cu pachete de 8 bii (octei)? Ei bine se poate rezolva problema printr-un mic truc care nu modific rezultatul : mai adugm 0 n stnga. Ci? Ati ci sunt necesari pentru a ajunge la cei 8 bii dorii. Putei s m credei pe cuvnt sau, mai bine, s ncercai s verificai faptul c 000011012 este tot una cu valoarea exprimat de 11012 , care este

1310 sau 0D, valoarea hexazecimal (cu notarea prescurtat complet: 0D 16 ).


Cam att despre conversia binar zecimal. Cumva, cred c suntei de acord cnd v spun c lumea calculatoarelor ar fi mult mai fericit dac nu ar lucra cu baza 10, dar aici este problema : dei calculatoarele ar fi mai fericite, oamenii cu siguran, nu! Ar mai exista un tip de conversii i anume din zecimal n hexazecimal (i viceversa), dar pe acestea nu le vom discuta pentru c putem ajunge s facem astfel de conversii aplicnd ce cunoatem deja : conversii zecimalbinare urmate de conversii binarhexazecimale. Rezultatul este acelai. Desigur c se poate gsi o formul de conversie direct zecimal hexazecimal (care va conine mpririle i produsele ce le-am vzut la conversiile zecimal binare), dar ele sunt att de rar necesare nct nu-i au rostul a fi explicate mai ales dup dificultatea ce am ntlnit-o la conversiile binar zecimale. Nu mai este un secret pentru nimeni faptul c sistemul acesta zecimal e plin de probleme! He hee tim conversii! Foarte frumos! Numerele, dup cum vom vedea, reprezint singurul lucru pe care calculatoarele l cunosc. Iar singurul sistem de numeraie cunoscut de calculatoare este cel binar. n consecin, este extrem de important s cunoatem acest sistem precum i modaliti de a aduce valori ntr-o form mai uoar de neles. Aici fac referire la diferite conversii posibile. Seciunea de memorii ce urmeaz va continua studiul simbolurilor pentru a ncerca s explice cum pot ele alctui banda respectiv carneelul din exemplul nostru cu maimua. Haidei s mai ridicm o ultim problem nainte de a continua. S considerm c avem numrul 10, dar nu tim n ce baz este el scris. Fr a cunoate asta, el poate fi n oricare din cele 3 : are simboluri att din vocabularul zecimal, binar dar i hexazecimal. Cum rezolvm aceast confuzie ?

23

Secretul const n adugarea unui prefix1 la numrul iniial. Astfel, dac am fi dorit ca numrul s fie iniial scris n baza 2, el ar fi trebuit prefixat cu 0b2 rezultnd 0b10. Dac am dori ca numrul s fi fost exprimat n baza 16, atunci respectivul prefix ar fi trebuit s fie 0x3 rezultnd 0x10. Lipsa prefixului sugereaz faptul c numrul este scris n baza 10. Aa vom face referire la numere din diferitele baze de numeraie de-acum nainte.

Am ajuns la memorii
Ce s-ar alege de lumea n care trim dac nu am avea memorie? Exist o vorb pe care probabil c ai mai auzit-o : cei ce nu i cunosc trecutul sunt blestemai s-l repete. Este nevoie de memorie peste tot : orice fiin are memorie pentru a-i cunoate mcar predtorii, a ti ce e comestibil i ce nu, ba chiar i plantele au nevoie de memorie atunci cnd se orienteaz ctre soare. Memoria unui calculator este la fel de important. n ea se gsesc att instruciuni de executat (asemntoare cu figurile geometrice de pe banda maimuicii) ct i informaii utile calculatorului (echivalentul carneelului). Cnd vorbim de memoria unui calculator, neleg c s-ar putea s existe dificulti n a nelege conceptul. La urma urmei, e greu de artat unde se afl ea fizic n cadrul calculatorului. Pentru a nelege mai bine ideea de memorie n calculatoare a vrea s v gndii la memorie ca fiind o mulime de cni/pahare puse una lng alta i numerotate de la 0 (valoare limit des utilizat n calculatoare) pn la o valoare foarte foarte mare. Dac imaginaia noastr este ct de ct comun, atunci ai putea viziona urmtorul desen :

V rog observai c ntr-adevr irul ncepe odat cu cana 0, urmat de cana 1 i aa mai departe pn ajunge la cana N. N reprezint ultima can din ir. Numrul de cni utilzate este astfel N + 1 (1 vine de la cana 0, altfel erau doar N). Bun bun, avem cni, dar cum ne ajut asta s vizionm memoria unui calculator ? Ei bine, putem folosi interiorul cnii pentru a ine lucruri. Ce ai zice dac am pune n cni figurile geometrice folosite n exemplul cu maimuica ? Nu ar fi mai palpabile ? Rezultatul ar fi acelai : fiecare corp/figur geometric va comanda o aciune. Dac nu vrem s pstrm corpuri, am putea pstra carneelul folosit de maimuic pentru a numra secundele. n realitate, calculatorul folosete ca i coninut de cni, numere binare. Aceste numere binare sunt, n funcie de tipul de memorie n care sunt stocate, fie interpretate ca i instruciuni, fie ca i informaie de prelucrat. Poate exemplu acesta va mai clarifica puin lucrurile. n orice caz, trecerea de la band la cni prezint urmtoarele beneficii : 1. o can poi s o ii pe cnd o figur geometric e mai greu de delimitat i
grupare de simboluri (litere sau cifre) ce se pune naintea altei grupri de simboluri (n cazul nostru, naintea unui numr) 2 b-ul vine de la binar 3 x-ul vine de la hexazecimal
1

24

2. cnile sunt numerotate ceea ce ne va ajuta mai departe cnd vom face referire la adrese de memorie (numerele de pe ele practic asta simbolizeaz). Revenind. Din punct de vedere tehnic, un calculator cunoate 2 tipuri de memorii: 1. memorie perisabil (se mai numete si volatil) n care sunt depozitate informaiile de stare ale calculatorului (cum a fost numrul de secunde scrise de maimuic pe carneel). Acest tip de informaie se numeste perisabil pentru c ea exist att timp ct calculatorul este pornit. Odat ce calculatorul se stinge, informaia se pierde. 2. memorie neperisabil (sau nevolatil) n care sunt depozitate instruciunile ce urmeaz a fi interpretate i executate de calculator. Echivalentul ei este, ai ghicit, fia de obiecte geometrice ale maimuicii. Evident, ele sunt neperisabile deci nu sunt afectate de nchiderea calculatorului, ceea ce este i de dorit avnd n vedere c nu ne-ar conveni ca de fiecare dat cnd pornim calculatorul s trebuiasc s-i rescriem instruciunile sale ce urmeaz a fi executate. Probabil v ntrebai de ce exist dou tipuri de memorii. Nu ar fi suficient doar una ? Rspunsul este, evident, nu. Motivul l-ai putut vedea cnd am introdus definiia memoriilor nevolatile : este necesar pentru a ine instruciunile/comenzile ce trebuiesc executate. Teoretic, se poate folosi memoria nevolatil pentru a o nlocui pe cea volatil, dar din motive de performan (timpul de lucru cu memoriile nevolatile este muuult mai ridicat dect cel cu memorii volatile), acest lucru nu se realizeaz n practic. Dac ar fi sa transpunem cele 2 tipuri de memorie n cnile noastre, am avea urmtoarele 2 rnduri de cni, fiecare rnd destinat unui tip de memorie :

Observai v rog cum fiecare tip i are cana 0 i cum fiecare tip i are numrul su de cni. Memoria volatil se termin cu cana pe cnd cea nevolatil se termin cu numrul N. N nu trebuie neaprat s fie egal cu , ba din contra : de cele mai multe ori N este mult mai mare dect att din motive de utilitate ct i cost de producie. Aceasta nu este chiar toat povestea. Cnd vom discuta mai aprofundat despre Ale, vom vedea c micro-creieraul1 plcuei mai conine nc un tip de memorie care se afl la limita dintre volatil i nevolatil, iar, poate mai important, vom vedea c exist chiar i o subdivizare a memoriei volatile n regiuni de adrese cu funcii speciale. n continuare, haidei s vedem ce sunt n stare s fac calculatoarele. Vom discuta un pic despre tipurile de instruciuni recunoscute de un calculator.

Ce tiu calculatoarele s fac ?


Bun. Avem memoria, avem i limbajul, i avem i-un scop : dorim s folosim un calculator pentru a nlocui maimuica. Pentru asta, este necesar s cunoatem ce operaii este el capabil s fac respectiv ce tip de instruciuni recunoate.
1

se mai folosete notarea -creiera, creierasauchiarC.Esteposibilsntlniimaimulte astfeldenotaiiprincrulie.

25

Lucrnd cu simboluri binare, majoritatea calculatoarelor pot realiza 4 tipuri de instruciuni : 1. Operaii matematice (adunri, scderi, nmuliri i mpriri) 2. Operaii binare (diferite operaii la nivel de bii) 3. Operaii de date (mutri de date n memorie) 4. Operaii de control (salturi condiionate sau necondiionate n alte regiuni de cod) Aceste operaii elementare sunt suficiente pentru a face un calculator s rezolve orice alt problem pe care o poate rezolva orice alt calculator calculator din aceast lume. Diferena este doar la nivel de vitez i performana cu care o problem este rezolvat. Este uimitor cum inteligena unui calculator poate fi obinut din combinrii propice a unor astfel de instruciuni matematice. Dac nu m credei, avei puintic rbdare cci ne vom convinge i de asta. Instruciunile care controleaz astfel de operaii sunt variate, dar toate sunt scrise n sistem binar aa cum am mai precizat. n aceast idee, am putea lua un calculator care, dac ar ntlni n memorie secvena 0b00110101 0b10110010 (2 octei, observai v rog cum o instruciune poate ocupa mai multe locaii de memorie respectiv mai multe cni n exemplul nostru), ar face, s spunem, o adunare a coninutului cnii 3 din spaiul de memorie volatil cu valoarea ce se gsete n cana 4, iar rezultatul l-ar pune n cana 5. Asta ar fi o variant de interpretare. O alt variant ar fi ca respectiva secven de octei s genereze un salt al secvenei de execuie de la adresa curent X, la adresa Y. O alt interpretare ar lua cele 2 valori i le-ar executa precum 2 instruciuni separate. Una din ele ar pune bitul cu numrul 3 din valoarea ce se gsete n cana 2 pe 1 i ar pune rezultatul napoi n cana 2, iar alta ar spune calculatorului : continu cu urmtoarea instruciune, cci eu nu i cer s faci nimic la instruciunea asta. Dac ne gndim mai bine, secvena respectiv, dac o punem n spaiul de adrese volatile (zona de date), ele se vor traduce n simple valori numerice, necontrolnd calculatorul n niciun fel. Vedei voi, ceea ce vreau s subliniez prin aceast exemplu este faptul c nu exist un vocabular standard ntre calculatoare. Atunci cnd ele sunt fabricate, creatorul lor le fixeaz limbajul ce-l vor recunoate. Dup aceasta, creatorul pune respectivul limbaj la dispoziia celor interesai s cunoasc cum s discute (aciunea poart denumirea de programare1) cu respectivul calculator. Astfel, fiecare main de calcul vine cu un set de instruciuni recunoscute. Toate le au, i Ale le are, dup cum vom vedea. Totui, aceast flexibilitate n a alege secvena de instruciuni recunoscute de un calculator vine cu un dezavantaj enorm : din pricina acestei liberti, practic o secven de instruciuni programate pentru un calculator X nu vor ndeplini acelai comportament pe un alt calculator Y. Dac lum un caz concret : acest fapt evideniaz motivul pentru care o aplicaie de celular nu va merge niciodat pe un PC. Acum c am discutat un pic despre modul n care sunt codificate2 instruciunile, s discutm un pic despre fiecare tip de instruciune n parte. Vom ncepe cu instruciunile de tip operaie matematic.

noiune nou ce semnific aciunea de a scrie instruciuni n spaiul de memorie nevolatil a unui calculator 2 sau atribuite coduri pentru care le garanteaz comportamente specifice calculatorului

26

Operaiile matematice reprezint baza de funcionare a unui calculator, a oricrui calculator. Acest lucru l-a evideniat i Turing cnd a demonstrat lumii c aceste mainrii pot fi de ncredere. Cele 4 operaii de baz, aa cum am amintit mai sus, sunt : adunri, scderi (un caz particular de adunare cu opusul), nmuliri (un caz special de adunare repetat) i mpriri (un caz particular de scderi repetate sau adunri cu opusul repetate). Uimitor! Observai ceva interesant ? Singura operaie matematic pe care o tie ntr-adevr calculatorul este adunarea! Restul sunt variaiuni ale acestei operaii. Haidei s vedem de ce, iar n stilul nostru, vom apela din nou la exemple. Vom porni de la un caz simplu de adunare : 5+3=8 . Nimic special pn aici, dar dac am transforma-o ntr-o scdere ? : 53=2 . Stai un pic. 53=2 nu e totuna cu a scrie 5+(3)=2 ? Ba da, iar asta nseamn adunare cu opusul, practic tot o adunare, dar un pic mai diferit interpretat. Dac mergem mai departe i facem o nmulire : 53=15 este totuna cu 5+5+5=15 sau, am putea afirma c, nmulirea reprezint o succesiune de adunri. n concluzie, i nmulirea o putem rescrie prin operaia de adunare. Dar mprirea ? 5 :3= =1 rest 2 . Ctul 1 poate fi vzut ca rspunsul la ntrebarea de cte ori se poate scdea 3 din 5 unde 2 reprezint numrul final pentru care nu se mai poate realiza scderea. Scderea adunare cu opusul. Sumariznd, un calculator tie s fac doar adunri, restul de operaii sunt variaiuni ale acestei operaii de baz. Desigur, noi avem instruciuni care s le realizeze direct, fr a fi nevoii s le reproducem. Totui, din cauza faptului c nmulirea i mprirea reprezint operaii mai complexe, Ale nu le suport fiind nevoit s le reproduc (prin procedee asemntoare cu cele descrise mai sus). Un caz special de adunare/scdere o reprezint operaia de incrementare/decrementare. Incrementarea unui numr reprezint adugarea la valoarea numrului respectiv a lui 1 i punerea rezultatului napoi la adresa original a acelui numr. Decrementarea are efect contrar incrementrii : scade 1 din valoarea curent a unei adrese i pune rezultatul astfel obinut napoi la adresa respectiv. Din cauza faptului c aceste operaii sunt foarte des utilizate mai ales mpreun cu instruciunile de control pentru a realiza cicluri, majoritatea calculatoarelor au atribuit acestor operaii coduri individuale pentru a putea fi executate distinct. ntrebare-ntrebtoare : ce putem opera matematic ? Ei bine, cel mai simplu rspuns ar fi 2 numere ce se gsesc la 2 adrese din spaiul de memorie volatil, iar rezultatul l vom pune la adresa dat de al 3-lea parametru. Uneori, aa cum vom vedea i la Ale, rezultatul se pune n locul uneia dintre cele 2 adrese de unde s-au luat valorile iniiale. Mai mult, din cauza zonelor speciale n care mparte calculatoraul Ale spaiul su de memorie volatil, vom vedea c respectivele adrese ce intr n componena operaiei sunt supuse unor constrngeri.

5 3

27

Vom mergem mai departe i vom discuta operaiile binare. Acest tip de operaii sunt foarte diversificate i permit modificarea octeilor la nivel elementar de bit. Mai precis, prin operaii binare se pot : Realiza I-uri/SAU-ri/SAU EXCLUSIV-uri logice Operaia de I ia 2 octei i, dup ce se uit la fiecare 8 perechi de bii de pe poziii omoloage1, completeaz un al 3-lea dup urmtorul tabel : Bit i din octet 1 0 0 1 1 Exemplu : Octet 1 Octet 2 0b01010011 0b00110101 Bit i din octet 2 0 1 0 1 I logic 0 0 0 1

Octet Rezultat (I logic) 0b00010001 Pentru a ne obinui cu notaia, dac vrem s scriem faptul c un numr binar c este rezultatul operaiei de I logic aplicat ntre un a binar i un numar b binar vom folosi, aa cum vom vedea i cnd vom scrie aplicaii pe Ale, simbolul & n urmtorul mod : c = a & b. Operaia de SAU logic, pe de alt parte, ia 2 octei i, dup ce se uit la fiecare 8 perechi de bii de pe poziii omoloage, completeaz rezultatul, un al 3-lea, dup urmtorul tabel : Bit i din octet 1 0 0 1 1 Exemplu : Octet 1 Octet 2 Octet Rezultat (SAU logic) 0b01010011 0b00110101 0b01110111 Bit i din octet 2 0 1 0 1 SAU logic 0 1 1 1

Spunem c c este rezultatul SAU-ului logic aplicat ntre a i b folosind urmtoarea notaie : c = a | b.

poziie omoloag = poziie dat de acelai index n ambii octei. De exemplu, o poziie omoloag la index 3 din octeii 0b00001001 i 0b00110100 ar scoate biii 1 i 0, ambii situai pe poziia 3 ncepnd de la 0 numrtoarea din dreapta octetului, aa cum ne-am obinuit

28

Iar operaia logic de SAU EXCLUSIV, ia 2 octei i, dup ce se uit la fiecare 8 perechi de bii de pe poziii omoloage, completeaz rezultatul, un al 3-lea, dup urmtorul tabel : Bit i din octet 1 0 0 1 1 Exemplu : Octet 1 Octet 2 0b01010011 0b00110101 Bit i din octet 2 0 1 0 1 SAU EXCLUSIV logic 0 1 1 0

Octet Rezultat (SAU EX. logic) 0b01100110 Notaie : Octet Rezultat = Octet 1 ^ Octet 2. Cei 2 octei pot fi fie ambii luai din memoria volatil (cu aceleai constrngeri aplicate pentru Ale ca i cele discutate la operaii matematice), fie o valoare luat dintr-o locaie de memorie volatil i cealalt valoare luat dintr-o constant1. De subliniat este faptul c SAUul EXCLUSIV din Ale nu suport aceast ultim modalitate de invocare. Realiza complementarea biilor unui octet Prin complementare se nelege operaia prin care rezult un octet a crui bii sunt inversai2 fa de octetul iniial. Inversarea se face innd cont de tabelul urmtor Bit i COMPLEMENT logic 0 1 Exemplu : Octet Surs Octet Rezultat (Complementat) 0b01010011 0b10101100 1 0

Cu notaia : Octet Rezultat = ~ Octet Surs Ale cunoate 2 tipuri de complementri (complementare simpl i complementare n exces de 2). Noi vom discuta predominant despre complementarea simpl, cealalt fiind un pic mai dificil de neles din punct de vedere matematic. Realiza setri/resetri individuale de bii ntr-un octet Prin setri/resetri se nelege exact asta : capacitatea de a regla fin valorile biilor ntr-un octet.

1 2

valoare fix, care nu se schimb prin inversare se nelege schimbarea unui bit din 0 n 1 i din 1 n 0

29

Exemplu :

0b01010011

0b01010111

0b01010010

Realiza setri/resetri totale de bii ntr-un octet Permite curarea unei valori fie prin punerea tuturor biilor pe 1, fie prin punerea tuturor biilor pe 0. Desigur, operaiile logice pot fi multe i late, dar pentru simplitate, ne vom opri doar la aceste funcii. Partea foarte fain este c, dei nu sunt specificate toate funciile logice (nu avem I NEGAT sau SAU NEGAT, precum i alte cazuri), ele pot fi uor reproduse prin combinri a ceea ce avem. De exemplu, I NEGAT poate fi considerat ca fiind compus dintr-o funcie a crei valoare rezultant intr, la rndul ei, ntr-o funcie de complementare, asemenea celei discutate anterior. Tabelul de operare astfel asociat funciei este : Bit i din octet 1 0 0 1 Bit i din I logic octet 2 0 1 0 0 0 0 I NEGAT logic 1 1 1

1 1 1 0 , iar dac aplicm aceste cunotine pe un exemplu, vom avea : Octet 1 Octet 2 0b01010011 0b00110101

Octet Rezultat (I NEGAT logic) 0b11101110 Desigur, acest principiu se poate aplica i la funcia SAU NEGAT precum i la alte funcii mai complexe. nainte de a merge mai departe i a discuta alte operaii elementare recunoscute de un calculator, a dori s discutm un pic despre o notaie simplificatoare pentru funciile boolene1. Notaia la care voi face referire n rndurile ce urmeaz este folosit de cei ce construiesc calculatoarele i consider c este bine s o cunoatem. Nu de alta, dar s-ar putea s le ntlnii n alte locaii prin materialele studiate de voi i e bine s nu v speriai. Notaia conine elemente grafice i ajut la condensarea2 funciei n sine. Desigur, am putea s ne uitm dup tabelul de ieire asociat unei funcii logice, dar uneori asta poate fi dificil de realizat, mai ales dac funciile logice se compun (n maniera celei discutate mai sus). n aceast idee, vom pleca de la observaia c fiecare tabel de funcie elementar scoate o
o alt denumire acordat funciilor logice (algebra boolean folosete operanzi doar din mulimea {adevrat, fals} sau, tradus n simboluri din baza 2 : {1, 0}) 2 ilustrarea ntr-o manier ct mai scurt
1

30

valoare binar care depinde de o combinaie de 2 valori prezente. Practic ceea ce va urma s realizm va fi o variant cioplit n urmtorul bloc grafic :

Unde bit intrare 1 i bit intrare 2 sunt cei 2 bii care dicteaz valoarea lui bit rezultat dup ce trec prin funcie logic. Practic, lucrnd cu bii, un astfel de bloc este echivalentul unui singur rnd din orice tabel logic evideniat mai sus, mai puin la cel n care se introduce COMPLEMENTAREA logic. i acum s trecem la particularizri. Unele funcii logice, vei vedea, vor avea 2 reprezentri grafice. Le desenm pe toate pentru a vi le face cunoscute atunci cnd le ntlnii i le folosim:

Acestea ar fi funciile discutate de noi. Noi vom prefera reprezentarea american a simbolurilor pentru c, dei nu suntem americani, vom vedea c ele sunt cele mai utilizate. Desigur c mai exist i alte tipuri de elemente grafice asociate altor funcii, dar pentru ce le vom folosi noi, sunt suficiente. Observai v rog cum complementul logic nu primete dect o singur valoare logic spre deosebire de dou, cte vedem la celelalte elemente. Acest lucru este i normal dac ne uitm la tabelul complementului logic unde observm c ntradevr rezultatul operaiei depinde doar de un singur bit. nchei aceast categorie prin a sublinia faptul c elementele logice reprezentate grafic sunt foarte mult folosite, aa cum spuneam, n construcia de componente electronice precum i a creieraelor electronice precum cel prezent pe Ale. Ele pot surprinde, ntr-o manier simplificatoare, eficient, dar mai ales intuitiv, modul de operare al acestora. Pentru a arta

31

un exemplu de compunere a operaiilor logice, vom ncerca s construim, din elementele introduse de noi, o funcie I NEGAT a crei tabel de definiie l avem prezentat mai sus. Descrierea ne spune c o funcie logic I NEGAT se poate realiza prin alturarea a unei funcii logice I lng o funcie logic COMPLEMENT. Rezultatul grafic s-ar prezenta n felul urmtor :

V las pe voi s vedei c ntr-adevr construcia se comport ca i un I NEGAT / COMPLEMENTAT dnd valori la intrarea simbolului i urmrind tabelul de rezultate la fiecare ieire a lui pentru a-l aplica, dup caz, n continuare la urmtorul element din serie.

ntrebri / Exerciii: 1. ncercai s construii un SAU NEGAT. Cum demonstrai c soluia dumneavoastr este una corect ? 2. Ce credei c face urmtoarea construcie ? :

Continum discuia cu instruciunile care lucrez direct cu memoria i anume : operaiile de date. Prin operaii de date nelegem operaii de mutare a informaiei de la o locaie de memorie volatil n alt locaie. n aceast idee, avem cteva operaii elementare : 1. posibilitatea de a muta data de la o locaie i a suprascrie informaia aflat n alt locaie din memorie (poart denumirea de mutare de informaie), 2. posibilitatea de a transfera date nspre/dinspre mediul extern n calculator, 3. posibilitatea de a ncrca date n memoria volatil de la adrese ce se afl n memoria nevolatil, 4. posibilitatea de a pune rezultate oriunde n memoria volatil i 5. posibilitatea de a mpinge/scoate date dintr-o noiune ce poart denumirea de stiv i care se afl situat n spaiul memoriei volatile. Desigur c aceste operaii de baz pot fi specializate s confere programatorului mai mult flexibilitate pentru aplicaii, dar n final, ele se comport asemntor. S le lum n ordine i s le discutm. Mutarea informaiei este o operaie foarte des utilizat de ctre programatori. Prin aceast aciune, informaia inut n cni sau, mai direct, n memoria volatil ajunge s se multiplice pentru a nu se pierde. Un exemplu de utilizare al mutrii ar putea fi considerat urmtorul caz : dorim s vedem dac numrul care este scris pe un bileel i se afl n cana 2 este par sau impar, dar vrem ca la sfritul operaiei, cum este de cele mai multe ori cazul, s nu pierdem valoarea iniial. Am putea gndi o succesiune de pai care s realizeze exact acest lucru : 1. Mutm informaia pe care o avem din cana 2, multiplicnd-o conform celor discutate n cana 3. Acum, valoare se afl att n cana 2 ct i n cana 3.

32

2. Verificm dac informaia din cana 2 este strict mai mic dect 2 3. Dac este mai mare sau egal cu 2, aplicm la informaia din cana 2 o scdere cu 2 i srim la verificarea de la punctul 2 (cam muli de 2 ntr-o explicaie! :-) ) 4. Dac nu este mai mare, verificm dac este 0 (caz n care numrul era par) sau dac a rmas 1 (caz n care numrul iniial era impar). 5. Dup ce am stabilit paritatea, pentru a relua informaia, mutm valoarea inut n cana 3 (care era copia iniial a informaiei) napoi n cana 2, astfel garantnd c starea iniial a fost restabilit Grafic (c e mai frumos vizual, nu ?) am putea ilustra acest procedeu n felul urmtor1 :

pe parcursul acestei crulii v vei mai ntlni cu astfel de imagini. Ele sunt simplu de interpretat : considerai c timpul curge de sus n jos astfel c regiunea de la baza imaginii se ntmpl ultima pe axa timpului. Grafic, elementele prezente au urmtoarea semnificaie : dreptunghiul (cu margini rotunde sau nu) : element n care se realizeaz aciunea scris n el, rombul : element de decizie prin care, n funcie de o condiie, se poate avansa pe una din cele 2 ci de adevr i sgeata : element ce leag 2 blocuri (fie ele romburi, dreptunghiuri sau orice combinaie de cele 2).
1

33

Fiind att de important, majoritatea calculatoarelor actuale conin aceast facilitate. Ale, dup cum vom vedea, nu face excepie. Continum posibilitatea de a transfera date dinspre/nspre mediul nconjurtor reprezint modalitatea prin care orice calculator i face cunoscut starea sa intern ctre lumea nconjurtoare sau, invers, modalitatea prin care calculatorul poate citi ce se ntmpl n mediul n care funcioneaz. Calculatoarele de birou, laptopurile i telefoanele inteligente i manifest aceast stare printr-un ecran mai mare sau mai mic. i Ale are un ecrnel dac i putem spune aa (mai corect ar fi o fie de LEDuri1), prin care vom putea interaciona cu ea. Practic, dup cum vom vedea, memoria volatil este la rndul ei fragmentat n mai multe zone importante. Una din aceste zone permite opiuni de control al exteriorului. Aceast facilitate este aa de des folosit, poate din cauza faptului c este singura modalitate prin care se poate comunica cu universul exterior, nct i merit o seciune de discuii a ei. n acest context este suficient s tim c lumea exterioar poate fi citit/scris sau, mai complet: controlat prin operaii de mutare a unor valori n zone speciale de memorie care dirijeaz aceste capaciti. Pentru mai multe detalii, permitei-mi s amn un pic discuia. Urmtoarea n list : posibilitatea de a ncrca date n memoria volatil din memoria nevolatil. Prin aceast capacitate, se poate lucra cu date predefinite. Mai inei minte proprietatea principal a memoriei nevolatile ? : se pierde odat ce calculatorul se nchide. Pi dac aa se ntmpl lucrurile atunci cum am putea s scriem o secven prin care am calcula aria unui cerc, de pild? Suprafaa unui disc este dat de relaia Suprafa=razraz unde este 3.14159. Cum am putea ca, de fiecare dat, s calculm i s pstrm pentru a o folosi n calculul suprafeei ? Rspunsul este simplu : mai greu, dar aceast metod de manipulare a datelor ne permite s nu o calculm, ci s o lum direct de la o adres predefinit din memoria nevolatil (acea memorie care nu se distruge odat cu pierderea energiei, mai inei minte ?) fiindu-ne calculat i salvat atunci cnd scriem aplicaia. n felul acesta ctigm att timp, pentru c nu mai suntem nevoii s calculm manual valoarea lui , dar i memorie pentru instruciunile necesare calculului lui . Posibilitatea de a pune date oriunde n memoria volatil este ct se poate de sugestiv. Ne-am fi gndit c ar fi ciudat s nu avem acces la adrese de memorie. Dac nu am avea acces, atunci de ce exist fizic, nc de la nceput ? Nu ar fi fost mai bine s nu se fi chinuit creatorul calculatorului s pun cnie care nu pot fi accesate ? Trebuie s m credei pe cuvnt cnd v spun c aa ceva se poate ntmpla : s se implementeze spaii de memorie (cnie) care, dei pot fi adresate, ele nu pot fi citite sau,
1

LED = Light Emitting Diode (din englez, se citete lait emiting daioud) i reprezint nite componente electrice micue care au proprietatea de a lumina dac sunt conectate la tensiune (baterie sau altceva) - beculee

34

invers, nu pot fi scrise sau, n cel mai ciudat caz, ele nu-i pstreaz informaia pus n ele dei au fost mereu conectate la tensiune. Acest concept merge mn n mn cu zonele de control ale perifericelor1 discutate mai sus. Ca i exemplu simplu, gndii-v c un astfel de periferic ce se poate controla dintr-o secven de cod este un ceas. Ceasul incrementeaz la fiecare secund o valoare ce se afl situat ntr-o anumit cni din memorie. Dm drumul la ceas i, atunci cnd dorim s citim timpul trecut de la pornire, efectiv ne uitm la valoarea cniei respective situate n spaiul de memorie volatil. Este normal ca la fiecare citire s avem o alt valoare chiar dac nu noi modificm direct valoarea ce se gsete la adresa respectiv. Urmtoarea operaie de date ce este implementat n majoritatea calculatoarelor actuale ne permite s facem ceva ce ne-am ntrebat dac este posibil nc de la introducerea memoriilor : ne permite s salvm informaia din memoria volatil ntr-o zon nevolatil pentru a putea fi reluat la urmtoarea pornire a calculatorului sau pentru a fi pur i simplu salvat astfel nct s poat fi prelucrat ulterior de aplicaii exterioare. Nu e tare asta ? Practic, am putea scrie o secven de instruciuni pentru calculator care ar calcula un rezultat ce necesit mult timp de aflat i, pentru a elimina pericolul de incendiu, l-am nchide seara, iar dimineaa, cnd l-am reporni, calculatorul ar continua de unde a rmas dei nu a fost bgat n priz peste noapte. Personal, vd aceast facilitate foarte util. Cu att mai util cu ct, prin acelai procedeu, o aplicaie poate s scrie ea nsi instruciuni n spaiul de memorie nevolatil, instruciuni care mai apoi vor fi interpretate i executate de calculator. Cu alte cuvinte, exist posibilitatea ca o aplicaie ce se execut pe un calculator s-i modifice singur comportamentul. Spunem aceste lucruri pentru c i Ale le poate realiza. Ultima i probabil cea mai important utilitate a operaiilor cu date o reprezint ceea ce se numete stiva unui calculator. Dicionarul EXplicativ al limbi romne (DEX) d urmtoarea definiie pentru noiunea de stiv : STV, stive, s. f = Mulime de obiecte de acelai fel (i cu aceleai dimensiuni), aezate ordonat unele peste altele, pentru a forma o grmad. Corect i din punctul de vedere al unui calculator. Practic, o stiv ar fi asemntoare cu un teanc de gogoi :

Dac nlocuim gogoile cu, n cazul nostru, cni numerotate consecutiv asemeni adreselor de memorie obinem stiva unui calculator. Pentru stiva unui calculator dou operaii ne sunt deosebit de utile :
reprezint dispozitive sau module conectate din exterior. Uneori se refer chiar la module interne ale C-ului.
1

35

punerea de valori n vrful stivei (mai poart denumirea de mpingere sau, n englez, push) i scoaterea de valori din vrful stivei (n englez, pop). Grafic, operaiile posibile se deruleaz n felul urmtor :
Vrful stivei

Probabil v ntrebai, pe bun merit, de ce nu am putea folosi accesul direct la memorie pentru a obine acelai efect ? Dei am putea obine, cu ceva efort, acelai efect : pstrarea de valori n spaiul memoriei volatile, stiva vine cu un avantaj. Acesta const n faptul c nu trebuie s cunoatem adresa unde vom depozita valoarea dorit n memorie. i spunem mpinge 23 i ea automat va face ce tie mai bine : va pune n vrful su valoarea 23. Dac dup aceea vom vrea valoarea din vrf vom spune scoate i vom obine valoarea. Este chiar aa de simplu! Dac ar fi s folosim accesul direct la memoria volatil, ar trebui ca, pe lng valoarea ce o dorim depozitat, s tim i poziia sa n memorie (numrul cnii) n care o vom depozita. Aceast btaie de cap este uneori prea mare i de aceea se dorete a fi evitat. Principiul este simplu : cu ct mai puin btaie de cap, cu att mai bine! Un ultim punct de discuie nainte de a nchide i aceast categorie de operaii o constituie modul n care stiva este poziionat n memorie. Imaginea de sus nu este ntru totul corect. De cele mai multe ori, calculatoarele au, la pornire, vrful stivei situat pe ultima poziie a zonei de memorie volatil. Grafic, aceast fraz s-ar traduce n felul urmtor : Dar, stai un pic dac stiva este situat n limita superioar a spaiului de adrese, atunci cum crete ea cnd adugm un element ? Ei bine, ea nu crete cnd adugm un element, ea descrete! Desigur, dac considerm c a descrete este tot una cu a crete n jos atunci am neles cum funcioenaz o stiv ntrun calculator. Acestea fiind spuse, vom discuta i ultima categorie de instruciuni i anume operaii de control. Operaiile de control sunt de departe cele mai interesante. Mai inei minte maimuica noastr ? Cum putea ea sri peste instruciuni atunci cnd ntlnea un anumit simbol ? Ei

36

bine, acest tip de comportament l putem ntlni i la simbolurile recunoscute de orice calculator actual. Operaiile de control reprezint o modalitate de a dirija execuia unei succesiuni de instruciuni ntr-o alt regiune, aflat la o alt adres. Acest concept este foarte important i interesant. Practic, din cauza acestui fapt putem realiza aciuni pe baza unor informaii urmrite i putem realiza ceea ce se numesc ciclii controlai n aplicaii. Gndii-v dac am dispune de un calculator pe care l-am nva s numere care este valoarea total a monezilor ce le avem la noi. Dac am scrie instruciunile necesare ca fiind o succesiune de comenzi, de unde am ti cnd s ne oprim ? Adic, desigur c am putea s gndim o succesiune de aciuni precum : 1. Uit-te la moned, citete valoarea i adaug-o la suma deja existent 2. Din nou : Uit-te la moned, citete valoarea i adaug-o la suma deja existent 3. etc. Este clar : nu putem ti cte astfel de comenzi ar trebui s scriem dac numrul de monezi nu este mereu acelai. Adic dac am ti sigur c respectivul calculator ar trebui s observe mereu 5 monezi atunci am avea 5 astfel de instruciuni, dar este evident c uneori vom dori s numrm mai multe monezi, alteori, dimpotriv, mai puine. Mai mult : dac memoria nevolatil (cea care stocheaz instruciunile) este fix (i chiar este) atunci, pe msur ce am avea mai multe monezi de numrat, practic numrul instruciunilor necesare realizrii sarcinii ar crete. Gndii-v cte instruciuni ar fi necesare pentru a numra 1000 de monede, dar 100000 ? Suma este ridicol de avut dei exist persoane care dein, din varii motive, aceste cantiti de monede. Este clar : trebuie s existe o metod mai eficient de utilizat. Aici intr pe scen salturile i, mai important, salturile condiionate. S trecem direct la exemplu i s vedem cum ar influena acest nou concept soluia noastr. Salturile ne permit s avem urmtoarea secven de pai n programul ce l scriem : 1. Uit-te la moned, citete valoarea i adaug-o la suma deja existent 2. Dac nu mai sunt monezi atunci ncheie numrarea i arat rezultatul altfel continu execuia cu punctul 1 i asta este tot! Nu mai avem nevoie de 1000 de instruciuni pentru 1000 de monezi, ci putem utiliza un numr mult mai redus. n felul acesta, nu numai c ne facem viaa mai uoar ca programatori de calculatoare, dar i consumul de memorie este redus ca s nu mai vorbim de flexibilitatea abordrii : numrul de monezi ce pot fi inspectate este nelimitat folosind acelai set de instruciuni. Foarte tare, nu gsii ? Desigur, exemplul nostru ilustreaz ideea de salt ce depinde de o anumit condiie (de unde vine i denumirea de salt condiionat), dar pot exista i instruciuni de salt care sunt realizate neinnd cont de niciun element de control. Dac v este mai uor, gndii-v la salturile necondiionate (aa se numesc aceste instruciuni) precum un caz praticular de salturi condiionate a cror condiie este mereu adevrat. Nu mai are rost s spun c toate calculatoarelor moderne (nu pot s m gndesc la unul ce nu respect aceast condiie) suport acest tip de instruciuni. De fapt, a putea afirma cu ncredere c nu cunosc calculataore care s nu recunoasc, la un anumit nivel sau altul (poate unele nu au instruciuni de nmulire, dar acest lucru nu este o problem aa cum am vzut mai sus), aceste clase de instruciuni.

37

Dac ceea ce am afirmat eu este adevrat i tind s cred c aa este, atunci asta ne spune un lucru foarte interesant despre lumea calculatoarelor n care trim : ne spune faptul c orice niruire de instruciuni ce sunt gndite pe un calculator, i vor gsi echivalentul n comportament pe un alt calculator chiar dac, de cele mai multe ori, o instruciune de pe o familie de calculatoare nu este neleas la fel pe o alt familie. Aceast informaie ne ajut s nelegem de ce Ale nu este aa de diferit pe ct pare fa de friorul su mai mare, calculatorul prin care scriu aceste rnduri sau prin care i dictai lui Ale ce s fac. Rezumnd : lucrurile acestea sunt suficient de simple pentru a fi nelese, dar i suficient de puternice pentru a dinui de la ceas la telefon i de la Ale la calculator. Toate sunt mai mult sau mai puin la fel! Revenind, aceast clas de comenzi nchide seciunea intuitiv dedicat lor. n continuare vom lua puterea ce ne-o ofer aceste comenzi i vom vedea modalitile prin care ele afecteaz lumea n care exist i, n proces, reuesc s ne modeleze vieile.

Universul lor n universul nostru ...


Bun bun, am urmrit cum un calculator poate s citeasc simboluri dintr-o resurs proprie numit memorie i poate s interpreteze respectivele simboluri ca fiind comenzi ce le execut fr s comenteze i cu devotament total, dar cum pot nite operaii matematice a cror desfurare nici mcar nu o putem urmri s fie n stare s modeleze lumea nconjurtoare ? La urma urmei, ce utilitate ar avea un calculator dac nu am putea interaciona cu el ? Nu prea mare cu siguran maimuica noastr ar dormi linitit tiind c nu ar avea cine s-i ia locul. Probabil c nu este un oc pentru muli faptul c lucrurile nu stau chiar aa. Calculatorul poate s interacioneze cu lumea n care trim i n care triete, de acest lucru putem fi siguri altfel el nu ar fi cunoscut popularitatea pe care o are n zilele noastre. Modalitile sunt multe : calculatoarele de uz general (ca i cel pe care-l avei i dumneavoastr) au monitoare prin care se poate urmri starea lor intern i au tastaturi prin care se poate comunica cu ele. Pe lng aceste 2 elemente mai evidente, calculatoarele personale au i modaliti de a emite sunete (placa de sunet se numete componenta ce realizeaz acest lucru), de a comunica cu alte calculatoare din aceeai familie (prin ceea ce se numete plac de reea), de a comunica cu alte dispozitive precum memorii externe (le cunoatem sub denumirea de flash-uri), MP3 playere, FAX-uri, etc. Ba chiar mai mult : unele calculatoare pot chiar s vad mediul n care exist (prin camere web) i s-l aud prin microfoane. Aceste capaciti sunt majoritar prezente la calculatoarele personale. S nu uitm c i Ale este un calculatora. Nu trebuie s cunoti prea multe s-i dai seama c plcua dispune de o serie de butonae care pot juca rolul de tastatur i nite LEDuri care poart rolul de monitor. Pe lng aceste operaii simple, dar deloc neinteresante mai ales la dimensiunea la care se prezint Ale, plcua ce o deinei poate s fac i lucruri mai puin obinuite dintre care amintesc : capacitatea de a vedea i capacitatea de a citi temperatura din jur, dar despre toate aceste vom vorbi pe ndelete la momentul oportun.

38

A fost i este clar : calculatoarele interacioneaz cu spaiul n care triesc i trim. Dar cum pot s fac ele mai exact acest lucru ? Cum pot operaii precum 2 + 5 s aprind un becule sau, mai complicat, s trag o linie pe ecran sau s deseneze un cerc ? Ei bine, nu prea pot, sau mai bine spus : nu prea pot de unele singure prin ceea ce am aflat noi pn acuma despre calculatoare, dar exist o soluie, aa cum exist o soluie pentru orice i ea este dat, n aceast situaie, de componentele externe!. Ce a-i spune dac i-am da calculatorului componente exterioare prin care s fac lucrul acesta ? Aceste componente externe sunt grupate n module1 cu funcii precise. Aceste module sunt cele controlate de ctre operaii simple matematice cu rezultatul cunoscut. Haidei s urmrim gndirea aa cum ne face nou plcere mai mult i anume prin desene. Pn acum calculator de care am nvat noi nu a tiut de mediul exterior. Aceast situaie o putem cel mai bine surprinde prin urmtoarea imagine :

Aveam o memorie din care erau culese instruciunile pe care calculatorul le citea, le nelegea i le executa urmnd ca, dup caz, s returneze rezultatul care era nmagazinat n memorie i tot aa. Cum rezolvm problema cu mediul ? Cum majoritatea calculatoarelor au o modalitate prin care sunt introduse i culese rezultatele de ctre un utilizator (am vzut asta la exemplul cu calculatoarele personale), haidei s introducem n diagrama noastr exact acest lucru : nite module externe prin care se poate comunica cu un calculator. Astfel, noul desen l-am putea ilustra n liniile ce urmeaz :

Practic modulele ar fi nite grupri de elemente care asigur o funcionalitate bine precizat creieraului electronic. Dar, stai un pic modulele sunt legate direct la creieraul electronic n aceeai manier n care este legat i memoria ? Rspunsul este cam da, dar dac este aa atunci asta nu nseamn c avem instruciuni care le controleaz la fel cum avem instruciuni care acioneaz asupra memoriei ? Cu alte cuvinte am putea s avem urmtoarea secven de instruciuni mpreun cu efectele descrise ? : 1. Verific dac tasta cu etichet 1 este apsat a. Dac este apsat atunci afieaz pe ecran (sau ce modalitate de afiare avem : LEDuri, monitor, etc.) valoarea 1 b. Dac nu este apsat tasta respectiv, atunci verific dac tasta cu etichet 2 este apsat i. Dac este apsat atunci afieaz pe ecran valoarea 2 ii. i aa mai departe
1

grupare care are un rol bine stabilit ntr-un sistem electric sau ne-electric

39

Spre frumuseea lucrurilor inginereti, rspunsul este da! Se poate i chiar se utilizeaz aceast tehnic n care instruciunile din memorie pot controla comportamentul modulelor externe. Dar cum pot face asta? Adic ultima noastr imagine arat 2 astfel de module, dar ele pot fi mult mai multe. Am putea avea nc un modul de temperatur i un modul de ceas (care s ne contorizeze timpul), iar lista poate continua. Cum poate un astfel de creiera electronic s tie cu ce tip de modul comunic la un moment dat ? Exist instruciuni unice pentru comunicarea cu fiecare modul n parte ? Evident, dac ne gndim aa, atunci sumedenia de posibiliti de a aduga funcionaliti creieraelor ne-ar fora s adugm un numr la fel de mare de instruciuni. Fiecare modul cu instruciunea sa. Nu aa ceva nu este posibil. Adic ar fi posibil, dar gndii-v ce btaia de cap ar avea cei ce creeaz calculatoare dac ar trebui s se gndeasc s adauge instruciuni particulare pentru toate combinaiile de module externe ce le-ar putea ntlni pe parcursul existenei sale. Mai ru ar fi i dac ne-am gndi c el ar trebui s se gndeasc s adauge instruciuni nu numai pentru modulele care exist deja, dar i pentru modulele care vor veni. Imposibil! Aa ceva este de neacceptat fizic, dar mai ales economic. n schimb, modul abordat de control este altul. n funcie de caz, exist 2 soluii : 1. Se poate merge pe convenie, iar cnd spun asta m refer la un mod de comunicare ntre calculator i modulul extern prin care calculatorul, n funcie de specificaiile modulului pe care le cunoate, trimite spre modul exact secvena de bii pentru a obine efectul dorit. Poate prea mult vorbrie nu este n regul. Haidei s lum un exemplu : Vom considera c avem un modul de 8 butonae conectat la un calculator. Cel ce produce modulul ne spune c pentru a citi starea unui anumit buton trebuie s trimitem secvena 0b11001100 urmat de 0b00000001 pentru a verifica butonul 1 sau 0b00000010 pentru butonul 2, 0b00000011 : butonul 3 i aa mai departe. Astfel, dac dorim s verificm starea butonului 4, nu facem dect s trimitem spre modul secvena 0b11001100 0b00000100. Rezultatul, s spunem c-l aflm imediat dup secven de comand i poate fi 0b00000001 pentru apsat sau 0b00000000 pentru neapsat. Informaiile sunt trimise/primite prin instruciuni de date. Tocmai ce am discutat despre ele n paragraful anterior, deci nu mai relum discuia. 2. n zilele noastre n care modulele sunt construite foarte apropiate de creierul calculatorului, poate chiar pe aceeai component fizic (cip), abordarea este diferit : interpreteaz unele regiuni din memorie ca fiind cuvinte de comand pentru modulele respective. Ale fiind de ultim generaie, folosete acest principiu. S lum un exemplu demonstrativ : s considerm acelai exemplu cu modulul de taste sub aceast viziune. n aceast nou configuraie, starea tuturor celor 8 taste ar putea fi citit oricnd dintr-o locaie de memorie cu rol obinuit. S considerm c respectiva adres ar fi 0x05. Citind octetul ce se afl la acea adres am putea obine urmtoarea valoare : 0b00110010. Dac considerm c fiecare tast are un bit asociat n acest octet cu valoarea 1 dac este apsat i 0 dac nu este apsata, atunci am putea trage concluzia c la momentul obinerii valorii respective, singurele butoane apsate au fost cele numerotate cu 2, 5 i 6. Cumva, aceast modalitate de lucru este mai avantajoas dect cea enunat anterior, iar dac capsula care gzduiete creieraul are un numr redus de pini1 cu modulele
1

pinul reprezint un contact electric prin care se poate comunica cu logica din circuit. n crulia de fa, vom mai folosi denumirea de picioru sau terminal/terminal electric toate avnd acelai neles

40

importante nglobate intern, atunci aceast abordare este cea mai potrivit. Creieraul lui Ale are doar 8 pini i, dup cum vom vedea, are multe module interioare pe care le putem folosi, deci este ndreptit s adopte aceast metod. Gata tim suficient despre calculatoare pentru a nlocui n sfrit maimuica noastr care, ntre timp s-a i plictisit de meseria pe care o avuse i oricum se gndea la o carier de profesor de matematic la o coal eminent din provincie. Maimuica a plecat, calculatorul a ajuns! nainte de a continua cu treburi mai serioase, s sumarizm ceea ce am aflat despre calculatoare la modul general : 1. calculatoarele sunt sclavii ideali : dac sunt nvai ce s fac, o vor face fr oprire, fr a cere mriri de salariu i fr a se plnge, 2. memoriile sunt elementele externe care conin att instruciuni ce pot fi executate de ctre creierul calculatorului ct i informaii utile rezultate n urma acestor operaii, 3. instruciunile sunt de mai multe feluri, dar, fundamental, ele se pot reduce la cteva instruciuni unice i 4. mediul exterior poate fi citit i modificat de ctre calculatoare prin intermediul modulelor externe. i, n mare, asta este tot. Acestea sunt uneltele de baz cu care vom porni n a nelege lumea calculatoarelor i n a nelege plcua Ale. Ale, am vorbit att de mult de ea, dar niciodat despre ea. A sosit timpul s vedem din ce este Ale cu adevrat alctuit

Ale intr pe scen


Dup atta teorie, ne bucurm s ncepem n sfrit discuia despre plcua alturi de care a venit aceast crulie. Dei componentele care sunt prezente pe ea pot fi intimidante, vreau s v asigur c nu este deloc aa. Regiunile de piese prezente pe plcu se pot mpri n module care s-ar desena dup cum urmeaz :

S le discutm n ordine i vom ncepe cu cel mai simplu modul: ochiorul! Sun frumos i mic, pentru c este frumos i mic. Practic, prin intermediul lui, Ale poate s citeasc gradul de iluminare prezent n exterior. Cnd spun grad de iluminare nu m refer la imagini complete aa cum suntem obinuii la camerele de filmat/fotografiat clasice. Gradul de iluminare se refer la cantitate de lumin care cade pe suprafaa sa. Practic, n

41

funcie de aceast cantitate, vom putea folosi Ale s citim diferite valori ale luminii din lumea nconjurtoare. Dac vrei s vedei cum arat acest ochior pe plcu, cutai o component ce arat cam aa :

Pentru cultura dumneavoastr general, principiul de funcionare al modulului este unul simplu i-l vom ilustra n continuare. Dac nu v intereseaz acest aspect, putei fr nicio problem s srii aceste explicaii. Pentru cei ce a-i rmas: revenind ... Cantitatea de lumin ce cade pe element influeneaz rezistena sa electric. Nu am mai discutat pn acum, dar considerai rezistena electric ca fiind proprietatea unui element de a se opune trecerii curentului electric prin el. Gndii-v la o eav prin care curge ap. Din cauza dimensiunii fixe a evii, nu poate s curg prin eav dect o anumit cantitate de ap. Spunem n acest caz c respectiva eav are o rezisten la cantitatea de ap ce trece prin ea : cu ct este mai mic eava, cu att este mai mare rezistena i invers, cu ct este mai mare eava, cu att mai mult cantitate de ap va trece prin ea, rezistena fiind una mic. n acela fel exist componente care se numesc rezistene electrice i au proprietatea de a se opune trecerii curentului electric prin ele, diminundu-l. Revenind cantitate de lumin ce cade pe fotoelement (ochior) influeneaz rezistena electric a elementului n felul urmtor : o cantitate redus de lumin conduce la o rezisten mai mare a elementului pe cnd o cantitate mai mare de lumin conduce la o rezisten mai mic a elementului. Observai v rog cum, lumina controleaz o serie de parametri electrici. Noi nu trebuie dect s citim respectivii parametri ca s aproximm cantitatea de lumin din jur. Acesta este principiul de baz al ochiorului. Desigur, creieraul se ocup de citirea respectivului parametru, dar el nu citete direct curentul (creieraelor le este mai greu s lucreze cu astfel de parametrii). n schimb lucreaz foarte bine cu tensiuni, iar trecerea din cureni n tensiuni tiindu-se rezistena se face foarte simplu folosind legea btrnului Ohm1 : U=I R unde am notat cu U = tensiunea, I = curentul i R = rezistena . Dac mai lum faptul c fotoelementul este pus n serie2 cu o rezisten formnd ceea ce proiectanii de circuite electrice numesc divizor de tensiune3 (vezi figura ce urmeaz), atunci tensiunea ce este citit de creiera este dat de relaia: U rezultat =U alimentare

Rezisten2 . Rezisten2+ Rezisten1

1 2

mai multe detalii gsii pe internet aici : http://ro.wikipedia.org/wiki/Legea_lui_Ohm una dup alta 3 nite explicaii foarte bune privind divizorul de tensiune le putei gsi aici : http://www.circuiteelectrice.ro/curent-continuu/legile-lui-kirchhoff/circuite-divizoare-de-tensiune

42

Unde, pentru Ale, am stabilit c


2

U alimentare (tensiune intrare) = 5 V1,


3

Rezisten1 (R1) =

1.5k , Rezisten2 (R2) este dat de fotoelement cu 1M la ntuneric i foarte foarte mic la lumin. Creieraul citete tensiunea dat de U rezultat (tensiune divizat) i cu asta, basta. Mai mult lumin nseamn o tensiune rezultat mai joas (R2 scade, R1 este constant tensiune divizat scade) pe cnd mai puin cantitate de lumin se traduce n tensiune rezultat mai mare (R2 este foarte mare, R1 este constant tensiune divizat crete). Modalitatea prin care creieraul de pe Ale poate s citeasc printr-o secven de instruciuni lumina o vom discuta un pic mai ncolo. Deocamdat mergem mai departe i discutm despre modulul de resetare. Modulul de reset se rezum dintr-un simplu butona care, atunci cnd este apsat, reseteaz creieraul i respectiv contorul de instruciuni. n felul acesta, dac comenzile ce le scriem pentru Ale nu fac ceea ce ne propunem, putem oricnd s apsm butonul pentru a relua de la nceput instruciunile i a reurmri execuia. Pentru a localiza respectivul butona, cutai urmtoarea component pe plcu :

Vei gsi 9 astfel de componente. Cel mai izolat este butonul de resetare, iar restul de 8 sunt parte a modulului de mini-tastatur pe care-l vom discuta n urmtoarele rnduri. Modulul de mini-tastatur este alctuit din 8 butoane care ne permit s comunicm cu Ale i cu aplicaiile care le vom scrie pentru ea. Datorit creieraului ales pentru plcu, cele 8 butonae nu au putut fi citite direct (nedispunnd de suficiente terminale electrice). Ele a trebuit s fie conectate la o component extern auxiliar care permitea citirea strii butonaelor printr-un numr redus de piciorue. O astfel de component poart denumirea
1
2

V = voli, unitatea de msur pentru tensiune se citee : 1 virgul 5 chilo omi i este tot una cu 1500 de omi, chilo(K) fiind un multiplu (1k = 1000), iar omi (ohmi, scris corect) reprezint unitatea de msur pentru rezisten 3 se citee : 1 mega om i este tot una cu 1000 de chilo omi, mega(M) fiind un multiplu (1M = 1000K=1000000)

43

de registru de deplasare cu 8 intrri, una pentru fiecare buton, i 3 ieiri care merg spre creiera. Un registru de deplasare cu ncrcare paralel i ieire serial asemeni celui folosit de Ale este o component care permite cuplarea mai multor componente (asta nseamn conceptul de paralel) i citirea lor pe mai puine terminale (latura serial a definiiei). Dac cele 8 intrri e clar unde merg (la butoane), mai puin evident este rolul celor 3 terminale care leag componenta de creiera. S le lum n ordine i s ne facem o intuiie asupra a ceea ce fac ele : 1. un terminal prin care creieraul atenioneaz componenta c urmeaz s i se cear starea butoanelor i c ar trebui s ncarce valoarea lor ateptnd semnalul de trimitere. n acest sens, o alt denumire folosit pentru terminal este aceea de terminal de ncarcare. 2. un pin prin care creieraul cere pe rnd, prin tranziii de tensiuni aplicate 0 5 Voli (care pot fi considerate valori logice dac este s interpretm 5 Voli ca fiind 1 logc i o Voli ca fiind 0 logic), starea butoanelor n mod consecutiv. Din pricina acestui rol, terminalul se mai numete i terminal de ceas. Respectivele tranziii ncep, de regul, imediat dup ce s-a realizat atenionarea componentei de ctre creiera i 3. un picioru prin care creieraul primete starea butonului curent a crei poziie este dat de numrul de tranziii aplicate pe terminalul de ceas luate n considerare de la ultima atenionare a modulului. Rolul su i confer denumirea de terminal de date. Datorit celor 8 intrri, doar 8 tranziii urmate de 8 citiri sunt posibile, iar n lipsa unei noi atenionri, valorile ulterior citite vor fi de 0 logic (asta ne spune productorul componentei) S lum un exemplu de operare : s zicem c dorim s citim n acest moment starea tastelor. Prima i prima dat trebuie s atenionm componenta c urmeaz s citim starea tastelor. Facem asta pulsnd1 terminalul de ncrcare i trimind 8 pulsuri pe terminalul de ceas mpreun cu 8 citiri ale terminalului de date. Strile fiecrei taste vor intra una cte una pe terminalul de date urmnd ca respectivul creiera s reconstruiasc starea tuturor tastelor ntr-un octet nou prin operaii logice de deplasri urmate de SAU-uri logice, dup cum vom vedea. Dac explicaia scris este greu de urmrit i neles, poate ne ajut mai bine un grafic :

este tot una cu o tranziie de la 0 la 1 apoi napoi la 0

44

Desigur, aceasta nu este singura metod corect de citire a tastelor. Uneori nu este necesar citirea tuturor tastelor i putem opri ncrcarea direct la o tast anume. n felul acesta ctigm timp, dar pierdem din generalitate : soluia nu este bun pentru orice aplicaie gndit pentru Ale, ci doar pentru acele aplicaii pentru care viteza aplicaiei este foarte important. La urma urmei, una este s citeti tot timpul toate cele 8 taste, i alta este s te opreti la a 2-a sau a 3-a tast citit. Ale va merge pe varianta mai general din motive uor de neles, dar am considerat c aceste idei merit amintite. Am tot discutat despre aceast compoment, vrei s o identificm ? Uitai-v dup o pies care arat aa :

care are inscripionat pe ea 74HC165 (sau ceva asemntor). Ar trebui s fie amplasat lng cele 8 butonae care, apropo, sunt dispuse n linie n partea de jos a plcuei. S nu v facei griji dac explicaiile acestea sunt cumva mai greu de neles. Le putei relua pentru o nelegere mai bun. Oricum i noi le vom relua i mbunti atunci cnd vedem cum reuete creieraul de pe plcu s citeasc din secvena sa de instruciuni aceste stri.

45

n aceeai categorie am putea include i modulul de afiare, dar haidei s vedem mai n detaliu cum funcioneaz acest modul. Modulul de afiare este, aa cum spuneam, foarte asemntor cu cel al mini-tastaturii n sensul c are 8 LED-uri i funcioneaz dup un principiu asemntor, dar oarecum invers. Datorit acelorai limitri ca i cele observate n cazul tastaturii, comanda de afiare se realizeaz cu ajutorul unei componente externe. Practic, cu ajutorul acestei componente, creieraul reuete s comande aprinderea celor 8 LED-uri doar prin 2 terminale : 1. un terminal de date folosit pentru a culege bii de ctre component i a-i trimite spre LED-uri i 2. un terminal de ceas cu rolul n a ncrca, la fiecare puls, un bit de pe terminalul de date i a-l trimite spre LED-ul curent , deplasnd celelalte valori pentru a face loc noii valori. Fiecare dintre valorile prezente are n coresponden un LED, iar o valoare de 1 aprinde LED-ul i o valoare de 0 stinge respectivul LED Dup cum se observ, aceast component nu are un terminal de ncrcare, rolul su fiind inutil n acest context. S lum un exemplu ca s nelegem mai bine conceptul : considerm c dorim s trimitem spre cele 8 LED-uri bii suficieni pentru a aprinde LED-ul 2 i 5. Acest lucru l-am face n urmtorii pai (s nu uitm c primul bit controleaz, n final, al 8-lea LED, al 2-lea bit controleaza al 7-lea LED i aa mai departe) : 1. LED 8 va fi nchis pe terminalul de date va fi scris bit-ul 0 2. Pulsm terminalul de ceas pentru a ncrca valoarea pe LED-uri 3. LED 7 va fi nchis pe terminalul de date va fi scris bit-ul 0 4. Pulsm terminalul de ceas pentru a ncrca valoarea pe LED-uri 5. LED 6 va fi nchis pe terminalul de date va fi scris bit-ul 0 6. Pulsm terminalul de ceas pentru a ncrca valoarea pe LED-uri 7. LED 5 va fi nchis pe terminalul de date va fi scris bit-ul 1 8. Pulsm terminalul de ceas pentru a ncrca valoarea pe LED-uri 9. LED 4 va fi nchis pe terminalul de date va fi scris bit-ul 0 10. Pulsm terminalul de ceas pentru a ncrca valoarea pe LED-uri 11. LED 3 va fi nchis pe terminalul de date va fi scris bit-ul 0 12. Pulsm terminalul de ceas pentru a ncrca valoarea pe LED-uri 13. LED 2 va fi nchis pe terminalul de date va fi scris bit-ul 0 14. Pulsm terminalul de ceas pentru a ncrca valoarea pe LED-uri 15. LED 1 va fi nchis pe terminalul de date va fi scris bit-ul 1 16. Pulsm terminalul de ceas pentru a ncrca valoarea pe LED-uri i stop-joc : afiorul va conine configuraia dorit. Desigur c acest procedeu se poate optimiza s conin mai puine comenzi folosind instruciuni de control i operaii pe bii de pild. Totui, precizm c aceast abordare a fost aleas pentru a nelege mai bine conceptul. Fiind att de asemntor cu modulul de tastatur, componenta n cauz seamn foarte bine cu echivalenta sa de la tastatur, dar difer printr-o cifr : pentru LED-uri cutai pe plcu acelai tip de component, dar inscripionat 74HC164 (sau asemntor). O vei gsi cel mai probabil n regiunea celor 8 LED-uri.

46

Acum c am discutat toate modulele externe1 prezente pe plcua Ale : fotoelementul, modulul de reset, tastatura, afiorul, s discutm cel mai complex modul avnd cele mai multe componente, i anume : modulul de programare. Programatorul (ca s nu mai folosim expresia de modul de programare care este prea lung) are singurul rol de a ne permite s instruim calculatoraul de pe Ale s ne execute instruciunile pe care le dorim. Practic, nici unul din modulele respective nu ar fi utile dac nu ar exista o aplicaie care s tie cum s comunice cu ele. Ei bine, aplicaia nu ar exista, printre altele, dac ea nu ar putea fi descrcat din calculatorul personal n care a fost conceput pe creieraul de pe Ale. Pe lng aceast proprietate fundamental pentru Ale, prin intermediul programatorului, toate modulele inclusiv creieraul se alimenteaz, nemafiind nevoie de o alimentare extern aa cum am vzut la alte plcue de acest tip. Desigur c, aa cum spuneam adineauri, modulul conine cele mai multe piese fa de restul modulelor, iar printre acestea amintim 2 LED-uri aezate unu lng cellalt cu urmoarea semnificaie : 1. LEDul verde arat cnd modulul este alimentat (prin cablul USB), iar 2. LEDul rou se aprinde atunci cnd se descarc o aplicaie pe creiera. Cea mai important component a acestui modul o reprezint circuitul integrat Attiny2313 care, surprinztor, este tot un creiera asemntor celui folosit de Ale. Am putea spune c ceea ce facem noi este s programm un creiera prin intermediul altui creiera mai mare. Attiny2313 a fost programat nainte de a fi montat pe plcu pentru a juca, n acest caz, rolul de programator. Interesant, nu credei ? Mi-aduce aminte de vechea ntrebare : cine a fost primul : oul sau gina?. n cazul nostru, a fost Attiny2313. Urmrii v rog componenta principal a programatorului i ncercai s reinei dimensiunea lui fizic. Este singurul element cu 20 de piciorue, deci nu ar trebui s fie o prea mare problem. n comparaie cu el, creieraul plcuei are doar 8 terminale, dar tii ce ? Cred c s-a discutat suficient despre module externe! Haidei s mergem mai n detaliu cu analiza plcuei i s ne ocupm de latura inteligent a sa. n continuare vom privi, prin noiunile nvate despre calculatoare, elementul ce face plcua cu adevrat inteligent. Vom discuta despre creieraul plcuei Ale. S ncepem

Microcreieraul Ale
Tot ce am nvat despre calculatoare ne-a dus n acest punct al vieii noastre mici. S nu pierdem din vedere scopul cruliei : vrem s nvm s facem lucruri extraordinare alturi de Ale. Acest lucru l putem face doar pentru c ceea ce am discutat mai sus se aplic ntrutotul i pe creieraul plcuei Ale. Da da, ai auzit bine : cum ziceam, calculatoarele nu sunt doar cunoscutele cutii mari care scot vjitul acela cnd sunt n funciune, o nu! Calculatoarele sunt muuult mai mult i muuult mai multe.

credei c acestea sunt toate ? stai s vedei ce urmeaz ...

47

Ale are creiera, unul mic ce-i drept, dar suficient ct s ne putem juca cu el i s nvm cte ceva prin el. Dar s vedem despre ce creiera este vorba i s vedem ce putem s spunem despre el prin ceea ce am nvat deja. Dac continum n stilul cu care ne-am obinuit cnd am discutat despre module, creieraul este cel mai mic circuit integrat dintre cele amintite : are doar 8 piciorue dispuse n 2 rnduri a cte 4 terminale fiecare, dar s nu lsai dimensiunile sale s v nele, doamne ce tie s fac! Dac l vei cuta pe plcu, el arat cam aa : , iar pe component, dac v vei uita mai bine, vei gsi i tipul microcreieraului : Attiny25. n lumea electronicii, denumirea unei componente poate conduce la mult informaie, i asta mai ales datorit internetului. Desigur, aceast informaie nu este tot timpul uor de neles. Dac vei vedea foaia de catalog ce vine cu CD-ul, vei vedea c specificaiile lui Attiny25 se ntind pe cteva sute de pagini. Ne propunem, n cele ce urmeaz, s urmrim principalele caracteristici ale microcreieraului folosit. Vom ncerca s marcm ct mai multe aspecte ce pot fi puse n eviden prin exemplele create mpreun cu plcua. Vom face acest lucru ntr-o manier progresiv, de la simplu la complex, iar cnd va veni momentul, vom mbrca explicaiile cu instruciuni practice pentru a le nelege mai bine. Aadar, ce zicei s ncepem cu memoria ?

Memoria microcreieraului
Microcreieraul Attiny25 ne pune la dispoziie, aa cum ne-am obinuit, 2 tipuri de memorie : una volatil pentru a ine informaii despre aplicaiile ce le dorim executate i una nevolatil ce ne confer spaiu pentru instruciuni. Acum s introducem nite cifre : avem 2048 de octei de memorie pentru instruciuni i 224 de octei memorie pentru date. Spunndu-v asta, suntei ndreptii s v ntrebai : asta nseamn c putem scrie 2048 de instruciuni ? Ei bine, nu chiar, iar motivul este unul simplu : majoritatea instruciunilor au 16 bii (sau 2 octei, pentru a rmne la aceeai unitate de msur), iar unele au chiar 32 de bii (4 octei). Dac ignorm pe cele puine de 32 de bii am putea spune c, n cel mai fericit caz, cei 2048 de octei ar putea gzdui maxim 1024 instruciuni, iar asta ar fi adevrat dac nu ar exista unele excepii dar este suficient de corect pentru noi. n tot cazul, numrul de instruciuni ce le putem scrie pe Ale sunt de ordinul sutelor ceea ce este suficient pentru a nva tot ce ne propunem. Dac tot suntem la capitolul memorii, este bine s amintesc faptul c cele 2 categorii nu acoper toate cazurile de memorii disponbile dup cum ar prea. Spun acest lucru acum, pentru a introduce un nou tip de memorie cu care vine Attiny25. Ce ar putea aduce n plus acest nou tip de memorie? Pi o caracteristic interesant a ei spune c nu este nici volatil i nici nevolatil. Cum se poate aa ceva? v ntrebai. Simplu, are caracteristicile amndurora : Poate fi citit/scris ca i o memorie volatil, dar nu se pierde atunci cnd creieraul nu este bgat n priz asemeni memoriei nevolatile. Sunt 128 de octei n aceast categorie pe microcreiera1. De obicei, n acest nou tip de memorie se
1

care, apropo, poart denumirea de memorie EEPROM de la englezescul Electrically Erasable Programmable Read-Only Memory (Memorie fix programabil electric). M rog, prezentm aici denumirea pentru a v obinui cu ea. S-ar putea s o mai vedei prin crulie i e bine s tii de unde provine.

48

nmagazineaz informaii de configurare gen valoarea matematic a lui (tii voi : 3.1415...) sau informaii de stare gen de cte ore a funcionat creieraul. Ok, avem cele 3 memorii. Putem s clasm acest capitol i s mergem mai departei ? Nu nainte de a analiza un pic n detaliu aceste memorii i de a nelege zonele speciale prezente. Da, ai auzit bine : exist regiuni speciale i specializate n att n memoria volatil ct i n cea nevolatil, dar nu i n cea mixt1. Aceste regiuni au un rol special pentru microcreiera dup cum vom vedea n continuare n memoria volatil putem vorbi despre 4 regiuni speciale din care 2 se suprapun: n domeniul de adrese 0x0000 - 0x001F, cuprinznd 32 de octei, avem aa numitele registre de fiier2 prin care pot opera instruciuni ale microcreieraului precum cele de operaii matematice sau de date. Practic exist clase de instruciuni care nu pot opera cu informaii dect cu adrese din domeniul acesta. Aa este construit microcreieraul. Din cauza faptului c aceast regiune este foarte des utilizat, s-au acordat denumiri pentru fiecare din cei 32 de octei ai si astfel : adresa 0x0000 se numete Registrul 0 (se noteaz R0), adresa 0x0001 s.n.3 Registrul 1 (se noteaz R1) adresa 0x001F s.n. Registrul 31 (R31). Dup cum vom vedea, dei microcreieraul lucreaz cu date de 8 bii, exist, i instruciuni de control care folosesc 16 bii. Este i normal dac ne gndim c un salt trebuie s poat ajunge oriunde n cele 2048 de locaii de memorie nevolatil. Ori putem n 8 bii s punem orice valoare din domeniul 0 - 2047 ? Rspuns evident : nu! Dac mai inei minte tabelul de conversie din baza 2 n baza zecimal, cea mai mare valoare ce se poate scrie pe 8 bii este dat de urmtoarea analiz :

0b111111112=22... 2+ 22... 2 +...+2+1=128+ 64+32+...+2+1=25510


de 7 ori de6 ori

.De

aici vine i necesitatea acestor registre speciale. Pentru acestea se folosesc 3 grupri a cte 2 registre normale fiecare din domeniul R26 - R31 (ai sesizat notaia sper - o vom folosi des) numii simplu X, Y i Z. X este compus din R26 i R27 Y este alctuit din R28 : R29 Z este format din R30 : R31 domeniul 0x0020 - 0x005F ce conine 64 de octei este important deoarece valorile pe care le citim/scriem n el controleaz modulele prezente n interiorul capsulei microcreieraului4. Probabil v ntrebai de ce sunt att de muli octei ? Chiar avem nevoie de tot acest spaiu ? Nu, nu este nevoie de tot acest spaiu dei modulele, dup cum vom vedea, sunt multe. Cei ce au creat microcreieraul au rezervat acest numr mare de octei pentru a ncerca s uniformizeze regiunile de memorie pentru mai multe tipuri de microcreierae (mai inei minte Attiny2313-ul folosit n modulul de programare ? ). Evident, capacitile fiecrui microcreiera diferind, este de dorit ca s se aloce un spaiu suficient de mare pentru a susine aceste capaciti.

1 2

ultimul tip de memorie introdus care are proprieti din ambele clase dei nu voi discuta denumirea complet (este tradiional), voi preciza faptul c putem considera un registru ca fiind o coal de hrtie pe care scriem cu creionul i putem s tergem cu guma oridecte ori vrem s modificm informaia prezent 3 prescurtarea pentru se numete 4 n documentele oficiale, le vei gsi sub denumirea de periferice. Unii mai folosesc i aceast variant. Poate o vei gsi i prin crulie

49

i domeniul 0x0060 - 0x00DF cuprinznd 128 de octei este folosit att de stiva aplicaiilor ct i ca spaiu general de date, putnd fi direct adresat de instruciunile de date suportate n felul acesta avem 32 (registre de fiier) + 64 (registre de control) + 128 (spaiul stivei sau regiune general de date) = 224 de octei numrai i explicai. Poate sunt unii dintre voi care consider c aceti 224 octei folosii pentru date sunt insuficieni. Aceast valoare este neltoare. Dup cum vom vedea, la scopul nostru declarat de a nva, sunt suficient de muli octei. Dac ar fi s sumarizez aceste regiuni pentru o nelegere mai bun, a face-o prin imaginea urmtoare :

Ok, cam att despre regiunile memoriei volatile, s vedem ce se ntmpl cu memoria nevolatil. Memoria nevolatil nu este aa de puternic fragmentat ca cea volatil. De fapt, dac ne gndim mai bine, nimic din ceea ce am nvat noi nu ne poate justifica o eventual mprire pe regiuni a acestui tip de memorie. i totui, 2 regiuni exist : O regiune de ntreruperi i O regiune normal de cod. ntreruperi ? Ce sunt alea ? He he he mereu avem ceva nou de nvat. Vom avea un capitol special dedicat ntreruperilor, dar, pentru moment, gndii-v la ele ca fiind modalitatea prin care inima creieraului este atenionat atunci cnd un modul a terminat de fcut ceva sau atunci cnd n exteriorul creieraului se petrece ceva care cere atenia aplicaiei noastre. ntreruperile sunt noiuni foarte puternice, fr ele calculatoarele nefiind deloc ceea ce sunt astzi. Deocamdat este suficient s tim c ele exist i c primii 30 de octei din memoria nevolatil sunt rezervai lor.. Dac 30 de octei sunt rezervai pentru zona respectiv, asta nseamn c regiunii de cod i rmn 204830=2018 octei ? Ar fi adevrat dac cele 2 regiuni n discuie ar fi total separate, dar dup cum au fost gndite lucrurile, regiunea de cod poate s nghit regiunea de ntreruperi. Cu alte cuvinte, dac creieraul nu apeleaz la noiunea de ntreruperi, el poate s foloseasc respectivul spaiu ca fiind zon de instruciuni. Cam att despre memorii. nainte de a trece mai departe s discutm instruciunile suportate de Attiny25, vom ilustra printr-o diagram simpl, cele 3 tipuri de memorii prezente n creieraul lui Ale :

50

Haidei s discutm un pic despre instruciunile ce pot fi scrise pe Ale

Instruciunile cunoscute de Ale ...


Ale tie multe tipuri de instruciuni. Dei este mic, nelege instruciuni din toate clasele deja discutate de noi. Dac dorii un numr, aflai c Attiny-ul lui Ale recunoate 120 de comenzi majoritatea executate ntr-o unitate de timp. Dac folosii unitatea de timp cu care este livrat plcua atunci aceasta are valoarea de 1 micro secund! O microsecund nseamn a milioana parte dintr-o secund sau, altfel spus, o secund are un milion de microsecunde. Dac vrei mai clar, aflai c Ale poate executa aproape 1000000 (un milion) de astfel de instruciuni pe secund! Aceast baz de timp se poate mri sau micora, iar o discuie pe aceast tem ar fi interesant, dar i avansat totodat. Vom avea o seciune n crulie n care ne vom ocupa de exact acest lucru : modificarea vitezei de execuie a instruciunilor pe Ale. nainte de a merge mai departe, trebuie neaprat s discutm despre ceva. Vom porni aici discuia despre un registru de control. Este vorba despre registrul de stare (poart notaia de SREG1), o regiune de memorie deosebit de important pentru orice calculator care ine informaii despre rezultatul operaiilor realizate cum ar fi dac rezultatul ultimei operaii algebrice a fost zero. Acest registru este deosebit de important deoarece de aici se iau valorile pentru care se evalueaz instruciunile de control, printre altele. Registrul n cauz este situat la adresa 0x003F n spaiul regitrilor de control. Asta nseamn c el se afl poziionat n memoria fizic la adresa 0x0020 + 0x003F = 0x005F. Cum am calculat asta ntrebai ? Ei bine, aa cum ziceam adineauri, toi regitrii de control se afl n domeniul 0x0020 0x005F. Cu alte cuvinte, adresa lor nu consider valoarea 0 ca fiind valoare de nceput a numrrii ci consider valoarea 0x0020. Astfel, acest tip de adresare mai poart denumirea de adresare relativ, iar exprimarea unei adrese pornind de la adresa fizic 0x0000 mai poart denumirea de adresare absolut. Aa cum vei vedea in alte materiale, regitrii de control se exprim predominant folosind adresarea relativ pe care o vom folosi i noi. Revenind biii registrului SREG au urmtoare semnificaie : Rang
7 6 5 4 3 2 1 0

Notaie I

vine din englez, se citete esreg i este prescurtarea de la Status Register - registru de stare, n limba romn

51

Rang Op. permise Val. iniial

S/C2 0

S/C 0

S/C 0

S/C 0

S/C 0

S/C 0

S/C 0

S/C 0

Unde literele de la notaie au urmtoarele semnificaii : Liter Nume complet I Control ntreruperi globale Bit de copiere Stegule de transport-parial Semnul operaiei Depirea rezultatului Rezultat negativ Rezultat zero Rezultat cu transport Semnificaie Setarea acestui bit pe 0 dezactiveaz ntreruperile globale, pe cnd punerea lui pe 1 are efectul contrar Folosit de instruciunile care lucreaz stocarea/ncrcarea de bii Indic dac sau nu a rezultat un rest n urma unor operaii matematice ce folosesc operanzi de 4 bii (exist i din alea, dar sunt mai speciale) Semnul rezultatului ultimei operaii matematice Se seteaz atunci cnd o adunare depete n valoare capacitatea destinaiei astfel nct rezultatul stocat nu este chiar cel corect Pstreaz informaii privind dac sau nu rezultatul ultimei operaii matematice a fost unul negativ Spune dac ultima operaie matematic a avut ca rezultat valoarea 0 Este al 9-lea bit dintr-o operaie matematic (sum, spre exemplu)

T H

S V

N Z C

Discutasem adineauri c aceast vitez este adevrat pentru instruciuni care se execut ntr-o unitate de timp. Totui, nu toate instruciunile au aceast proprietate: n funcie de complexitatea lor, instruciunile necesit mai multe astfel de uniti de timp. Dar tii ce ? Haidei s vedem acest lucru pentru toate instruciunile cunoscute de Attiny25! n felul acesta cunoatem i instruciunile disponibile. Rezistai alturi de mine pentru c vine un tabel lung, dar complet pentru cei care caut informaii despre capacitile directe ale lui Ale.
Denumire instruciune ADD Rd, Rs2 ADC Rd, Rs ADIW Rdl, K
2 1

Comentariu Calculeaz suma dintre Rd i Rs, iar rezultatul pune-l napoi n Rd Realizeaz suma dintre Rd. Rs i bitul C din SREG, iar rezultatul stocheaz-l napoi n Rd Adaug valoarea constant dat K din domeniul 0 - 63 la 1 1 2

#1

Exemplu de folosire ADD R0, R1 ADC R1, R2 ADIW R26, 5

reprezint prescurtarea de la Scriere/Citire n aceast coloan vom avea unitile de timp necesare execuiei instruciunii respective 2 Rd/Rs/Rr este unul dintre cei 32 de regitrii discutai la seciunea dedicat memoriilor. Ca i neles particular, Rd nseamn registru destinaie, Rs : registru surs, iar Rr : registru auxiliar

52

Denumire instruciune

Comentariu cuvntul de 16 bii Rdl care poate fi orice registru inferior din gruprile : {R27:R26 sau XH:XL1, R29:R28 sau YH:YL, R31:R30 sau ZH:ZL}

Exemplu de folosire

SUB Rd, Rr SUBI Rd, K SBC Rd, Rr SBCI Rd, K

Calculeaz Rd - Rs i pune rezultatul napoi n Rd. Calculeaz Rd - K (constant cu valoare din domeniul 0 255) i pune rezultatul napoi n Rd. Calculeaz Rd - Rr - valoarea bitului C din SREG i pune rezultatul n Rd Calculeaz Rd - constanta K (din domeniul 0-255) valoarea bitului C din SREG i pune rezultatul n Rd. Rd poate fi unul din registrele : R16 - R31 Aceai interpretare ca i cea dat pentru ADIW, doar c nu se face adunare ci scdere. Valorile au aceleai limite Realizeaz I LOGIC ntre biii registrului Rd i cei ai lui Rr, iar rezultatul l pune n Rd Aplic I LOGIC ntre valoarea binar a registrului Rd (R16-R31) i constanta K (0-255), rezultatul punndu-l n Rd Realizeaz SAU LOGIC ntre biii registrului Rd i cei ai lui Rr, iar rezultatul l pune n Rd Realizeaz SAU LOGIC ntre biii registrului Rd (R16R31) i cei dai de constanta K (0-255), iar rezultatul l pune n Rd Aplic SAU-EXCLUSIV ntre registrele Rd i Rr, rezultatul fiind pus n Rd Pune n registrul Rd rezultatul calculului 255 - Rd Stocheaz n registrul Rd rezultatul operaiei 0 - Rd Calculeaz SAU LOGIC aplicat pe Rd (R16-R31) i valoarea constantei K (0-255), iar rezultatul stocheaz-l napoi n Rd terge biii din Rd (R16-R31) care au poziiile identice cu biii din constanta K i a cror valoare din K (0-255) este 1 Calculeaz Rd + 1 i pune rezultatul napoi n Rd Calculeaz Rd - 1 i pune rezultatul napoi n Rd Testeaz dac Rd este 0 (caz n care bitul Z din SREG se pune pe 1) sau valoare negativ (caz n care bitul N din SREG se pune pe 1) ncarc n Rd valoarea 0x00 ncarc n Rd valoarea 0xFF Salt necondiionat n memorie, din punctul curent, la o adres dat de k. k poate adresa orice valoare din spaiul de instruciuni

1 1 1 1

SUB R1, R5 SUBI R2, 7 SBC R0, R9 SBCI R17, 12

SBIW Rdl, K AND Rd, Rr ANDI Rd, K

2 1 1

SBIW R28, 21 AND R9, R2 ANDI R18, 123

OR Rd, Rr ORI Rd, K

1 1

OR R5, R16 ORI R30, 1

EOR Rd, Rr COM Rd NEG Rd SBR Rd, K

1 1 1 1

EOR R9, R0 COM R7 NEG R2 SBR R20, 210

CBR Rd, K

CBR R17, 0xF0 (pune pe 0 logic ultimii 4 bii din R17) INC R7 DEC R22 TST R6

INC Rd DEC Rd TST Rd

1 1 1

CLR Rd SER Rd RJMP K

1 1 2

CLR R13 SER R22 RJMP 10 RJMP -15

terminaia H vine de la high - octet superior i L vine de la low - octet inferior

53

Denumire instruciune IJMP RCALL K ICALL RET RETI

Comentariu Salt indirect la adresa dat de registrul compus Z Apel de funcie la adres relativ dat de valoarea lui k. Nu exist restricii asupra lui k din spaiul de memorie Apel de funcie indirect dat de valoarea lui Z Revenire din funcie n punctul unde am fcut CALL-ul (oricare dintre ele) Revenire din funcia de gestionare a ntreruperii n locul de unde a lsat-o ultima instruciune nainte de generarea ntreruperii n sine Compar valorile regitrilor Rd (R0-R31) cu Rr (R0-R31) i sari peste instruciunea ce urmeaz dac cei 2 regitrii au valori egale Compar valorile ce se gsesc n regitrii Rd i Rr (ambii putnd fii oricare din : R0-R31) i pune biii necesari pe SREG pe valorile gsite Compar valoarea gsit n registrul Rd (R0-R31) cu valoarea constantei K i seteaz, n funcie de rezultat, biii din SREG Sari peste urmtoarea instruciune dac bitul B (0-7) din registrul Rr (R0-R31) a fost setat pe 0 Urmtoarea instruciune de dup SBRS este ignorat dac bitul dat de poziia B (0-7) n registrul Rr (R0-R31) are valoarea 1 Sari peste urmtoarea instruciune dac bitul B (0-7) din registrul de control ce se afl la adresa P (0-31) a fost setat pe 0 Are efectul opus lui SBIC : Sari peste urmtoarea instruciune doar dac bitul aflat la poziia B (0-7) din registrul de control dat de adresa P (0-31) are valoarea 1 Sari la adresa relativ dat de valoarea constantei K (64:63) dac valoarea bitului cu indice S (0-7) din SREG este 1 Acelai lucru ca i la BRBS, doar c saltul se face la valoarea 0 Sari la adresa relativ fa de punctul curent de execuie dat de valoarea constantei K (-64:63) dac bitul Z din SREG are valoarea 1 Sari la adresa relativ fa de punctul curent de execuie dat de valoarea constantei K (-64:63) dac bitul Z din SREG are valoarea 0 Sari la adresa relativ fa de punctul curent de execuie dat de valoarea constantei K (-64:63) dac bitul C din SREG are valoarea 1 2 3 3 4 4

Exemplu de folosire IJMP RCALL 22 RCALL -0x0F ICALL RET RETI

CPSE Rd, Rr

1 (F) 2/3 (A)2 1

CPSE R0, R17

CP Rd, Rr

CP R22, R9

CPI Rd, K

CPI R9, 7

SBRC Rr, B SBRS Rr, B

1 (F) 2/3 (A) 1 (F) 2/3 (A) 1 (F) 2/3 (A) 1 (F) 2/3 (A) 1 (F) 2 (A) 1 (F) 2 (A) 1 (F) 2 (A) 1 (F) 2 (A) 1 (F) 2 (A)

SBRC R9, 5 SBRS R11, 2

SBIC P, B

SBIC 15, 2

SBIS P, B

SBIS 11, 0

BRBS S, K

BRBS 3, 12

BRBC S, K BREQ K

BRBC 2, -10 BREQ 20

BRNE K

BRNE -17

BRCS K

BRCS 37

se interpreteaz n felul urmtor : dac Rd Rr atunci nu se realizeaz saltul i CPSE-ul dureaz 1 unitate de timp. Dac Rd = Rr n schimb, atunci saltul se realizeaz i, n funcie de dimensiunea instruciunii ce o urmeaz, poate lua 2 sau chiar 3 uniti de timp pentru execuie

54

Denumire instruciune BRCC K

Comentariu Sari la adresa relativ fa de punctul curent de execuie dat de valoarea constantei K (-64:63) dac bitul C din SREG are valoarea 0 Are aceeai semnificaie ca i BRCC cu tot cu valori limit Are aceeai semnificaie ca i BRCS cu tot cu valori limit Sari la adresa relativ fa de punctul curent de execuie dat de valoarea constantei K (-64:63) dac bitul N din SREG are valoarea 1 Sari la adresa relativ fa de punctul curent de execuie dat de valoarea constantei K (-64:63) dac bitul N din SREG are valoarea 0 Sari la adresa relativ fa de punctul curent de execuie dat de valoarea constantei K (-64:63) dac operaia bitul N SAU-EXCLUSIV bitul V din SREG are rezultatul 0 Sari la adresa relativ fa de punctul curent de execuie dat de valoarea constantei K (-64:63) dac operaia bitul N SAU-EXCLUSIV bitul V din SREG are rezultatul 1 Sari la adresa relativ fa de punctul curent de execuie dat de valoarea constantei K (-64:63) dac bitul H din SREG are valoarea 1 Sari la adresa relativ fa de punctul curent de execuie dat de valoarea constantei K (-64:63) dac bitul H din SREG are valoarea 0 Sari la adresa relativ fa de punctul curent de execuie dat de valoarea constantei K (-64:63) dac bitul T din SREG are valoarea 1 Sari la adresa relativ fa de punctul curent de execuie dat de valoarea constantei K (-64:63) dac bitul T din SREG are valoarea 0 Sari la adresa relativ fa de punctul curent de execuie dat de valoarea constantei K (-64:63) dac bitul V din SREG are valoarea 1 Sari la adresa relativ fa de punctul curent de execuie dat de valoarea constantei K (-64:63) dac bitul V din SREG are valoarea 0 Sari la adresa relativ fa de punctul curent de execuie dat de valoarea constantei K (-64:63) dac bitul I din SREG are valoarea 1 Sari la adresa relativ fa de punctul curent de execuie dat de valoarea constantei K (-64:63) dac bitul I din SREG are valoarea 0 Seteaz bitul de pe poziia B (0-7) din registrul ce se afl la adresa constantei P (0-31) pe 1 Reseteaz bitul de pe poziia B (0-7) din registrul ce se afl la adresa constantei P (0-31) pe 0

# 1 (F) 2 (A) 1 (F) 2 (A) 1 (F) 2 (A) 1 (F) 2 (A) 1 (F) 2 (A) 1 (F) 2 (A)

Exemplu de folosire BRCC 0x07

BRSH K BRLO K BRMI K

BRSH 0x12 BRLO 47 BRMI 0x10

BRPL K

BRPL 65

BRGE K

BRGE 19

BRLT K

1 (F) 2 (A)

BRLT -13

BRHS K

1 (F) 2 (A) 1 (F) 2 (A) 1 (F) 2 (A) 1 (F) 2 (A) 1 (F) 2 (A) 1 (F) 2 (A) 1 (F) 2 (A) 1 (F) 2 (A) 2 2

BRHS -60

BRHC K

BRHC 0x15

BRTS K

BRTS -0x18

BRTC K

BRTC 39

BRVS K

BRVS 4

BRVC K

BRVC 51

BRIE K

BRIE -27

BRID K

BRID 0x21

SBI P, B CBI P, B

SBI 0x10, 3 CBI 17, 6

55

Denumire instruciune LSL Rd

Comentariu Deplaseaz toi biii din registrul Rd (R0-R31) cu o poziie la stnga astfel nct : bitul 7 din Rd ajunge n bitul C din SREG, bitul 6 din Rd ajunge pe poziia 7 bitul R0 ajunge pe poziia R1, iar pe poziia R0 se pune valoarea 0 1

Exemplu de folosire LSL R2

LSR Rd

Deplaseaz toi biii din registrul Rd (R0-R31) cu o poziie la dreapta astfel nct : bitul 7 din Rd ia valoarea 0, pe bitul 6 ajunge valoarea vechiul bit 7, pe bitul 0 ajunge vechiul bit 1, iar valoarea bitului 0 va ajunge n bitul C din SREG

LSR R19

ROL Rd

Rotete biii registrului Rd (R0-R31) de la dreapta la stnga prin bitul C din SREG astfel: bitul C intr n b(0)1, b(0) intr n b(1) b(6) intr n b(7), iar b(7) ajunge din nou n C

ROL R10

ROR Rd

Rotete biii registrului Rd (R0-R31) de la stnga la dreapta prin bitul C din SREG astfel: bitul C intr n b(7), b(7) intr n b(6) b(1) intr n b(0), iar b(0) ajunge din nou n C

ROR R0

ASR Rd

Rotete registrul Rd (R0-R31) de la stnga la dreapta pstrnd b(7) constant i trecnd restul de valor cu un bit mai spre stng. b(0) ajunge n C din SREG

ASR R13

SWAP Rd BSET S BCLR S BST Rr, B BLD Rr, B SEC CLC


1

Interschimb primii 4 bii cu ultimi 4 bii din registrul Rd (R0-R31) Seteaz bitul cu indice S (0-7) din registrul SREG pe 1 Reseteaz bitul cu indice S (0-7) din registrul SREG pe 0 Seteaz bitul T din SREG cu valoarea dat de poziia bitului B (0-7) din registrul Rr (R0-R31) Copiaz valoarea bitului T din SREG pe poziia dat de constanta B (0-7) n registrul Rr (R0-R31) Seteaz bitul C din SREG pe 1 Reseteaz bitul C din SREG pe 0

1 1 1 1 1 1 1

SWAP R2 BSET 6 BCLR 5 BST R8, 5 BLD R7, 3 SEC CLC

b(0) = [simplificare de notaie] citim bitul 0 a registrului Rd

56

Denumire instruciune SEN CLN SEZ CLZ SEI CLI SES CLS SEV CLV SET CLT SEH CLH MOV Rd, Rr MOVW Rd, Rr

Comentariu Seteaz bitul N din SREG pe 1 Reseteaz bitul N din SREG pe 0 Seteaz bitul Z din SREG pe 1 Reseteaz bitul Z din SREG pe 0 Seteaz bitul I din SREG pe 1 Reseteaz bitul I din SREG pe 0 Seteaz bitul S din SREG pe 1 Reseteaz bitul S din SREG pe 0 Seteaz bitul V din SREG pe 1 Reseteaz bitul V din SREG pe 0 Seteaz bitul T din SREG pe 1 Reseteaz bitul T din SREG pe 0 Seteaz bitul H din SREG pe 1 Reseteaz bitul H din SREG pe 0 Copiaz valoare registrul Rr (R0-R31) n Rd (R0-R31) Copiaz valoarea dat de o pereche de regitrii extini Rr (R31:R30, R29:R28, R27:R26) n alt regiune de regitrii speciali Rd (R31:R30, R29:R28, R27:R26) ncarc valoarea constantei K (0-255) n registrul Rd (R16-R31) ncarc valoarea ce se gsete la adresa dat de registrul X (R26:R27) n registrul Rd (R0-R31) ncarc valoarea ce se gsete la adresa dat de registrul X (R26:R27) n registrul Rd (R0-R31) apoi incrementeaz registrul X Scade 1 din valoarea lui X (R26:R27) apoi folosete rezultatul pe post de adres de unde se ncarc informaia n registrul Rd (R0-R31) ncarc valoarea ce se gsete la adresa dat de registrul Y (R28:R29) n registrul Rd (R0-R31) ncarc valoarea ce se gsete la adresa dat de registrul Y (R28:R29) n registrul Rd (R0-R31) apoi incrementeaz registrul Y Scade 1 din valoarea lui Y (R28:R29) apoi folosete rezultatul pe post de adres de unde se ncarc informaia n registrul Rd (R0-R31) ncarc valoarea ce se gsete la rezultatul sumei dintre adresa dat de registrul Y (R28:R29) i constanta q (063) n registrul Rd (R0-R31) ncarc valoarea ce se gsete la adresa dat de registrul Z (R30:R31) n registrul Rd (R0-R31) 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1

Exemplu de folosire SEN CLN SEZ CLZ SEI CLI SES CLS SEV CLV SET CLT SEH CLH MOV R0, R3 MOVW R26, R28

LDI Rd, K LD Rd, X LD Rd, X+

1 1 2

LDI R5, 2 LD R9, X LD R9, X+

LD Rd, -X

LD R11, -X

LD Rd, Y LD Rd, Y+

1 2

LD R2, Y LD R8, Y+

LD Rd, -Y

LD R17, -Y

LDD Rd, Y+q

LD R9, Y+3

LD Rd, Z

LD R0, Z

57

Denumire instruciune LD Rd, Z+

Comentariu ncarc valoarea ce se gsete la adresa dat de registrul Z (R30:R31) n registrul Rd (R0-R31) apoi incrementeaz registrul Z Scade 1 din valoarea lui Z (R30:R31) apoi folosete rezultatul pe post de adres de unde se ncarc informaia n registrul Rd (R0-R31) ncarc valoarea ce se gsete la rezultatul sumei dintre adresa dat de registrul Z (R30:R31) i constanta q (063) n registrul Rd (R0-R31) ncarc un octet din spaiul de instruciuni de la adresa dat de constanta K (0-65535) n registrul Rd (R0-R31) Salveaz valoarea registrului Rr (R0-R31) n memoria de date la adresa dat de valoarea registrului extins X (R26:R27) Salveaz valoarea registrului Rr (R0-R31) n memoria de date la adresa dat de valoarea registrului extins X (R26:R27) apoi adaug 1 la valoarea lui X Scade 1 din valoarea lui X (R26:R27) apoi folosete rezultatul pe post de adres unde se salveaz valoarea registurlui Rr (R0-R31) Salveaz valoarea registrului Rr (R0-R31) n memoria de date la adresa dat de valoarea registrului extins Y (R28:R29) Salveaz valoarea registrului Rr (R0-R31) n memoria de date la adresa dat de valoarea registrului extins Y (R28:R29) apoi adaug 1 la valoarea lui Y Scade 1 din valoarea lui Y (R28:R29) apoi folosete rezultatul pe post de adres unde se salveaz valoarea registurlui Rr (R0-R31) Salveaz valoarea lui Rr (R0-R31) la adresa din spaiul de date dat de suma dintre valoarea registrului Y (R28:R29) i constanta q (0-63) Salveaz valoarea registrului Rr (R0-R31) n memoria de date la adresa dat de valoarea registrului extins Z (R30:R31) Salveaz valoarea registrului Rr (R0-R31) n memoria de date la adresa dat de valoarea registrului extins Z (R30:R31) apoi adaug 1 la valoarea lui Z Scade 1 din valoarea lui Z (R30:R31) apoi folosete rezultatul pe post de adres unde se salveaz valoarea registurlui Rr (R0-R31) Salveaz valoarea lui Rr (R0-R31) la adresa din spaiul de date dat de suma dintre valoarea registrului Z (R30:R31) i constanta q (0-63) Salveaz valoarea regisrului Rr (R0-R31) n spaiul de instruciuni la adresa dat de constanta K (0-65535) ncarc n R0 octetul ce se gsete la adresa Z(R30:R31) ncarc n Rd (R0-R31) octetul ce se gsete la adresa 2

Exemplu de folosire LD R25, Z+

LD Rd, -Z

LD R30, -Z

LDD Rd, Z+q

LD R6, Z+19

LDS Rd, K ST X, Rr

2 1

LDS, R18, 995 ST X, R8

ST X+, Rr

ST X+, R11

ST -X, Rr

ST -X, R25

ST Y, Rr

ST Y, R19

ST Y+, Rr

ST Y+, R6

ST -Y, Rr

ST -Y, R2

STD Y+q, Rr

STD Y+15, R9

ST Z, Rr

ST Z, R22

ST Z+, Rr

ST Z+, R3

ST -Z, Rr

ST -Z, R12

STD Z+q, Rr

STD Z+20, R7

STS K, Rr LPM LPM Rd, Z

2 3 3

STS 1005, R8 LPM LPM R5, Z

58

Denumire instruciune Z(R30:R31) LPM Rd, Z+ SPM

Comentariu

Exemplu de folosire

ncarc n Rd (R0-R31) octetul ce se gsete la adresa Z(R30:R31) apoi adaug 1 la vechea valoare a lui Z Instruciune folosit pentru a modifica spaiul de instruciuni. Prezint o complexitate mai ridicat deci nu o vom aborda n aceast crulie ncarc n Rd (R0-R31) valoarea unui registru de control indicat de adresa constantei P (0-63) Scrie n registrul de control dat de adresa P (0-63) valoarea registrului Rr (0-31) mpinge pe stiv valoarea registrului Rr (R0-R31) Scoate din stiv un octet pe care-l stocm n registrul Rd (R0-R31) Nu realizeaz nicio operaie de niciun fel, doar consum timp (util pentru secvene de ntrziere/sincronizare) Pune creieraul ntr-o stare de consum redus de energie Resteaz valoarea cinelui de paz (vom aborda acest lucru ntr-un exemplu ulterior). [Nu se prea folosete din aplicaie] Oprete execuia instruciunilor i acord controlul evaluatorului de cod.

3 ?

LPM R17, Z+ SPM

IN Rd, P OUT P, Rr PUSH Rr POP Rd NOP SLEEP WDR BREAK

1 1 2 2 1 1 1 1

IN R2, 0x05 OUT 0x10, R7 PUSH R3 POP R8 NOP SLEEP WDR BREAK

i cred c acestea sunt cam toate instruciunile : 120 la numr. Pentru cei ce a-i urmrit tabelul : bravo vou, iar pentru restul : nicio problem dac nu l-ai putut citi n ntregime. Scopul plasrii tabelului aici a fost unul pur informativ, el putndu-se consulta atunci cnd este nevoie. n acest sens, am lsat prima coloan cu denumirile originale n englez (aa cum sunt ele prezentate n foaia de catalog a creieraului Attiny25) pentru a v obinui cu notaia care o vom folosi atunci cnd le vom utiliza. Chiar dac vi se pare greu de inut minte, cu puin antrenament i puin imaginaie vei vedea c lucrurile nu sunt chiar aa de grele precum par. Prescurtrile respective nu sunt czute ntru totul din cer. Ele provin de la denumiri de aciuni englezeti care explic manifestarea lor. Spre exemplu : RJMP provine de la Relative Jump (salt relativ) aa cum BRNE provine de la Branch If Not Equal (sari dac nu sunt egale) sau MOVW care semnific Move Word (mut cuvnt de 2 octei). Bun, acum c am vzut care sunt instruciunile cu care vom avea deaface cnd vom programa creieraul de pe Ale, s lum un exemplu simplu i s vedem cum am putea combina aceste instruciuni pentru a face efectiv ceva util. Vom realiza acest lucru pentru a introduce un mod de gndire mai apropiat de plcu i implicit de realitate. Pn acum am vzut cum calculatoarele execut instruciuni una dup alta, iar noi vom folosi aceste cunotine pentru a merge un pic mai departe i a concepe o aplicaie care are potenialul de a funciona (cel puin pe Ale). S ne jucm un pic

59

Problema este simpl : dorim s aflm, cu ajutorul creieraului lui Ale, suma primelor 15 numere din domeniul 0 - 15. n urma calculului, rezultatul va fi disponibil n registrul R16. Dac am considera c aplicaia am scri-o pentru vechea noastr maimuic, atunci o soluie ar fi urmtorul set de pai : 1. iniializeaz locaia de memorie (numim aceast locaie, valoarea Rezultat) care va avea rezultatul cu 0 2. iniializeaz locaia de memorie (numim aceast locaie, valoarea Contor) care va spune cte numere am adunat cu 15 3. este valoarea inut n contor mai mare dect 0 ? a. dac da : i. adun valoarea ce se gsee acuma n Contor la Rezultat i noua valoare pune-o peste vechiul Rezultat ii. scade 1 din Contor i rezultatul pune-l napoi n Contor iii. sari la punctul 3 i continu execuia de acolo b. dac nu : i. prsete ciclul i arat rezultatul i nu este de mirare c asta ar fi tot. La sfritul ciclului vom avea rezultatul la adresa botezat Rezultat. Acum, cu ajutorul cunotinelor dobndite referitoare la instruciunile nelese de Ale, secvena de pai care ar descrie ntru totul comportamentul enunat mai sus ar fi urmtoarea : LDI R16, 0 LDI R17, 15 pas_3: ADD R16, R17 DEC R17 BRNE pas_3
;1 R16 este, conform cerinei iniiale, Rezultat-ul de mai sus ; R17 reprezint, n acest caz, Contor-ul ; Punct n memorie care va conine adresa de salt a ciclului. pas_3 poart ; denumirea de etichet ; R16 (nou) = R16 (vechi) + R17 (Contor) ; R17 (nou) = R17 (vechi) - 1 ; dac R17 nu este egal cu 0, reia execuia de la adresa dat de ethicheta ; pas_3 ; altfel, dac R17 este egal cu 0, saltul nu se mai realizeaz i execuia ; continu cu instruciunea imediat urmtoare dup BRNE cu rezultatul ; final disponibil n R16 aa cum cere enunul problemei

i cam asta este tot : problem realizat n 5 instruciuni sau 10 octei de limbaj. Rescriu codul fr comentarii n cele ce urmeaz pentru a putea fi mai uor de urmrit i de analizat : LDI R16, 0 LDI R17, 15 pas_3: ADD R16, R17 DEC R17 BRNE pas_3 Dac tot suntem aici, haidei s vedem ct ar dura execuia acetui progrmel pe Ale.
1

vom folosi ; (punct i virgul) pentru a comenta instruciunile ce le trimitem pe Ale. Prin comentare nelegem introducerea unei buci de text care nu va ajunge s fie executat de Attiny25 i care are semnificaie doar pentru noi, cei ce scriem programe pentru a ne face viaa mai uoar printr-o nelegere mai rapid a sa

60

Aadar, conform tabelului, instruciunile LDI dureaz fiecare cte o unitate de timp. ADD necesit, mpreun cu DEC, de asemenea o unitate de timp fiecare, iar BRNE necesit o unitate de timp dac condiia de egalitate cu zero este fals i dou uniti de timp dac condiia este adevrat. n total avem 2 + 2 + 1 (sau 2) = 5 (sau 6) instruciuni. Totui, s nu uitm c avem deaface cu un ciclu de execuie: instruciunile aflate ntre eticheta pas_3 i comanda BRNE, adic ADD i DEC, se vor executa de 15 ori, iar saltul se va realiza de 14 ori. Dac nu m credei, putei s verificai i singuri cu foaie i pix. Prin urmare, mica noastr aplicaie ar necesita un numr de uniti de timp date de urmtoarea sum : 2 (pentru cele dou instruciuni LDI) + 2 (pentru ADD i DEC) * 15 (pentru c de attea ori se execut n ciclul respectiv) + 2 (pentru BRNE care realizeaz saltul) * 14 (attea salturi se fac) + 1 (pentru ultimul BRNE care nu mai realizeaz saltul i ncheie aplicaia) = 61. 61 de uniti de timp ar consuma aceste instruciuni pentru a rezolva mica noastr problem. Dac lum n calcul ce am spus adineauri cum c, aa cum o primii pe Ale, o unitate de timp nseamn 1 microsecund, atunci n timp real, rezultatul ar fi disponibil dup 611 s=61 s (61 de microsecunde). Ca s v dai seama ct de rapid nseamn asta, dac o secund are un milion de microsecunde, atunci ntr-o secund s-ar putea executa aproximativ 16393 de astfel de sume! S scriu pe litere : aisprezece mii trei sute nouzeci i trei de astfel de execuii ar intra ntr-o secund! Dac asta nu este rapid atunci nu tiu ce este! Urmrind acest model mpreun cu marele tabel, vei putea analiza performanele aplicaiei voastre ceea ce uneori se i dorete. Nu putei ti niciodat nainte de a ncheia seria de curioziti nvate, propun o ultim analiz spectaculoas a codului nostru : vom vedea efectiv cum sunt vzute aceste instruciuni n memoria de comenzi a lui Attiny25. Desigur, putem tri i fr aceast informaie, dar o abordm totui pentru c poate exist unii dintre voi care vor s cunoasc i lucrurile acestea. Oricum o facem o singur dat pentru c astfel de detalii nu se prea explic fiind mai greu de descris. Dac nu dorii s cunoatei aceste lucruri, nu este nicio problem, putei s srii cu ncredere aceaste explicaii dac nu v simii confortabil i ne revedem dup. Ok, pentru cei care ai rmas, s lum aplicaia noastr i s vedem pentru fiecare tip de instruciune n parte, cum se transpune ea n memorie1 : Tip instruciune LDI ADD DEC BRNE Parametrii Rd, K Rd, Rr Rd K Bii rezultai 1110 KKKK dddd KKKK 0000 11rd dddd rrrr 1001 010d dddd 1010 1111 01kk kkkk k001 Dimensiune 16 bii (2 octei) 16 bii (2 octei) 16 bii (2 octei) 16 bii (2 octei)

Pentru curioi : biii acestor reprezentri s-au luat dint documentul Atmel 8 bit AVR Instruction Set, o referin complet asupra tuturor instruciunior cunoscute de Attiny25 precum i de alte creierae asemeni lui.
1

61

Ceea ce vedem n coloana 3 reprezint codificarea instruciunii generale din coloana nti aa cum o vede Attiny-ul n memorie. Reprezentarea este una binar cu un simbol (1, 0, K, d, etc.) pe bit rezultat i delimitat n cte 4 grupri de 4 bii fiecare pentru a putea fi urmrit mai uor. Ca o prim observaie putem spune c, ntr-adevr, aplicaia noastr ar ocupa 25=10 octei n memoria de instruciuni ceea ce ar fi suficient pentru cei 2048 de octei disponibili. Dar noi s revenim i s vedem cum sunt codificai parametrii folosii de noi pentru respectivele instruciuni. Pentru simplitate, eliminm eticheta din cod, oricum ea nu exist n memoria final. Ea este util doar traductoarelor pentru a putea calcula adrese n momentul translatrii din text n bii recunoscui de creiera : Instruciune LDI R16, 0 LDI R17, 15 ADD R16, R17 DEC R17 BRNE pas_3
; [ adresa lui pas_3 = -4 fa de adresa curent]

Valoare parametru 1 0000 0001 1 0000 1 0001 111 1101

Valoare parametru 2 0000 0000 0000 1111 1 0001

Punnd cap cal cap cele 2 tabele avem urmtoarea reprezentare final : Instruciune LDI R16, 0 LDI R17, 15 ADD R16, R17 DEC R17 BRNE pas_3 Reprezentare binar complet 1110 0000 0000 0000 1110 0000 0001 1111 0000 1111 0000 1001 1001 0101 0001 1010 1111 0111 1110 1001 Reprezentare n sistem hexazecimal 0xE000 0xE01F 0x0F09 0x951A 0xF7E9

Astfel, asamblnd cele 5 instruciuni ntr-o secven continu aa cum se prezint ea n memoria fizic de instruciuni, programul complet ar fi urmtorul :

E0 00 E0 1F 0F 09 95 1A F7 E9
Nu arat prea inteligibil, dar de ce ar fi ? Attiny25, sau orice alt calculator c veni vorba, nu trebuie s citeasc pe litere ca s tie c are deaface cu un ADD de pild + c dac ar face aa, atunci ar fi tare ineficient utilizat memoria. Fiecare liter sau reprezentare de cifr i are nevoie de octetul su, iar asta ar nsemna c numai pentru instruciunea ADD R16, R17 ar fi necesari 12 octei n loc de 2 ct o cere cazul real. Inadmisibil! Cu aceste valori n memorie, creieraul nu trebuie dect s aduc la fiecare unitate de timp cte o instruciune, s o interpreteze i analizeze i s o execute, i cu asta basta.

62

Instruciunea i consum efectul, iar aplicaia nainteaz la urmtoarea valoare, ciclul relundu-se ori de cte ori este necesar. Aceast analiz nu ne-a ajutat dect s vedem modul n care efectiv sunt stocate n memorie intruciunile propriu-zise. Cunoscnd acest lucru, ne este mai uor s nelegem limitele fizice ale memoriei i suntem, prin urmare, mai precaui atunci cnd scriem o secven de instruciuni. Vedei voi, dei vocabularul este unul permisiv, tot constrngerile fizice, din realitate sunt cele care ne ridic probleme. Mereu au fost ... Cu acestea fiind spus, sper

c ni s-au alturat i cei care nu au dorit s urmreasc subiectul ca s putem continua cu un ultim subiect de interes
general nainte de a discuta i nva, pe instruciuni, restul de capaciti ale lui Ale. n cele ce urmeaz vom vorbi cte ceva despre modulele ce ni le pune la dispoziie Attiny-ul. Nu vom sta mult pe ele pentru c le vom discuta pe-ndelete, utiliznd exemple practice, n seciunile nu foarte ndeprtate.

Un pic despre modulele lui Attiny25 ...


Am vorbit despre memorie i am vorbit despre instruciuni. Ar fi suficient s trecem s discutm exemple de cod dac nu ar exista o singur problem : n exemplul sumei de mai sus, cum facem cunoscut valoarea lui R16 ctre lume? Adic, este foarte bine c Attiny-ul o tie, dar parc ar fi util i ca noi s o aflm din moment ce ne-am chinuit s concepem paii respectivi, nu considerai ? Este clar avem nevoie de module! tii voi : acele regiuni de circuit comandate de ctre creiera care ne dau diferite funcionaliti cum ar fi posibilitatea de a ine evidena timpului sau capacitatea de a discuta cu mediul. Le-am mai abordat noi, la modul general, ntr-o seciune anterioar. Din punct de vedere al modulelor interne, creatorii creieraului nu au dus lips de imaginaie. Ba din potriv, n capsula aceasta mic cu 8 pini au reuit s introduc, pe lng nucleul rumegtor de instruciuni i memoria asociat lui, i : 1. un ceas cu spaiu alocat numrrii de 8 bii 2. alt ceas cu aceeai limitare fizic la numrare, dar capabil de viteze mai mari 3. un canal universal de comunicaii1 4. un modul capabil s ia semnalele continue i armonioase din mediu i s le asocieze o valoare binar pentru a putea fi utilizat n aplicaia proprie2 5. capacitatea de a citi temperatura de la un modul intern 6. un ceas cu rol de cine de paz pentru codul executat3 7. o serie de moduri de consum redus pentru o gestionare mai bun a puterii consumate de circuit

modulul se numete, n englez, : Universal Serial Interface, USI pe scurt, i este folosit pentru a comunica i a mprti informaii ntre mai multe creierae 2 modulul poart de numirea de convertor analogic-digital : Digital to Analog Converter, n englez i abreviat DAC 3 n englez : WatchDog cu prescurtarea WDT. Dac este folosit corect, asigur, aa cum am scris, deblocarea unei aplicaii

63

i cred c acestea sunt toate. Sper c nu am uitat nimic. Toate aceste module ofer plcuei posibilitatea de a face lucruri foarte interesante, dup cum vom vedea. Gata, cred c am discutat destul i nelegem suficient ct s ncepem mult ateptatele exerciii practice direct pe plcu. Punei-v centura de siguran pentru c ne ateapt o curs pe cinste!

Ale cunoate lumea!


Tot ce am nvat n rndurile precedente ne-a adus n acest punct. Cunoatem cum funcioneaz un calculator, cunoatem de ce are nevoie pentru a funciona un calculator, tim ce conine plcua Ale i i cunoatem limitrile de memorie/vitez la care funcioneaz ea. De asemenea, am vzut un tabel cu toate instruciunile ce le tie creieraul Attiny25 de pe Ale. Mai mult, am nceput chiar s vedem cum am putea folosi instruciunile pentru a face o prim aplicaie util pe care am analizat-o n fel i chip pentru a vedea : 1. ct de rapid este ea i 2. cum se prezint ea n mica memorie a creieraului Cu aceste lucruri tiute, ncepem discuia de a trimite efectiv instruciunile pe Ale i de a programa plcua n sine. Pentru a face acest lucru, trebuie mai nti s nelegem care este drumul pe care-l parcurg instruciunile de la o form ct de ct citibil de genul : LDI R16, 0 LDI R17, 15 pas_3: ADD R16, R17 DEC R17 BRNE pas_3 la forma final din memoria creieraului : E0 00 E0 1F 0F 09 95 1A F7 E9 Ei bine, pentru ca acest lucru s se realizeze avem nevoie de 2 aplicaii : 1. o aplicaie care s transpun instruciunile din forma citibil n forma redus, optim pentru Ale (aceast aplicaie mai poart denumirea de compilator, i aa o vom referi de acum ncolo) 2. o aplicaie prin care rezultatul dat de compilator este trimis spre creieraul de pe Ale pentru a se executa (acest tip de aplicaie poart denumirea de programator) Dac ar fi s ilustrm grafic modul prin care textul scris de noi ajunge s fie executat pe Ale, atunci imaginea urmtoare ar ajuta :

64

Practic, prima i prima dat dup ce am scris textul, el trece prin ceea ce noi am numit compilator. Compilatorul are sarcina de a-l cura (prin eliminarea comentariilor, de pild, care oricum nu sunt de folos) i de a nlocui etichetele cu adrese fizice pe baza crora vor fi completate instruciunile. Dup aceea, folosind un tabel asemntor cu cel descris de noi la ultima anliz, se genereaz secvena de octei care va fi neleas de creiera. Mai departe, programatorul, cealalt aplicaie din acest lan, ia rezultatul compilatorului i-l trimite efectiv spre plcu, iar plcuta ncepe imediat s execute instruciunile respective. n felul aceste ajunge textul scris de noi s fie executat de Attiny. Desigur c cele 2 aplicaii sunt destul de puternice : compilatorul poate s ne avertizeze cnd am greit ceva n faza de text i tie s genereze cod pentru mai multe tipuri de creierae n mai multe feluri (nivele de optimizare), iar programatorul tie la rndul su s comunice cu mai multe plcue gen Ale. Pentru a folosi doar opiunile lor care ne sunt nou utile cnd lucrm cu Ale, am creat psAle (programatorul Ale). Practic, folosind aceast aplicaie proprie, nu mai trebuie s-i specificm compilatorului pentru cine generm octeii respectivi i nici programatorului ctre ce plcu dorim s trimitem aplicaia rezultat. Totul se face n mod automat de ctre micul nostru progrmel. Pentru mai multe detalii privind psAle, v sugerez s urmrii instruciunile din extensia cruliei pe care le gsii la sfritul ei. Acolo vei gsi informaii suficiente pentru a lucra cu aplicaia att la nivel de nceptor, ct i la nivele mai ridicate. Revenind acum ar fi probabil momentul cel mai bun s conectai plcua la calculator i s pornii programul psAle dac nu a-i fcut-o deja. Pentru asta avei nevoie de cablul su sau de unul asemntor. Gsii un loc USB liber, ataai cablul la plcu i cellalt capt la calculator i gata. Dac totul este n regul, vei vedea cum Ale v salut printr-un joc frumos de lumini. Aceasta este o aplicaie cu care a fost ncrcat plcua nainte de a fi livrat ctre dumneavoastr. Rbdare, cci vei nva chiar voi s realizai aceste jocuri de lumin mpreun cu multe alte lucruri interesante. Pentru moment, avem plcua conectat la calculator i avem aplicaia psAle pornit. Haidei s scriem prima noastr aplicaie.

[1s] Ale, f nimic!


V rog observai formatul subtitlului. l vom folosi la toate exemplele noastre. n subtitlu avem un numr (n cazul nostru, o cifr chiar) care indic o ordine. Pe msur ce vom nainta spre exemple mai complicate, acest numr va crete. Apoi, avem litera s. s vine de la asm sau limbaj de asamblare care reprezint un mod de a scrie aplicaii primitiv, dar foarte puternic. Acest mod utilizeaz instruciunile pe care le-am introdus n marele tabel i cu care ne-am obinuit n ultimul exemplu. Mai trziu, vom vedea c poate exista i un c. cul va veni de la limbajul C, o modalitate mai uoar de a programa, dar care poate ascunde anumite detalii de implementare. Din acest motiv, pentru a avea controlul total asupra codului generat, vom ncepe cu s-uri. Gruparea numr-liter ne ajut s gsim mai uor exemplul n aplicaia psAle. Ultima parte a subtitlului reprezint o serie de cuvinte cheie prin care ne putem da seama cam ce va face codul respectiv. n acest sens, ncepem cu o bucat de cod corect din punct de vedere al limbajului, dar care nu face nimic. ncepem aa pentru a nelege scheletul ce-l va conine toate aplicaiile noastre de acum nainte. Ce rost ar avea s ncepem direct cu jocul de lumini dac nu am nelege lucrurile de baz ?

65

Putei selecta codul 1s din lista de exemple a lui psAle, iar eu voi discuta aici ce conine el. Voi vei vedea un cod comentat n detaliu, iar eu, de cele mai multe ori, voi omite respectivele comentarii urmnd s vin cu alte variante care s explice codul dintr-o alt perspectiv. Totul pentru a uura nelegerea lui. Aadar, codul pentru 1s golit de comentarii arat n felul urmtorul : .section .text .global main main: rjmp main Hopa! Ce avem aici ? n afar de main: rjmp main care reprezint un salt la aceeai instruciune realizat de o infinitate de ori (la nesfrit), primele 2 linii de cod nu reprezint nicio instruciune a creieraului. Bucla infinit1 este necesar pentru a ine codul sub control. Dac nu ar fi ea, din cauza restului memoriei, Ale ar ncerca s interpreteze valori de octei neprogramai de noi i ar da peste instruciuni nedorite. n felul acesta, prin blocarea execuiei ntr-un sigur punct, evitm acest comportament. Totui, ce se ntmpl aici n primele 2 linii ? Ei bine, cele 2 cuvinte cheie .section i .global reprezint cerine ale limbajului i sunt ateptate de ctre compilator. .section specific compilatorului c urmtoarele instruciuni vor fi plasate n zona de comenzi a memoriei (asta nseamn acel .text). Compilatorul vede, prin propria-i dorin, spaiul de instruciuni ca fiind fragmentat n regiuni precum zona variabilelor globale, neiniializate sau zona de instruciuni. Este un lucru pur convenional i oarecum aduce o ordine la codul final de pe creiera. Real vorbind, aceste regiuni nu au nicio semnificaie pentru Attiny, dar compilatorul o cere explicit specificat, iar noi i-o furnizm. Cealalt enigm e dat de .global. .global ntiineaz compilatorul c punctul de intrare al aplicaiei o reprezint adresa dat de eticheta main. Acest punct de intrare reprezint adresa de unde ncep s se execute instruciuni imediat dup alimentarea plcuei sau dup resetarea ei prin butonul de reset. Cam att despre scheletul aplicaiei. Pe msur ce se vor complica exemplele, vom aduga instruciuni completnd aceast ablon. Putei s scriei codul pe plcu. n urma transferului, s-ar putea ca toate cele 8 LED-uri nirate n linie s se aprind sau, din contr, s rmn stinse. n tot cazul, jocul iniial de lumini se va ncheia, iar aplicaia care realiza acest efect se va terge fiind nlocuit de noua aplicaie, 1s-ul nostru. Aceasta este treaba programatorului care este comandat de psAle. Motivul pentru care, n urma transferului lui 1s pe plcu, cele 8 LED-uri fie rmn toate pornite (cel mai probabil) fie se sting toate, este unul electric : nemaifiind nimeni care s le comande (aplicaia noastr nu spune nimic referitor la ce ar trebui s fac LED-urile), ele
1

aa se mai numete un ciclu de execuie care nu se oprete niciodat

66

rmn n aer. Unde n aer nseamn ntr-o stare nedefinit. Dac avei minile uscate putei s vede acest lucru : atingei cu un deget uscat picioruul aflat sub bulinua din colul dreptunghiului sau circuitului integrat, ca s fim mai coreci, 74HC164. l vei gsi undeva lng cele 8 LED-uri. Dac totul este n regul, vei vedea cum LED-urile o iau razna fiind influenate de degetul dumneavoastr. i asta, dragii mei, nseamn n aer. Cam att cu acest prim exemplu. Nu a fost unul complex s spunem c am lucrat cu regitrii de control sau cu periferice, dar a fost unul introductiv n care am dictat creieraului s se comporte aa cum dorim noi. n urmtoarea bucic de cod vom introduce o serie de instruciuni pentru a ne acomoda n continuare cu aplicaia noastr psAle. S continum

ntrebri / Exerciii : 1. Conteaz dimensiunea literelor atunci cnd scriem instruciuni pentru Ale ? 2. ncercai urmtorul cod : .section .text .global alta_eticheta alta_eticheta: main: RJMP main Ce credei c se ntmpl n acest caz ? De unde ncepe s se execute prima instruciune a aplicaiei ?

[2s] Iniializarea registrelor generale pe Ale


S analizm urmtorul exemplu : .section .text .global main main: ldi R16, 20 ldi R17, 0x0F ldi R18, 0b00001111 ldi R19, (1<<5) ldi R20, (0b00010000 | 0b00000001) ldi R21, (((21 + 3)*4)-10) / 2 rjmp main Diferena dintre 2s i 1s o reprezint acele 6 instruciuni de ncrcare a valorii imediate n registrele dorite. Ceea ce am vrut s subliniem prin aceste prime instruciuni a fost modul n care pot fi scrise constantele ce le dorim ncrcate. Practic, din pricina compilatorului, la cele 6 instruciuni avem tot attea moduri de a scrie o valoare constant pe care compilatorul o calculeaz nainte de a o transpune n octeii instruciunii : 1. ldi R16, 20 : urmree ncrcarea unei constante exprimate zecimal

67

2. ldi R17, 0x0F : ncrcm o constant exprimat n sistem hexazecimal (15 n baza 10) 3. ldi R18, 0b00001111 : acelai lucru, dar cu un numr n sistem binar (baza 2) 4. i mai rmn : a. ldi R19, (1<<5), b. ldi R20, (0b00010000 | 0b00000001) i c. ldi R21, (((21 + 3)*4)-10) / 2 . n afar de punctul a, restul de expresii ar trebui s v fie cunoscute. La punctul a nu facem altceva dect s lum valoarea 1 exprimat n binar i s i adugm atia bii de 0 n dreapta sa cte ne indic numrul din dreapta semnului <<1. n exemplul nostru, 15=0b000000012 5=0b001000002=3210 Toate ilustreaz diferite moduri avansate de a ncrca rezultatele unor operaii complexe pe care compilatorul le rezolv nainte de a construi octeii nelei de creieraul lui Ale Desigur c prin trimiterea codului ctre plcu nu vom vedea ceva diferit fa de ceea ce am vzut la 1s : LED-urile tot nu le controleaz nimeni, iar butoanele nici nu intr n discuie deocamdat. Totui, exemplul este unul bun pentru c ne introduce un pic n puterea compilatorului; plus c am vzut i o utilizare direct a instruciunii LDI. V rog observai cum instruciunile sunt scrise toate cu litere mici de fapt, compilatorul este suficient de detept s nu fac diferena dintre litere mici i litere mari, amndou fiind la fel de acceptate att pentru instruciuni, dar i pentru denumiri de regitrii. Noi, dei am folosit litere mari cnd am introdus instruciunile pentru a fi citite mai uor, vom folosi litere mici n exemplele ce urmeaz pentru a mai restrnge din cod i a-l face mai prietenos. O ultim remarc la acest exemplu ar fi faptul c respectiva iniializare a celor 6 regitri generali (R16 : R21) se face ntr-o manier continu ntr-o bucl infinit. V las pe voi s judecai utilitatea acestei abordri i v sftuiesc s nu uitai c exist posibilitatea introducerii a orict de multe etichete dorim pentru c ele oricum nu ajung, n faza final, pe plcu. Pn acum, totul este bine i frumos Am vzut c merge s scriem instruciuni din tabel i s le trimitem spre Ale, dar cum vedem efectiv c ceea ce scriem pe Ale chiar funcioneaz ? Ar fi util dac am putea-o programa pe Ale s ne comunice care este stare sa actual. n urmtoarea bucic de cod, vom ncerca s facem exact acest lucru. Vom ncerca o prim abordare pentru a controla cele 8 LED-uri de care dispunem.

ntrebri / Exerciii : 1. Ce valoare va avea R16 dup urmtoarea secven de instruciuni ? ldi R15, 4 ldi R16, 5 ror R15
operaia se mai numete deplasare binar la stnga. Pentru cultura voastr general aflai c exist i o deplasare binar la dreapta. Un exemplu n acest sens ar fi expresia
1

413=0b001010012 3=0b00001012 =510 . Observa, de asmenea, cum deplasarea


propriu-zis nu ine cont de valoarea biilor scoi din numrul iniial.

68

add R16, R15 rol R16 subi R16, 1

[3s] Ale ne salut


n acest exemplu, vom introduce modul prin care Ale, prin cele 8 terminale electrice ale creieraului su, reuete s comunice i s controleze rndul de 8 LED-uri disponibil pe plcu. Siu c vei spune c am mai discutat acest aspect ntr-o seciune anterioar atunci cnd am abordat toate modulele prezente pe plcu, dar de data aceasta vom explica mai pe-ndelete modul prin care Ale devine efa modulului de LED-uri implementnd efectiv secvena de comunicare prin instruciuni. Datorit numrului redus de pini ce-l are creieraul, la momentul respectiv discutam de necesitatea introducerii unei componente intermediare prin care s putem face posibil comunicarea Attiny-ului cu cele 8 LED-uri ale modulului. Componenta respectiv era un circuit integrat 74HC164. Fiind un element esenial al conceptului, consider c este bine s-l analizm mai serios aici, chiar dac principiul de funcionare al modulului l-am urmrit i discutat atunci cnd am vorbit de facilitile oferite de plcua Ale la modul general . Aadar, n mod real, circuitul integrat arat n felul urmtor :

Aceasta este componenta fizic, dar pe noi ne intereseaz mai degrab comportamentul electric al componentei ca mai apoi s putem construi secvena de instruciuni prin care s putem controla LED-urile. Pentru aceasta vom introduce o simplifcare a imaginii i o vom trece ntr-o notaie mai util unei astfel de analize. Acestea fiind spuse, desenul urmtor ar putea fi un candidat bun n aceast direcie :

Diferena nu este una foarte mare, cele 2 imagini semnnd pn la un anumit punct chiar foarte bine. Ceea ce aduce n plus aceast imagine fa de precedenta const ntr-o

69

numerotare a pinilor n funcie de scopul lor n circuit. Mai departe, putem asocia cele 14 terminale electrice n grupri cu o funcionalitate precis i ncercm s facem acest lucru n urmtorul tabel : Denumire picioru GND, VCC1 A, B CP Q0, Q1, Q2, Q3, Q4, Q5, Q6, Q7 Intrare / ieire ? Intrare Intrare Intrare Ieire Intrare Explicaii Piciorue folosite la alimentarea circuitului Pini de date folosii pentru a ncrca valori electrice n circuit Terminal electric de tact folosit la ncrcarea valorilor electrice n circuit Piciorue prin care se poate colecta valorile pompate n circuit prin CP, A i B Pin care atunci cnd are aplicat pe el valoarea de 0 Voli (GND/0V), pune toate ieirile (Q7-Q0) pe 0 logic (cu potenial de 0 Voli fa de terminalul GND). Dac pe respectivul picioru avem plasat VCC (5 Voli) atunci resetarea nu are loc.

MR

nainte de a continua cu explicaiile, v rog observai coloana din mijlocul tabelului : Intrare/Ieire ?. Ea dicteaz modul n care respectivul picioru este folosit : dac este intrare, atunci lui trebuie s i se aplice valori logice traduse n tensiuni pentru a urmri efectul dorit, pe cnd dac este ieire, atunci el va reflecta (de pe el vom putea citi) starea curent a logicii din circuit. Noi ntotdeauna vom ncerca s utilizm pinii de tip intrare pentru a obine ceva la ieire. Ale folosete direct intrrile lui 74HC164 care sunt controlate de creiera pentru a obine aprinderea celor 8 LED-uri dup cum dorim. Haidei s continum Vom ncerca s explicm comportamentul circuitului integrat pornind de la aceste 5 categorii funcionale. n regul! Pentru a face asta, ne vom folosi, aa cum ne-am obinuit, de un exemplu: s presupunem c dorim s trimitem spre ieirile colectoare (Q7-Q0) secvena de tensiuni care corespunde valorii binare 0b10100011 i s obinem astfel urmtoarea stare a LED-urilor ntr-o interpretare de tensiuni Qi-GND cu i=0,7 Pin destinatar
3

. Asta se traduce redat de urmtorul tabel : Tensiunea rezultat ntre pinul destinatar i picioruul notat cu GND 5 Voli 5V

Valoare binar transmis

Q0 Q1
1

1 1

GND vine din englezescul Ground care nseamn mas n romn sau terminal de referin, iar VCC reprezint cellalt pin de alimentare, cel pozitiv (5 Voli). 2 aceast notaie barat ( a ) simbolizeaz faptul c respectivul simbol funcioneaz dup o logic inversat. n acest caz, adevrul este considerat valoarea de 0 logic (0 Voli), pe cnd falsul este considerat atunci cnd pe terminal este prezent tensiunea VCC (5 Voli sau 1 logic). 3 reprezint o notaie matematic condensat i citim i ia valori ntre 0 i 7, relaia Qi-GND putnd fi nlocuit cu secvena Q0-GND, Q1-GND, Q2-GND, , Q7-GND

70

Q2 Q3 Q4 Q5 Q6 Q7

0 0 0 1 0 1

0V 0V 0V 5V 0V 5V

Pentru aceasta, prima i prima dat vom alimenta circuitul ceea ce nseamn c vom folosi gruparea GND, VCC. Nu vom dori ca ieirile Q7-Q0 s fie trecute pe 0 logic (0 Voli), deci vom aplica VCC (1 logic) pe pinul notat MR . Mai rmn 3 categorii: intrarea de date din care fac parte picioruele A, B, intrarea de sincronizare/comand unde avem doar pin-ul CP i ieirile propriu-zise Q7-Q0. Datorit faptului c terminalele Q7-Q0 sunt ieiri, nu va trebui s aplicm niciun fel de tensiune pe respectivii pini, ba din contr: va trebui s punem n eviden prezena lor aa cum am vzut-o n tabelul de mai sus. Ori este evident cum am fcut asta pe Ale, nu ? Exact prin LED-uri! Prin urmare, mai avem 2 categorii de semnale pe care nc nu le-am conectat la nimic. S vedem ce facem cu ele Prima categorie reprezint intrarea de comand/tact CP. Modificnd, din exterior, tensiunea acestui pin de la 0 Voli la 5 Voli se intmpl urmtoarele lucruri n ordinea n care ele apar scrise : 1. Valoarea logic curent aflat la citirea picioruelor Q7-Q0 este deplasat binar cu o poziie n stnga, Q0, a crei valoare a fost notat q0, pentru a face diferena n notaii ntre denumirea pinilor i valoarea lor, ajunge s fie citit pe picioruul Q1, q1 q2, q2 q3, , q6 q7, iar q7 se pierde nemaiexistnd un q8 pentru a merge mai departe. Urmtoarea imagine surprinde aceast deplasare :

2. Valoare rezultat (vom vedea cum, ntr-o secund) din semnalele logice aplicate pe pinii A, B ajunge s fie ncrcat pe pinul Q0 rmas nedefinit i marcat cu ? n desenul precedent. Acest lucru este o consecin direct a deplasrilor realizate la punctul 1. Intrrile de date A, B trec intern printr-o poart I ce dicteaz valoarea ce ajunge n Q0 la momentul tranziiei de pe 0 logic pe 1 logic a terminalului CP. De ce sunt 2 pini i nu unul, v ntrebai? Probabil cei ce au construit circuitul 74HC164 s-au gndit c introducerea unei astfel de pori mrete plaja de posibiliti a respectivei componente. Este o practic des utilizat pentru a mri gradul de utilizabilitate a unui circuit, dar care pe noi nu ne prea afecteaz.

71

Ei bine, ca i o scurt recapitulare, valorile logice date de o poart I pot fi citite din urmtorul tabel : A 0 0 1 1 B 0 1 0 1 A I B (rezultatul ajunge s fie ncrcat n Q0 n condiiile discutate mai sus) 0 0 0 1

Denumirea semnalelor a fost intenionat aleas aceasta pentru a lega interpretarea logic de pinii circuitului 74HC164. Cum se poate observa, n funcie de valorile aplicate pe intrrile de date A, B, Q0 va avea, la urmtoarea tranziie din 0 n 1 logic a pinul CP, valoarea urmrit. Vom vedea care sunt aceste valori urmrite de exemplul nostru ntr-o secund. Deocamdat ne deranjeaz faptul c trebuie s controlm 2 semnale de date i un semnal de tact 3 pini cu ajutorul creieraului nostru care are i-aa un numr foarte limitat de terminale : 8, din care 6 sunt efectiv controlabile (2 fiind folosite pentru alimentare). Desigur c beneficiul controlrii a 8 LED-uri din 3 piciorue este imediat i evident, dar se poate mai bine ? Dac nu era ntrebarea, nu era nici rspunsul. Rspuns : Evident c da!, se poate mai bine! Putem reduce numrul de pini pentru comunicarea creieraafiaj la doar 2 (unul de date i unul de tact) dac facem urmtoarea observaie : S zicem c pinul B l fixm mereu la valoarea de 1 logic. Cum afecteaz asta modul de comportament al valorii ncrcate ? Ei bine, dac urmrim tabelul de adevr, atunci cnd terminalul B este 1, valoarea rezultat urmrete i este dictat DOAR de valoarea pinului A. Super! Asta este exact ce ne dorim: Dac legm pinul B la VCC (1 logic), valoarea ncrcat va fi influenat doar de valoarea logic a pinului A, elibernd necesitatea de a folosi un pin preios de pe creiera, dar pstrnd efectul dorit! O alt variant folosit chiar de plcu o reprezint utilizarea n comun a celor dou intrri. La ce m refer aici cnd spun utilizare n comun ? Ei bine, m refer la lipirea fizic a celor 2 terminale i folosirea lor ca unul singur n circuit. Putem face acest lucru dac observm faptul c rezultatul porii I este 1 logic doar atunci cnd A=B=1 i 0 logic n caz contrar adic fie atunci cnd A=B=0 , dar i atunci cnd AB . Am ales aceast soluie n defavoarea celeilalte pentru a uura construcia plcuei : este mai complicat s caui i s aduci fizic VCC-ul la circuit dect s uneti cei 2 pini i s foloseti aceast configuraie care oricum va trebui s ajung la creiera pentru a putea comanda afiorul. Extraordinar! Avem posibilitatea de a controla aprinderea a 8 LED-uri prin doar 2 pini! Mai bine nici c se putea n felul acesta avem piciorue libere ale creieraului pentru restul de module. i acesta este modul de funcionare a circuitului 74HC164. Cu aceste explicaii, s revenim i s rezolvm exemplul nostru iniial : aprinderea LED-urilor dup tiparul dat de urmtoarea secven de bii : 0b10100011 (unde 1 reprezint aprins i

72

0 reprezint stins). Observm c, datorit deplasrilor spre stnga la fiecare tranziie, vom avea nevoie de 8 tranziii pentru fiecare valoare binar n parte, iar biii trimii ctre 74HC164 vor fi de la cel mai semnificativ (cel cu rang 7) la cel mai puin semnificativ (rang 0). Secvena urmtoare definitiveaz exemplul propus : 1. Iniializm semnalul de tact pe o valoare cunoscut (de 0 logic, spre exemplu) 2. Punem pe pinul A valoarea bitului de pe rangul 7 din exemplu : 1 logic (LED aprins) 3. Realizm tranziia terminalului CP (din 0 n 1 logic) pentru a realiza deplasarea Q7Q0 i a ncrca noua valoare (1 logic) la ieirea lui Q0 apoi aducem valoarea semnalului la 0 logic pentru a-l pregti pentru urmtorul bit 4. ncrcm pe terminalul A valoarea bitului aflat pe rangul 6 din exemplu : 0 logic 5. Pulsm linia de CP pentru ca deplasarea Q7-Q0 spre stnga s se realizeze (Q0 care avea valoarea precedent de 1 ncrcat ajunge s-i deplaseze informaia n Q1 ceea ce nseamn c Q1 va avea valoarea vechiului Q0 adic 1 logic), iar Q0 ia valoarea pinului A care am ales s fie 0 logic 6. [+ nc 6 astfel de tranziii scznd rangul bitului din octetul ce urmeaz a fi transmis] i cam att n finalul celor 8 pulsri a pinului CP, Q7-Q0 va avea valoarea 0b10100011. nainte de a vedea cum putem controla circuitul 74HC164 din instruciunile ce ne sunt puse la dispoziie de creieraului lui Ale, trebuie s precizm faptul c acest tip de comunicare bit cu bit sincronizate de un semnal de tact este foarte des ntlnit n lumea electronicii i poart denumirea de comunicare serial. Poate de aceea, nu este de mirare faptul c, circuitul 74HC164 poart denumirea de 8-Bit Serial-In, Parallel-Out Shift Register1. Aadar, 2 pini 8 LED-uri. Nu este ru deloc! Dar cum putem folosi plcua, respectiv Attiny-ul de pe ea ca s imite aceast secven i, chiar mai mult, s afieze orice secven binar de 8 bii dorit ? Cu alte cuvinte, ce secven de instruciuni va trebui s alegem pentru creiera (din tabelul cel mare) pentru a face acest comportament vizibil ? Ei bine, pentru a face acest lucru, va trebui s introducem n discuie 2 registre de control care se ocup de starea semnalelor la ieire. Din cauza faptului c orice pin controlabil al creieraului poate fi acionat n mod independent fie ca intrare (se pot citi valori prin el, util n cazul minitastaturii), fie ca ieire (poate trimite valori n exterior, util n cazul afiajului cu LED-uri), vom avea un registru de direcie numit DDRB2 i un registru prin care vom trimite efectiv valorile logice dorite ctre pinii dorii, PORTB3.

n traducere romneasc : Registru de deplasare de 8 bii cu intrare serial i ieire paralel. Este un registru de deplasare deoarece ndeplinete funcia de deplasare la stng amintit i are capacitatea de a pstra valorile dorite la ieirile sale Q7-Q0 att timp ct circuitul este alimentat. Ghicii de ce este cu ieire paralel ? 2 abreviere pentru Data Direction Register B, aa cum se gsete n literatura englez, care se traduce n limba romn prin Registru de direcie al portului B. Litera B a fost aleas pentru c i alte creierae cu mai multe piciorue au acelai registru n acelai loc din memorie. Acest lucru s-a realizat n scopul compatibilitii codului, aa cum discutam ntr-o seciune anterioar. 3 abreviere pentru Port B, registru care controlez valorile de ieire ale portului (grupului) cu litera B
1

73

Registrul de direcie DDRB este situat la adresa 0x0017 n spaiul regitrilor de control (0x0017 + 0x0020 = 0x0037 n spaiul real de memorie, valoare corect pentru domeniul fizic al registrelor speciale : 0x0020 - 0x005F), iar biii si au urmtoare semnificaie : Rang Notaie Op. permise Val. iniial
7 6 5 4 3 2 1 0

--C 0

--C 0

DDB5 S/C 0

DDB4 S/C 0

DDB3 S/C 0

DDB2 S/C 0

DDB1 S/C 0

DDB0 S/C 0

Unde literele de la notaie au urmtoarele semnificaii : Denumire --Nume complet Nefolosit Semnificaie Bitul respectiv nu are nicio utilizare electric de aceea el nu poate fi dect citit (C), iar valoarea mereu citit va fi 0 logic. Un 1 logic precizeaz faptul c pinul respectiv este folosit ca i ieire pe cnd un 0 logic spune c se vor citi valori logice de pe acel pin din aplicaie.

DDB5 DDB0

Direcia de utilizare a pinului PBi cu i=0,5

DDRB-ul va fi util n faza de iniializare a circuitelor, nainte de a scrie ceva pe LED-uri, de pild. Urmtorul registru este registrul de date PORTB care este situat la adresa 0x0018 n spaiul regitrilor de control (0x0018 + 0x0020 = 0x0038 n spaiul real de memorie, valoare corect pentru domeniul fizic al registrelor speciale : 0x0020 - 0x005F), iar biii si au urmtoare semnificaie : Rang Notaie Op. permise Val. iniial
7 6 5 4 3 2 1 0

--C 0

--C 0

PORTB5

PORTB4

PORTB3

PORTB2

PORTB1

PORTB0

S/C 0

S/C 0

S/C 0

S/C 0

S/C 0

S/C 0

Unde literele de la notaie au urmtoarele semnificaii : Denumire --Nume complet Nefolosit Semnificaie Bitul respectiv nu are nicio ntrebuinare electric de aceea el nu poate fi dect citit (C), iar valoarea mereu citit va fi 0 logic. Un 1 logic precizeaz faptul c pinul respectiv va msura VCC (5V) la ieire pe cnd un 0 logic trimite 0 Voli la ieire.

PORTB5 PORTB0

Valoare logic a pinului PBi cu i=0,5

Am tot folosit PBi cnd am explicat cei 2 regitrii pe care i vom folosi. Corespondena fizic ntre PBi i pinii creieraului poate fi urmrit din desenul urmtor :

74

Ale folosete urmtoarele conexiuni (PBi-uri) cu circuitul 74HC164 : Terminal 74HC164 Terminal Attiny Date PB1 CP PB0

Acestea fiind spuse, avem toate elementele necesare creerii unei secvene de instruciuni pentru a controla cele 8 LED-uri de pe plcu. Vom ncepe mai nti prin a iniializa pinii ce vor fi folosii pe post de ieire pentru creiera. Vom face asta prin urmtoarea secven de instruciuni :
; ncrcm n registrul R16 o valoare prin care PB0 i PB1 vor fi folosii ca i ieire

ldi R16, 0b00000011


; trimitem spre portul de direcie B, valoarea ce se afl n registrul R16

out DDRB, R16


; ncrcm n R16 o valoare prin care toate ieirile vor fi iniial puse pe 0 logic

ldi R16, 0b00000000


; trimitem spre ieirea portului B, valoarea ce se afl n registrul R16

out PORTB, R16 Acum, dup iniialiare, s lum n discuie un exemplu simplu. Considerm c dorim s trimitem un 0 pe Q0, iar Q7-Q1 nu ne intereseaz ce valoare vor avea. Pe baza a ceea ce tim, am putea face lucrul acesta prin urmtoarea secven de instruciuni :
; resetm pinul de date pentru a mpinge spre afiare un 0

cbi PORTB, PB1


; trecem linia de tact a creieraului pe 1 pentru ncrca valoarea din PB1 n Q0

sbi PORTB, PB0


; aducem linia de ceas la 0 pentru a-i menine starea iniial

cbi PORTB, PB0 i cam asta este tot. Codul complet obinut ar fi urmtorul : DDRB = 0x17 ; definim registrul care controleaz direcia portului B PORTB = 0x18 ; definim registrul care controleaz datele trimise ctre portul B PB0 = 0x00 ; definim valoarea pinului 0 relativ la PORTB PB1 = 0x01 ; definim valoarea pinului 1 relativ la PORTB .section .text .global main main:
; === INIIALIZM PERIFERICUL DE INTRARE/IEIRE ===

75

; ncrcm n registrul R16 o valoare prin care PB0 i PB1 vor fi folosii ca i ieire

ldi R16, 0b00000011


; trimitem spre portul de direcie B, valoarea ce se afl n registrul R16

out DDRB, R16


; ncrcm n R16 o valoare prin care toate ieirile vor fi iniial puse pe 0 logic

ldi R16, 0b00000000


; trimitem spre ieirea portului B, valoarea ce se afl n registrul R16

out PORTB, R16


; === TRIMITEM SPRE Q0 UN 0 LOGIC ===
; resetm pinul de date pentru a mpinge spre afiare un 0

cbi PORTB, PB1


; trecem linia de tact a creieraului pe 1 pentru ncrca valoarea din PB1 n Q0

sbi PORTB, PB0


; aducem linia de tact la 0 pentru a-i menine starea iniial

cbi PORTB, PB0 executa_vesnic: rjmp executa_vesnic ; bucl infinit Rezultatul ? Ori de cte or se execut aceast secven, vom avea garania c LED-ul corespunztor pinului Q0 (situat, cel mai probabil, n dreapta-sus pe plcu) va fi NCHIS. Q0 va fi nchis, dar de unde tim noi c secvena chiar se execut? Pentru a demonstra c ntr-adevr instruciunile noastre au efect asupra mediului nconjurtor vom urmri ceea ce se numete o captur de osciloscop1 a semnalului de pe pinul PB0 (CP-ul lui 74HC164). Aceasta arat in felul urmtor :

Poate v ntrebai ce vedem noi aici ? Ei bine, imaginea este plin de informaii. Aa cum v ziceam, noi monitorizm tensiunea pinului PB0, iar graficul arat exact acest lucru. Pe lng tensiunea propriu-zis, putem observa i o serie de msurtori de timp (de la tranziia pe 1 logic la tranziia pe 0 logic) dat de urmtoarele instruciuni : sbi PORTB, PB0 cbi PORTB, PB0 , singurele responsabile de apariia acestui grafic. De altfel, una din msurtori (este vorba de x , prezent n chenarul din dreapta sus) ne arat dimensiunea efectiv a impulsului
Osciloscopul este un aparat de msur electric prin care se pot observa modificri foarte rapide de tensiuni.
1

76

CP. Nu e de mirare c aceasta este de aproximativ 2 s ( 1.96 s , ca s fim mai exaci). Practic, dac ne vom uita n tabelul acela mare de instruciuni prezentat ntr-o seciune anterioar, vei vedea c respectivele comenzi, SBI i CBI, necesit fiecare o unitate de timp. Ori, aa cum ai primit creieraul, aceast unitate este de aproximativ 1 s . Diferena de 0.04 s dintre aceast msurtoare i valoarea calculat se datoreaz mai multor factori : baza de tact a creieraului nu este de exact 8Mhz, iar osciloscopul, ca orice aparat de msur, introduce i el o eroare de msurtoare. Totui, 0.04 s este o abatere nesemnificativ pe care o putem ignora. Alte informaii prezente n imagine sunt : 1. n bara de jos : tensiunea de referin la care a fost realizat msurtoarea (stnga : 2.00V) i baza de timp de referin care fragmenteaz dimensiunea orizontal n 500ns (nanosecunde! 1ns=0.001 s ) 2. n bara de sus : tensiunea de prag peste care se consider c un eveniment a avut loc pe canalul de msurare i c nregistrarea canalului poate s nceap (dreapta, sus : 1.20V). Tot ce este mai mic fa de aceast valoare este ignorat de ctre aparatul de msur. 3. Alte elemente de finee msurate, dar neimportante pentru cauza noastr. Desigur c putem tri i fr aceste explicaii. Le-am introdus aici doar pentru cei curioi. Pe noi ne intereseaz, n acest exemplu precum i n alte capturi ce le vom realiza, (vor mai fi i altele pentru c este singurul mod de a evidenia efectele fizice ale codului nostru) forma semnalului aa cum prsete el terminalul msurat precum i unele msurtori de timp. Gata! Cred c am stat suficient pe acest subiect. tii ce este ciudat ? Q0 poate fi nchis, dar ce facem cu celelalte LED-uri ? Frumos ar fi s afim exact secvena ce o dorim noi, nu un singur LED. Nu asta am discutat c vom face la nceput! Avei dreptate, i lucrul acesta l vom aborda n seciunea urmtoare ntrebri / Exerciii : 1. Care sunt cei 2 regitrii folosii pentru a comunica cu afiorul lui Ale ? 2. De ce sunt 2 intrri de date A, B pe circuitul 74HC164? 3. Scriei o secven de instruciuni pentru a afia ultimul bit (bitul cu index 7) din registrul R16 pe afior. 4. n codul de mai sus : Funcioneaz el fr instruciunea cbi PORTB, PB0 ? De ce ?

[4s] Ale ne salut mai frumos i mai complet


n exemplul precedent am vzut cum putem trimite un bit spre LED-uri. Haidei s continum i, folosind exerciiul utilizat atunci cnd am analizat circuitul 74HC164, s afiam pe LEDuri, conform secvenei de pai discutate, valoarea 0b10100011. Pentru asta, vom lucra pe codul precedent, multiplicnd instruciunile de interes pentru a atinge scopul urmrit. Codul astfel rezultat, un pic mai curat dect precedentul, este urmtorul : DDRB = 0x17 PORTB = 0x18 PB0 = 0x00 PB1 = 0x01 .section .text

77

.global main main:


; === INIIALIZM PERIFERICUL DE INTRARE/IEIRE ===

ldi R16, 0b00000011 out DDRB, R16 ldi R16, 0b00000000 out PORTB, R16
; === TRIMITEM SPRE 74HC164 SECVENA 0b10100011 === sbi PORTB, PB1 ; trimitem bitul situat pe rangul 7 al octetului dorit = 1 sbi PORTB, PB0 cbi PORTB, PB0

cbi PORTB, PB1 ; trimitem bitul situat pe rangul 6 al octetului dorit = 0 sbi PORTB, PB0 cbi PORTB, PB0 sbi PORTB, PB1 ; trimitem bitul situat pe rangul 5 al octetului dorit = 1 sbi PORTB, PB0 cbi PORTB, PB0 cbi PORTB, PB1 ; trimitem bitul situat pe rangul 4 al octetului dorit = 0 sbi PORTB, PB0 cbi PORTB, PB0 cbi PORTB, PB1 ; trimitem bitul situat pe rangul 3 al octetului dorit = 0 sbi PORTB, PB0 cbi PORTB, PB0 cbi PORTB, PB1 ; trimitem bitul situat pe rangul 2 al octetului dorit = 0 sbi PORTB, PB0 cbi PORTB, PB0 sbi PORTB, PB1 ; trimitem bitul situat pe rangul 1 al octetului dorit = 1 sbi PORTB, PB0 cbi PORTB, PB0 sbi PORTB, PB1 ; trimitem bitul situat pe rangul 0 al octetului dorit = 1 sbi PORTB, PB0 cbi PORTB, PB0 executa_vesnic: rjmp executa_vesnic ; bucl infinit i stop joc dup ncrcarea pe plcu, LED-urile vor fi aprinse n exact secvena de 1 i 0 dictat de octetul nostru din exemplu.

78

Totui, nu pot s nu simt c ceva nu este n regul! Dei soluia noastr este una corect, avem o serie de nelmuriri : Trebuie s analizm fiecare octet ce vrem s-l trimitem spre afiare i s-i scriem secvena de instruciuni aa cum am vzut mai sus ? Nu putem s reducem din dimensiunea codului avnd n vedere c o mulime de instruciuni se repet ? Frumos i elegant ar fi ca noi s alegem un registru n care s ncrcm o valoare ce dorim s o afim apoi s apelm secvena de instruciuni prin care se face afiarea propriu-zis. Acest lucru ne propunem i asta urmrim n rndurile ce urmeaz. Primul pas n acest sens ar fi rezolvarea problemei cu duplicarea de cod : avem prea multe instruciuni care se repet! Pentru asta putem folosi instruciuni de salt condiionat. Programul astfel rezultat ar putea s urmreasc urmtorul set de pai pentru a afia o valoare de 8 bii pstrat, iniial, n R16 : 1. Iniializm o variabil contor (R17, de pild) pe 8 pentru a ine evidena biilor trimii spre LED-uri 2. Dac bitul cel mai semnificativ din R16 este 0 atunci trimite un 0 pe linia de date altfel seteaz un 1 pe linia de date 3. Pulseaz linia de tact pentru a fora circuitul 74HC164 s ia n eviden informaia de pe linia de date i s o trimit mai departe spre LED-uri 4. Deplaseaz spre stnga informaia din R16 5. Scdem o unitate din variabila contor pentru c am trimis un bit spre LED-uri 6. Dac variabila de control nu a ajuns la 0 (mai avem bii de trimis), atunci revino la punctul 2 i continu de acolo Dac traducem aceti pai ntr-o secven de instruciuni pe care Attiny-ul s o neleag atunci am putea obine un cod asemntor cu urmtorul: ldi R17, 8 ; iniializm R17 cu 8 pentru a o putea folosi ca variabil de control n ciclul urmtor ciclu_afisare: sbrc R16, 7 ; verificm dac bitul cu indice 7 din registrul ce-l dorim afiat este pe valoarea 0 sbi PORTB, PB1 ; dac nu, setm bitul de date de pe PORTB - afior pe 1 sbrs R16, 7 ; verificm daca bitul cu indice 7 din registrul ce-l dorim afiat are valoarea 1 cbi PORTB, PB1 ; dac nu, seteaz bitul de date de pe PORTB - afior pe 0 sbi PORTB, PB0 ; trecem linia de ceas a creieraului pe 1 pentru a semnaliza un impuls nop ; o mic pauz pentru a respecta timpii circuitului 74HC164 cbi PORTB, PB0 ; aducem linia de ceas la 0 pentru a propaga bitul de date pe afiaj lsl R16 ; rotim tot coninutul registrului R16 spre stnga rezultnd bit0 peste bit1, bit1 peste bit2, .a.m.d dec R17 ; scdem un 1 din valoarea curent a lui R17 i punem rezultatul napoi n R17 cpi R17, 0 ; comparm valoarea contorului R17 cu 0 pentru a vedea dac mai trebuie s trimitem bii spre
; LED-uri

brne ciclu_afisare ; dac R17 nu este egal cu 0 atunci srim inapoi la "ciclu_afisare" mai trimitem un bit Dup cum se poate observa, noul cod aduce 2 avantaje : 1. este alctuit din 12 instruciuni fa de 24 cte am avut nevoie atunci cnd nu am folosit ciclii. n acest fel obinem o mbuntire a spaiului utilizat de 50% ceea ce nu este de neglijat cnd vorbim de capacitile memoriei noastre. 2. prin introducerea lui R16 ca i variabil ce conine valoarea ce se dorete afiat, nu mai trebuie s construim noi manual secvena de instruciuni pentru aprinderea LEDurilor dup un anumit tipar. Avnd R16, este suficient s scriem un

79

ldi R16, 0b10100011


; sau

ldi R16, 163


; sau chiar

ldi R16, 0xA3 nainte de instruciunile de mai sus, iar efectul este ACELAI! Vedei frumuseea acestei metode ? Practic nici nu te intereseaz reprezentarea binar a valorii ce o dorim afiat c respectiva conversie din alte baze de numeraie i cea binar se face automat. Astfel, fr a folosi pix i hrtie, Ale ne poate arta cum s facem conversii din alte sisteme de numeraie n sistemul binar. Nu m credei ? Putei verifica i singuri folosind alte valori ... LED-urie sunt singurul mod de comunicare prin care Ale se poate exterioriza lumii ce o nconjoar. Este singurul, cu toate c creieraul suport i alte metode de comunicare; aici vedem limitrile plcuei. Acestea fiind spuse, noul nostru cod cu acelai efect ca precendentul (afieaz secvena 0b10100011 pe LED-uri) devine : DDRB PORTB PB0 PB1 = 0x17 = 0x18 = 0x00 = 0x01

.section .text .global main main: ldi R16, 0b00000011 out DDRB, R16 ldi R16, 0b10100011 ldi R17, 8 ciclu_afisare: sbrc R16, 7 sbi PORTB, PB1 sbrs R16, 7 cbi PORTB, PB1 sbi PORTB, PB0 nop cbi PORTB, PB0 lsl R16 dec R17 cpi R17, 0 brne ciclu_afisare executa_vesnic: rjmp executa_vesnic Cu toate c soluia noastr este una mult mai elegant fa de cea discutat iniial, apare o problem : ce facem dac ntr-o aplicaie avem de afiat mai multe valori n mai multe puncte din cod ? Adic da, am putea folosi o bucl mai mare n care s avem instruciunile de afiat i R16 s ia, pe rnd valorile ce se doresc afiate, dar asta nseamn c urmrim ca afiarea s se realizeze dintr-o singur zon de cod! Nu este prea bine. Am putea s

80

multiplicm secvena de instruciuni care realizeaz afiarea ori de cte ori am avea nevoie de ea, dar nu este nici elegant, nici plcut s privim instruciuni att de multe care fac acelai lucru. Dac motivul acesta nu este suficient, atunci gndii-v c problema spaiului revine: nu avem prea mult n creiera i cel pe care-l avem nu ne putem permite s-l risipim. Atunci ce putem face ? Discutam adineauri despre noiunea de apelare. Ce o fi nsemnnd aceast cuvnt apelare ? Simplu vorbind, spunem c apelm o regiune de cod atunci cnd folosim instruciunea RCALL i respectiv, la finalul secvenei de instruciuni apelate, instruciunea RET. n principiu, atunci cnd facem un apel prin instruciunea RCALL, creieraul face 2 lucruri : 1. ncarc pe stiv punctul de unde s-a fcut apelul i 2. sare la adresa de cod unde se afl instruciunile apelate. Odat cu ntlnirea instructiunii RET, aciunea se desfoar invers: folosind adresa de pe stiv, se face automat saltul n punctul de apel i execuia continu cu prima instruciune ce se afl dup RCALL. S ncercm s ilustrm aceast explicaie n mod vizual :

n felul acesta, folosind conceptul de apel (de subrutine, pentru a fi mai complet), putem s evitm situaii din acestea :

i s obinem o rearanjare mult mai plcut ochilor precum asta :

Mai mult, datorit faptului c folosim o singur instruciune RCALL pentru a realiza execuia instruciunilor de afiare, am rezolvat problema cu excesul de spaiu. Un alt beneficiu al acestei abordri cu apeluri este unul nu foarte evident la nceput, dar foarte important pe msur ce scriem din ce n ce mai multe aplicaii. S spunem c ne-am fcut o subrutin de apel care face citirea tastelor de pe mini-tastatur. Subrutina respectiv o apelm din mai multe puncte din codul nostru, dar aflm, la un moment dat c ceva nu este ntru totul corect la respectiva secven de instruciuni. Avnd toate instruciunile ntr-un singur loc, nu mai trebuie s cutm prin cod s reparm

81

FIECARE secven, ci este deajuns s ne uitm ntr-un singur punct i s aplicm soluia, singurul punct unde se afl efectiv instruciunile i anume n subrutin! Mult mai uor i mult mai elegant, nu credei ? Revenind Aplicnd acest nou concept nvat pe plcua noastr obinem, deocamdat, 2 subrutine : una pentru iniializarea perifericelor cu adresa dat de eticheta initializeaza_perif i una pentru afiarea propriu-zis a valorii din registrul R16 a crei instruciuni ncep de la adresa etichetei afiseaza_r16 Am ales s introducem o subrutin pentru iniializarea perifericelor pentru c, dup cum vom vedea, exemplele noastre se vor complica i va trebui s adugm instruciuni de acest fel pentru a ine pasul cu aceast complexitate. Cu aceste subrutine introduse, plcua Ale ne salut din nou un pic mai ginga, dar sigur mai plcut : DDRB PORTB PB0 PB1 = 0x17 = 0x18 = 0x00 = 0x01

.section .text .global main main: rcall initializeaza_perif ; apelm subrutina de iniializare a perifericelor utilizate de aplicaie ldi R16, 0b10100011 ; ncrcm n R16 valoarea pe care dorim s o afim rcall afiseaza_r16 ; apelm subrutina de afiare propriu-zis executa_vesnic: rjmp executa_vesnic initializeaza_perif: ; etichet de intrare n subrutina de iniializare a perifericelor ldi R16, 0b00000011 out DDRB, R16 ret ; prsim subrutina, totul fiind iniializat afiseaza_r16: ; etichet de intrare n subrutina de afiare push R17 push R16 ldi R17, 8 ciclu_afisare: sbrc R16, 7 sbi PORTB, PB1 sbrs R16, 7 cbi PORTB, PB1 sbi PORTB, PB0 nop cbi PORTB, PB0 lsl R16 dec R17 cpi R17, 0

82

brne ciclu_afisare pop R16 pop R17 ret ; prsim subrutina pentru c afiarea s-a realizat i cam asta este tot ce trebuie s stim despre apelarea de subrutine. V rog observai instruciunile de PUSH i POP care deschid, respectiv nchid subrutina afiseaza_r16. Aceasta este o practic obinuit n acele subrutine n care dorim ca starea registrelor generale s rmn aceeai dup ncheierea subrutinei. Realizm acest lucru cu operaii asupra stivei. Dac ne gndim bine, noi folosim R17 pe post de contor i asta nseamn c, dac nu avem grij, putem distruge ce se afla n R17 la momentul apelului, ori poate acest lucru nu este, de cele mai multe ori, cel urmrit de noi. De aceea, ca bun practic, pentru toate registrle pe care le folosim n cadrul unei subrutine este indicat s salvm undeva (pe stiv e cea mai elegant soluie) valoarea lor iniial i s o restaurm la momentul ncheierii subrutinei. nainte de finalul seciunii, am realizat i o captur de osciloscop pentru a avea o vedere complet asupra subrutinei. Imaginea rezultat este urmtoarea :

Canalul 1 al osciloscopului (graficul de jos) a fost legat la terminalul de ceas (CP) a lui 74HC164 pe cnd canalul 2 (graficul de sus) evideniaz activitatea pinului de date a aceluiai circuit. Am inut mori s prezint i aceast msurtoare pentru a urmri efectiv evoluia ntregii subrutine asupra mediului fizic. n acest sens, observai v rog cei 4 bii de 1 logic ce alterneaz cu 4 bii de 0 logic care alctuiesc mpreun secvena de afiat dorit (graficul de date). De asemenea se pot urmri frumos cele 8 tranziii ale terminalului de ceas, aa cum ne-o cere algoritmul de comunicare cu afiorul. Un alt lucru interesant ce se poate urmri pe aceast imagine o reprezint perioada de execuie a subrutinei de afiare. Este vorba de acel x care, pentru analiza noastr, are valoarea de 110 s . La o asemenea valoare, nu este de mirare c actualizarea LED-urilor se face aproape instantaneu. n tot cazul, muuult prea repede ca ochiul uman s poat sesiza deplasrile valorilor din fundal. Important : n secvenele ce vor urma, datorit avantajelor aduse, vom folosi intens aceste apeluri de subrutine. Cu toate acestea, vom ncerca s nu scriem codul ntreg al subrutinei ori de cte ori vom scrie o aplicaie. Aceast secven va fi n principal scris

83

atunci cnd vom face efectiv introducerea subrutinei, iar noi ne vom folosi, din motive estetice i de economie de spaiu, doar de apelul acestor regiuni de cod. Gata, Ale poate s comunice cu noi i, mai mult, o face ntr-un mod curat i frumos. n exemplele ce urmeaz ne vom folosi de aceast capacitate pentru a demonstra posibiliti interesante ale creieraului. S continum ... P.S: Dac vrei ca Ale s ne salute n alt fel, tii ce trebuie s modificai! ntrebri / Exerciii : 1. La ce sunt bune subrutinele ? Gsii 2 argumente. Exist vreun motiv pentru care nu le-ai utiliza ? Argumentai. 2. Ce credei c se ntmpl cnd programul care traduce textul n instruciuni pe care creieraul lui Ale le nelege ntlnete instruciunea aceasta : DDRB = 0x17 ? Va ajunge ea pe Ale sau este folosit doar de traductor ? Argumentai. 3. Scriei o subrutin care s afieze un octet prezent n R16 n mod invers fa de cel abordat de noi n afiseaza_r16. 4. Modificai subrutina afiseaza_r16 pentru a trimite mereu spre LED-uri valoarea pe care o dorim din R16 la care se nsumeaz un 5. 5. De ce nu am folosit instruciuni PUSH/POP i n subrutina iniializeaza_perif ? 6. Credei c am putea tri fr instruciunile PUSH/POP ce ncadreaz subrutinele ? Argumentai. 7. Urmrind captura de osciloscop, de ce credei c un 1 logic prezent pe canalul de date dureaz o perioad mai mare dect un 1 logic prezent pe terminalul CP ? Tot aici, de ce credei c un 1 logic pe canalul de ceas (CP) dureaz mai puin dect un 0 logic prezent pe acelai canal ? Un indiciu bun pentru ambele ntrebri l constituie modul n care a fost construit subrutina de afiare.

[4.1s] O dovad c Ale gndete


Cred c aici este momentul perfect pentru a demonstra faptul c Ale e capabil s gndeasc. S urmrim urmtoarea bucat de cod i s nelegem ce se ntmpl : main: rcall initializeaza_perif ldi R16, 10 ldi R17, 5 rcall afiseaza_r16 add R16, R17 rcall afiseaza_r16 executa_vesnic: rjmp executa_vesnic Ce facem noi aici ? Ei bine, iniial ncrcm n R16 valoarea 10 i n R17 valoarea 5 apoi spunem c dorim s afim R16. n momentul acesta, ar trebui s vedem pe LED-uri secvena , care reprezint valoarea binar a numrului 10, dar nu este aa! Observm , care este valoarea lui 15! Cum se poate ntmpla una ca asta ? Ei bine, secretul st n ceea ce se ntmpl dup primul rcall : prin instruciunea de add, R16 va lua valoarea sumei dintre vechiul R16, care era 10, i R17, care e 5, rezultnd R16 =

84

15. Apoi vine apelul la subrutina de afiarea i R16 este afiat, iar noi, ntr-adevr vedem valoarea binar a lui 15. Ce vrem s demonstrm cu acest mic exemplu ? Vrem s subliniem 2 lucruri : 1. c ideea de a folosi push/pop n subrutine de cod este una bun altfel, dup primul apel la afiseaza_r16, R16 ar fi fost 0 i R17 de asemenea, iar rezultatul final nu ar mai fi fost 15 ci 0 + 0 = 0 deci nu unul foarte interesant i 2. Ale tie s fac adunri, nite operaii att de simple, dar att de importante n acest domeniu dup cum discutam pe la nceputurile aventurii noastre. Cu toate acestea, o ntrebare rmne : de ce nu vedem i primul 10 afiat ? M refer la prima instruciune de rcall ea unde merge ? Ei bine, aflai c ea se execut, dac aveai dubii, dar din cauza faptului c toat secvena dureaz cteva microsecunde nainte s se revin la punctul de apel, s se realizeze adunarea i s se apeleze al doilea rcall, rezultatul nu este aa de vizibil pentru noi. Va trebui s rezolvm aceast problem (invizibilitatea) i pentru a face acest lucru nu trebuie dect s introducem un pic de ntrziere n execuia instruciunilor. De acest lucru ne vom ocupa n seciunea urmtoare ... ntrebri / Exerciii : 1. Se modific comportamentul aplicaiei noastre dac eliminm primul rcall din secvena de instruciuni ? Argumentai. 2. Scriei secvena de instruciuni pe care voi ai aborda-o pentru a afla necunoscuta din relaia urmtoare : 30(5+ x )=8 . n final, pe Ale va trebui s citim valoarea lui x. 3. Putem scrie instruciuni pentru rezolvarea urmtoarei ecuaii : 5=20 folosind comenzi de mprire i/sau nmulire ? Argumentai.

[5s] Ale, mai ncet!


Cteodat, aa cum am vzut n exemplul anterior, prea mult vitez nu este un lucru bun. Uneori este necesar ca lucrurile s mearg mai ncet pentru ca noi, oamenii, s le putem observa. Trebuie s rezolvm aceast problem pe Ale, dar creieraul nu ne pune la dispoziie instruciuni pentru a ntrzia execuia unei secvene de cod mai mult de 1-2 cicluri de tact (vezi intruciunea NOP, de pild). Nu-i nicio problem, va trebui s creem noi o subrutin care s fac lucrul acesta. Aadar, ne propunem s realizm o subrutin care s nu fac altceva dect s consume timp, s blocheze derularea aplicaiei pentru o anumit perioad de timp dup care s se reia execuia codului. Dar ce vom scrie n aceast rutin ? Pi am putea scrie multe NOP-uri. Foarte multe NOPuri. De fapt am avea nevoie de att de multe pentru a obine o ntrziere de cteva milisecunde nct ele nu ar ncpea fizic n memoria de instruciuni. S nu uitm faptul c viteza implicit a Attiny-ul de pe Ale este de circa 1 milion de instruciuni pe secund, sau o instruciune la fiecare 1 s , ceea ce nseamn c am avea nevoie de cel puin 500 de mii de NOP-uri doar pentru a obine o ntrziere de jumtate de secund ( 5000001 s =500000 s=500ms ). Inacceptabil i irealizabil innd cont de memoria limitat de cod pe care o avem! O alt variant mai frumoas ar fi, aa cum am vzut atunci cnd am restrns codul de la subrutina de afiare, folosirea de clicuri. Ideea de baz este urmtoarea :

85

1. Iniializeaz o variabil contor pe o valoare mare, 2. Decrementeaz variabila contor, iar 3. Dac variabila contor nu este egal cu 0 atunci sari la punctul 2. Pentru a avea ct de ct anse s vedem ceva efecte, va trebui ca valoarea aceea mare de care se discut la punctul 1 s fie ntr-adevr mare. Attiny-ul folosit de noi cunoate cteva instruciuni ce lucreaz cu numere pe 16 bii care ar fi utile pentru cauza noastr. Presupunem c vom folosi registrul X (gruparea R26:R27) n acest sens i vom considera cea mai mare valoare posibil ce opereaz cu date pe 16 bii : 65535 sau 0xFFFF. n felul acesta putem folosi i cteva instruciuni pe 16 bii. Astfel, subrutina de ntrziere ar putea arta n felul urmtor : intarzie_un_pic: push R27 push R26 ldi R27, 0xFF ; ncrcm partea superioar a celor 16 bii utilizai ca variabil de control ldi R26, 0xFF ; ncrcm partea inferioar a respectivilor 16 bii _ciclu_intarziere: sbiw R26, 1 ; scdem 1 din gruparea R26:R27 i plasm rezultatul napoi n R26:R27 brne _ciclu_intarziere ; ct timp R26:R27 nu este 0, repetm pop R26 pop R27 ret Cum i putem testa performanele, ntrebai ? Am putea-o invoca ntre cele 2 afiri folosite n exerciiul precedent : main: rcall initializeaza_perif ldi R16, 10 ldi R17, 5 rcall afiseaza_r16 rcall intarzie_un_pic add R16, R17 rcall afiseaza_r16 executa_vesnic: rjmp executa_vesnic Dup ncrcarea aplicaiei pe plcu se va observa ceva interesant : acest apel de subrutin proaspt realizat ne va permite s vedem n sfrit ceea ce am bnuit c se ntmpl n creiera i anume afiarea secvenei scurt timp, de urmat, la . Subrutina de ntrziere funcioneaz!

Totui, s-ar putea ca unii dintre voi s fie deranjai de timpul redus oferit de aceast soluie. n ideea n care am folosit cea mai mare variabil din sistem ce ne-o pune la dispoziie creieraul, aceea de 16 bii, se pune ntrebarea dac putem crea o ntrziere i mai mare ? Desigur c am putea realiza mai multe apeluri consecutive de intarzie_un_pic, dar parc mai frumos ar fi s existe un singur rcall intarzie_un_pic n locul unde vrem aceast ntrziere. i atunci ce este de fcut ?

86

Ce zicei dac am mai pune un ciclu n subrutin ? Un nou ciclu care s-l includ pe cel iniial (botezat aici _ciclu_intarziere). Cu alte cuvinte, ce spunei de urmtoarea secven ? : intarzie_un_pic: push R27 push R26 push R25 ldi R25, 3 _ciclu_intarziere_M: ldi R27, 0xFF ldi R26, 0xFF _ciclu_intarziere: sbiw R26, 1 brne _ciclu_intarziere subi R25, 1 brne _ciclu_intarziere_M pop R25 pop R26 pop R27 ret Observai diferena ? n loc s folosesc o ntrziere rezultat din decrementarea continu a unei valori foarte foarte mari pe care oricum nu o aveam, de ce s nu fac 3 sau 5 sau cte cicluri doresc de astfel de decrementri pentru a obine ntrzierea pe care o doresc ? n codul de mai sus am ales valoarea 3 pentru ciclul cel mare (de aici vine M-ul din coada eitchetei _ciclu_intarziere_M) pentru a beneficia de aproximativ 760 milisecunde ntrziere, dac este s am ncredere n osciloscopul meu :

Pentru corectitudine, precizez c timpul a fost msurat ntre cele 2 apeluri ale subrutinei afiseaza_r16, vizibile n graficul de jos (CP) prin cele 2 bare. Graficul de sus arat activitatea terminalului de date.

87

Desigur c valori mai exacte se pot obine dac urmrim o analiz a codului din punct de vedere al timpului consumat aa cum am mai fcut ntr-o seciune precedent. Noi ns ne vom mulumi cu att, lsndu-v pe voi s calculai i s alegei valori pentru ntrzieri mai rotunde dac dorii. nainte de a ncheia aceast seciune, ce zicei, facem o aplicaie care imit luminile de poziie alternante ale unei biciclete ? Ele sunt utilizate de bicicliti pe timp de noapte pentru a fi vzui de celelalte persoane de pe drum. M refer aici la un dispozitiv din acesta :

Avem suficiente cunotine s o facem i ar fi prima noastr aplicaie util. S-i dm btaie ... Sumarizm : vrem ca Ale s imite comportamentul unei lumini alternante, asemeni celei ce o vedem pe biciclete noaptea. Prin lumini alternante nelegem faptul c la un moment dat sunt aprinse doar primele 4 LED-uri aprind celelalte 4 LED-uri - i tot aa. Pentru asta, ne vom folosi de toate subrutinele nvate pn acum : vom iniializa perifericele cu subrutina initializeaza_perif, vom realiza ntrzieri cu subrutina intarzie_un_pic i vom afia valori cu subrutina afiseaza_r16. Alternarea de LED-uri o putem face n mai multe feluri, iar noi vom folosi o soluie dat de instruciunea COM. Astfel, soluia care reunete toate aceste subrutine pentru a rezolva problema noastr poate fi urmtoarea : main: rcall initializeaza_perif ldi R16, 0x0F ; ncrcm valoarea iniial de afiat executa_vesnic: rcall afiseaza_r16 ; afim starea curent a variabilei com R16 ; pune n R16 valoarea lui R16 cu biii inversai : 1 devine 0 i 0 devine 1 rcall intarzie_un_pic ; introducem o ntrziere pentru a putea vedea reazultatul rjmp executa_vesnic ; repetm ciclul, necondiionat, la nesfrit O alt instruciune ce ar fi putut fi folosit cu acelai rezultat ar fi fost instruciunea SWAP. Ct despre ceea ce afim, desigur c se pot obine i alte forme vizuale. Totul depinde de valoarea iniial ncrcat n R16. , iar, dup o ntrziere, se i ciclul continu la nesfrit : -

88

i asta, dragii mei, este tot! Problema a fost rezolvat. Vedei ce frumos decurg lucrurile dac avem subrutine ? Totul devine o joac de potrivire a pieselor de puzzle, iar rezultatele pot fi extraordinare. ntr-adevr, se pot obine multe cu LED-urile lui Ale, dar comunicarea omAle se realizeaz, timid, deocamdat ntr-o singur direcie. Acest lucru se va schimba atunci cnd vom nva s folosim minitastatura. Acum ns, avnd o subrutin de ntrziere, orizontul exemplelor posibile se mrete simitor. n continuare, vom folosi secvenele nvate pentru a demonstra o facilitate sensibil a creieraului. Nu este chiar nou noiunea i avem aici ocazia s o clarificm

ntrebri / Exerciii : 1. Reimplementai secvena de instruciuni de mai sus folosind comanda SWAP. Exist vreo diferen ntre cele 2 implementri ? Argumentai. 2. Calculai, cu precizie ct mai mare, ntrzierea introdus de noi n subrutina intarzie_un_pic. Indicaie : folosii-v de analiza ce am fcut-o atunci cnd am discutat de instruciunile cunoscute de Attiny-ul lui Ale. 3. Realizai o subrutin de ntrziere care s ne confere jumtate de secund de ateptare. 4. n captura de osciloscop prezentat n aceast seciune, explicai de ce dup al doilea apel al subrutinei afiseaza_r16, semnalul de date rmne pe 1 logic ?

[5.1s] Unde este stiva ?


Am discutat mult despre stiv, dar nu am evideniat-o niciodat. Cu toate c avem instruciuni care o folosesc (vezi PUSH i POP), o ntrebare rmne : cum putem s artm c ea exist i c este folosit i de creiera ? Acum c putem afia valori din creiera prin afior, este momentul ideal pentru a arta lumii ce gndete Ale. Chiar dac nu lucrm direct cu adrese de memorie atunci cnd folosim memoria volatil prin intermediul stivei, acest lucru nu nseamn c aceast adres a stivei nu exist pstrat undeva. Ea trebuie s existe, altfel, spre exemplu, creieraul nu ar ti cte elemente are depozitate. Pentru aceasta creieraul are alocat un registru de control. Acesta se numete SP1 i are adresa relativ 0x003D n spaiul regitrilor speciali. Ca i structur intern, acest registru se prezint n felul urmtor : Rang Notaie Op. permise Val. iniial
7 6 5 4 3 2 1 0

SP7 S/C 1

SP6 S/C 1

SP5 S/C 0

SP4 S/C 1

SP3 S/C 1

SP2 S/C 1

SP1 S/C 0

SP0 S/C 1

Unde biii au urmtoarea semnificaie :


1

provine din englezescul Stack Pointer sau Adresa vrfului stivei

89

Denumire SP7 SP0

Nume complet Adresa vrfului stivei

Semnificaie Grup de bii ce indic adresa curent a vrfului stivei. Aceast adres este afectat de instruciunile PUSH i POP.

Haidei s o definim pentru aplicaiile noastre : SP = 0x3D i s artm efectiv existena ei precum i influena instruciunilor PUSH i POP asupra sa. Pentru asta vom construi un exemplu prin care vom arta 3 lucruri : 1. Care este valoarea iniial a vrfului stivei, 2. Valoarea vrfului stivei dup o aciune de PUSH (depozitare a unui octet pe ea) i 3. Valoarea vrfului stivei dup o comand de POP (extragerea unui octet de pe stiv). n explicaiile noastre iniiale spuneam c adresa stivei este iniializat cu cea mai mare adres a memoriei volatile pentru c ea crete invers : o aciune de depozitare (PUSH) scade aceast adres cu 1 pe cnd o aciune de extragere (POP) crete aceast valoare cu 1. Aadar, construim urmtoarea secven de instruciuni care face acest lucru : main: rcall initializeaza_perif executa_vesnic: in R16, SP ; citim i afim valoarea iniial a vrfului stivei rcall afiseaza_r16 rcall intarzie_un_pic push R16 ; mpingem o valoare pe stiv in R16, SP ; vedem cum a influenat aceast aciune vrful stivei rcall afiseaza_r16 rcall intarzie_un_pic pop R16 ; extragem o valoare de pe stiv in R16, SP ; verificm ce s-a ntmplat cu vrful stivei i de aceast dat rcall afiseaza_r16 rcall intarzie_un_pic rjmp executa_vesnic O instruciune nou pe care o folosim noi n acest exemplu este comanda IN. Dup cum am vzut n tabelul de instruciuni, folosim aceast comand pentru a extrage valoarea unui registru special (de control) i pentru a o depozita ntr-un registru de uz general (acele registre a cror denumire ncepe cu R). Dup cum vom vedea prin alte exemple, aceasta este singura metod prin care putem interaciona cu aceti regitrii speciali (n afar de registrul SREG care, aa cum am vzut n tabel, i are instruciunile sale special construite).

90

Dup ce trimitem aplicaia spre plcu, ce ar trebui s ne ateptm s vedem ? Ei bine, prima i prima dat ar trebui s vedem valoarea vrfului stivei aa cum a fost ea iniializat la pornirea creieraului : . Apoi, dup o scurt pauz, i o ncrcare a unui octet pe stiv, ar trebui s vedem adresa stivei avnd o valoare cu 1 mai mic : . Dup nc o pauz i o aciune de extragere, stiva se . va incrementa i va arta din nou valoarea iniial :

Prin acest exemplu putem observa ceva interesant : aa cum ne-am atepta, nu putem depozita pe stiv orict de multe elemente dorim din cauza memoriei limitate pe care o avem la dispoziie. Cu toate acestea, uurina folosirii stivei este un motiv puternic pentru a include acest concept n arsenalul nostru de soluii inteligente. n continuare, ca o dovad a posibilitilor multiple de folosire a afiorului, cutm inspiraie din

ntrebri / Exerciii : 1. Ci octei pot fi pe stiva lui Attiny25 ? inei cont i de zonele speciale ale memoriei volatile cnd calculai aceast valoare. 2. Credei c, pe baza a ceea ce cunoatem deja, putem modifica direct vrful stivei ?

[6s] Alte 2 exemple interesante cu LED-uri


Primul exemplu ar fi un numrtor binar de la 0 la 255. Ne propunem s utilizm tot ce am nvat despre Ale pentru a scrie o secven de instruciuni prin care, prin intermediul LEDurilor, s observm un numrtor binar. Pentru asta, vom folosi subrutina de afiare, subrutina de ntrziere i instruciunea INC, iar secvena urmtoare face exact ceea ce ne-am propus : main: rcall initializeaza_perif clr R16 ; tergem coninutul registrului R16. R16 va lua valoarea 0 executa_vesnic: rcall afiseaza_r16 ; afim valoarea curent a numrtorului inc R16 ; punem n R16 vechea valoare a lui R16 la care adugm 1 rcall intarzie_un_pic ; introducem o ntrziere pentru a putea vedea reazultatul rjmp executa_vesnic ; repetm numrarea la nesfrit Dac comparm acest progrmel cu cel discutat la semnalizatorul de biciclete vom observa c diferenele nu sunt foarte mari : semnalizatorul ncrca n R16 valoarea 0x0F pe cnd numrtorul nostru, dup cum este i normal, ncarc n R16 valoarea 0. Poate cea mai semnificativ diferen o reprezint nlocuirea instruciunii COM cu INC. COM modific valoarea biilor din R16 pe cnd INC adaug un 1 la vechea valoare obinnd valoarea imediat urmtoare a numrtorului. Aadar singura diferen o reprezint modul n care ceea ce se afieaz este modificat sau actualizat. V gndii ce complicat ar fi dac am imita cele 2 comportamente NUMAI din circuite electrice, aa cum este obinuit electronica tradiional ? Am avea 2 circuite complet

91

diferite! Pe cnd, cu ajutorul modificrii a 2 cuvinte din succesiunea de instruciuni din Ale, obinem acelai efect fr a atinge nici mcar un deget partea electric! Asta mi se pare fenomenal i n asta st puterea conceptului de creiera : asigur o varietate a comportamentului fr prea mult btaie de cap! Poate v ntrebai ce se ntmpl dup ce numrtorul atinge valoarea de 255 (cel mai mare numr ce ncape ntr-un registru de 8 bii) ? Ei bine, 25510=0b111111112 , iar

25510 +1=25610=0b1000000002 . Acest ultim rezultat necesit 9 bii pentru a se depozita.


Registrele avnd o capacitate maxim de stocare de 8 bii, practic numai primii 8 bii ai rezultatului ajunge s fie stocai n registru. Asta nseamn c Ale consider valoarea urmtoarei operaii : 25510 +1 ca fiind 0b000000002 sau 010 ! Practic, valoarea imediat urmtoare afiat de creiera dup 255 este 0, sau toate LED-urile nchise! Propun s ncheiem aceast serie de exemple de folosire a afiorului cu un ultim cod mai complex, dar i mai spectaculos. Ne propunem, de data aceasta, s afim o secven mai complicat de succesiuni de LEDuri. S zicem c dorim s vedem urmtoarea secven vizual derulndu-se pe afior : 0b00000000 0b10000000 0b11000000 0b01100000 0b00110000 0b00011000 0b00001100 0b00000110 0b00000011 0b00000001 Practic, vrem s vedem cum fug dou LED-uri din stnga afiorului spre dreapta sa. Dup attea exemple, putem s spunem c avem suficient experien pentru a face lucrul acesta. i este adevrat. n acest sens, o soluie ar fi urmtoarea secven : main: rcall initializeaza_perif executa_vesnic: ldi R16, 0b00000000 rcall afiseaza_r16 rcall intarzie_un_pic ldi R16, 0b10000000 rcall afiseaza_r16 rcall intarzie_un_pic ldi R16, 0b11000000 rcall afiseaza_r16 rcall intarzie_un_pic ldi R16, 0b01100000

92

rcall afiseaza_r16 rcall intarzie_un_pic ldi R16, 0b00110000 rcall afiseaza_r16 rcall intarzie_un_pic ldi R16, 0b00011000 rcall afiseaza_r16 rcall intarzie_un_pic ldi R16, 0b00001100 rcall afiseaza_r16 rcall intarzie_un_pic ldi R16, 0b00000110 rcall afiseaza_r16 rcall intarzie_un_pic ldi R16, 0b00000011 rcall afiseaza_r16 rcall intarzie_un_pic ldi R16, 0b00000001 rcall afiseaza_r16 rcall intarzie_un_pic rjmp executa_vesnic Paii sunt cunoscui i simpli : ncrcm tiparul ce-l dorim afiat, Apoi apelm subrutina de afiare i, n final, Apelm subrutina de ntrziere nainte de a merge la urmtoarea valoare de afiat. Totui, ori de cte ori vedei o astfel de secven de cod ce conine instruciuni duplicate, vreau s fii suspicioi i s v ntrebai : Se poate mai bine?. DA! Se poate! Mereu se poate ntrebarea esenial este Cum putem nmagazina tiparul pe care dorim s-l afim ?. Din cauza faptului c secvena de aprindere poate fi n orice ordine dorim, ea nu se poate genera prin operaii matematice. Dac s-ar fi putut, am fi integrat-o ntr-un ciclu i apoi ntr-o subrutin i viaa ar fi fost mult mai frumoas. Atunci ce putem face ? Soluia propus de crulie ar fi plasarea secvenei dorite n memoria de instruciuni i accesarea sa prin comanda LPM. n felul acesta secvena de octei ar fi situat n mod continuu n memorie, iar noi ar trebuie numai s o parcurgem i s o afim. Exact asta i propune i urmtoarea secven de cod : .section .progmem adresa_secventa_de_afisat: .byte 0b00000000, 0b10000000, 0b11000000, 0b01100000, 0b00110000 .byte 0b00011000, 0b00001100, 0b00000110, 0b00000011, 0b00000001

93

.section .text .global main main: rcall initializeaza_perif incarca_secventa_de_afis: ldi R31, hi8(adresa_secventa_de_afisat) ; ncrcm n Z [R31:R30] adresa de unde ncepe secvena ldi R30, lo8(adresa_secventa_de_afisat) ; de afiat. lo8 ia primii 8 bii mai puin semnificativi a acelei afiseaza_octet: lpm R16, Z+ ; scoatem din memoria de instruciuni de la adresa Z un octet i l plasm n registrul R16
; apoi incrementm registrul extins Z ; adrese pe cnd hi8 ia cei mai semnificativi 8 bii ai adresei

rcall afiseaza_r16 rcall intarzie_un_pic cpi R16, 0b00000001 ; verificm dac s-a atins octetul care ncheie secvena breq incarca_secventa_de_afis ; dac da, atunci reia succesiunea de octei i reafieaz-o rjmp afiseaza_octet Seciunea progmem instruiete aplicaia psAle s pun n memoria nevolatil urmtoarea secven de octei (byte n englez) care va avea adresa de nceput dat de eticheta adresa_secventa_de_afisat. n felul acesta, aa cum v spuneam, toat secvena pe care o dorim afiat se afl situat ntr-un singur loc n memorie. Noi nu trebuie dect s poziionm registrul extins Z [R31:R30] pe adresa de nceput a octeilor, s extragem octet cu octet tiparul dorit i s-l afim aa cum tim noi mai bine. Dup fiecare extragere, valoarea lui Z se autoincrementeaz dup cum ne indic +-ul de la sfritul instruciunii LPM : lpm R16, Z+ Aici apare o problem ns. Dac nu suntem ateni, Z-ul poate depi domeniul tiparului i poate ajunge s se plimbe prin toat memoria de cod afind octeii instruciunilor ce i gsete n calea sa. Odat ce ultimul octet din secven a fost afiat, ne propunem s resetm adresa lui Z la primul octet-tipar din serie. Acest lucru l facem prin urmtoarele instruciuni : cpi R16, 0b00000001 breq incarca_secventa_de_afis i cu aceasta ncheiem i acest exemplu. Aa cum am vzut, instruciunea LPM permite o ncrcare de valori direct din spaiul de instruciuni. Dei scopul real al folosirii acestei instruciuni este altul (de regul, se folosete pentru verificarea memorie), pentru problema noastr a fost suficient. De obicei, tiparele acestea sunt stocate n memoria EEPROM din simplu motiv c memoria de instruciuni este limitat, iar ocuparea ei cu valori statice ar reduce-o i mai mult. n continuare, vom introduce posibilitatea comunicrii cu Ale prin butoane. Vom introduce mini-tastatura

94

ntrebri / Exerciii : 1. Cte tipuri de .section cunoatei i care sunt acestea ? 2. Modificai codul de mai sus pentru a derula urmtoarea secven : 0b00000000 0b10000001 0b11000011 0b11100111 0b11111111 0b01111110 0b00111100 0b00011000 3. Ce s-ar ntmpla dac, n exemplul de mai sus, am avea urmtoarele modificri : .section .text .global adresa_secventa_de_afisat ? Ar mai funciona aplicaia ? Argumentai. 4. ncercai s folosii registrul extins Y n loc de Z. Mai funcioneaz codul ? De ce ?

[7s] Ale, suntem aici!


Acum c am vzut cum poate Ale comunica cu noi, parc interesant ar fi s putem i noi comunica cu ea, nu credei ? n toate exemplele precedente, dac ai fost curioi s apsai un butona din cele 8 prezente (n afar de cel de la modulul de Reset), ai vzut c plcua l ignor. Vom repara asta, mpreun, n exemplele care urmeaz. Aa cum discutam atunci cnd am introdus modulele plcuei, din cauza faptului c Attiny-ul nu are multe terminale, s-a cerut ajutorul unei componente externe pentru a putea citi att de multe butoane. Aceast component este un circuit numit 74HC165, iar fizic ea arat cam aa :

Din motive discutate atunci cnd am abordat LED-urile, o imagine mai util analizei noastre electrice ar fi urmtoarea :

95

Din nou distingem funcionaliti comune ale pinilor pe care le grupm, explicm i redm n urmtorul tabel : Denumire picioru GND, VCC Intrare / ieire ? Intrare Intrare Explicaii Pini folosii la alimentarea circuitului Pin ce accept semnalul de ncrcare a valorilor butonaelor conectate. El se activeaz la prezena unui 0 logic (GND sau 0 Voli) pe linie. Terminal electric de tact folosit la citirea butonaelor, cte unul pentru fiecare tranziie (de la 0 1) Picioru prin care se citete valoarea inversat (complementat) i direct a strii butonaului curent n urma unei ncrcri (vezi PL ) i a unor tranziii (vezi CP). Pin ce constituie intrare serial din exterior Terminale ce sunt conectate la butonae i prin care, la momentul solicitrii unei ncrcri ( PL ), se nmagazineaz intern valoarea butonaelor ateptnd s fie citite din exterior n mod secvenial (prin CP) Picioru prin care se activeaz semnalul de tact (ceas). GND aplicat pe acest pin determin circuitul s in evidena semnalului de tact prezent pe pinul CP pe cnd VCC face ca circuitul s nu rspund la tranziiile de pe CP.

PL

CP

Intrare Ieire

Q7 i Q7

DS

Intrare

D7, D6, D5, D4, Intrare D3, D2, D1, D0

CE

Intrare

O prim observaie comparativ ntre circuitul 74HC164 i cel analizat aici, 74HC165, face referire la numrul de pini al componentelor. 74HC164 are dou rnduri de cte 7 pini de unde unde astfel de circuite mai poart denumirea de tip 14 DIP1, iar 74HC165 are dou rnduri de cte 8 pini (16 DIP). n afar de asta, aa cum i denumirile apropiate o sugereaz, comportamentul lor este foarte asemntor. Dac 74HC164 primea bii pe dou terminale pe care le trimitea spre LED-uri, 74HC165 serializeaz informaia ce se gsete la un moment dat (dictat de pinul PL ) pe pinii D7D0 i o face disponibil ctre creiera pe un numr mai redus de terminale. Am putea spune c, dei comportamentul este acelai, circuitele difer prin direcia de circulaie a informaiei. ntreruptoarele preiau informaia din mediu i o fac disponibil creieraului, pe cnd LEDurile rspund mediului dup cum le dicteaz Attiny-ul lui Ale. S continum cu tradiionalul nostru exemplu pentru a vedea ce se ntmpl mai exact cu acest circuit. S zicem c dorim s citim, la un moment dat, starea celor 8 butoane conectate la circuit, iar ele au configuraia urmtoare :
ntreruptor Stare D7 A* D6 N** D5 N D4 A D3 A D2 N D1 A D0 A

*) prescurtare de la Apsat
1

abreviere englezeasc pentru Dual Inline Package, n romn : Pachet cu 2 rnduri de terminale

96

**) Neapsat

Asta se traduce n urmtoarele valori/tensiuni pe liniile Dn cu n=0,7 :


Pin Val. logic D7 D6 1 D5 1 D4 0 D3 0 D2 1 D1 0 D0 0

Practic, un ntreruptor apsat ntotdeauna va pune un 0 logic (0 Voli - GND) pe pinul respectiv, pe cnd un ntreruptor neapsat va determina apariia unui 1 logic (5 V - VCC) pe acelai pin. S vedem cum am folosi gruprile de semnale n acest caz. ncepem cu pinii de alimentare GND, VCC pe care i conectm la tensiunea de alimentare a circuitului. Aadar, cu ei nu avem treab, n sens c vor avea mereu aceeai valoare aplicat, nefiind necesar s-i controlm. Vom avea nevoie s citim starea tastelor, deci va trebui ca semnalul CP s fie activ. Asta nseamn c tensiunea aplicat pe CE va fi de 0V (GND). De asemenea, pentru c tot timpul vom dori s citim starea tastelor de la momentul respectiv, CE -ul poate fi legat permanent la GND. Terminalul DS nu ne este util n acest caz deoarece el controleaz valoarea ce se deplaseaz n D0 atunci cnd se extrage o valoare prin Q7. Putem s-l fixm la orice valoare logic/tensiune sau chiar s-l lsm liber, neconectat. Totui, aceast ultim soluie (lsarea unui pin neconectat) nu este una corect.

Important : n general, este bine s fixm toi pinii intrare nefolosii la valori logice cunoscute. n felul acesta, putem s controlm mai bine logica circuitului, iar interferenele cauzate de mediul electric n care trim sunt diminuate. Aadar, s spunem c legm terminalul DS la GND. Pinii D7-D0 vor fi ocupai cu butonaele. Prin urmare ne mai rmn 3 grupe de pini. Din grupa Q7 i Q7 vom alege Q7 ca fiind pinul de pe care vom citi starea butonaului curent dei am putea la fel de bine s-l alegem i pe Q7 , caz n care creieraul ar fi primit biii ce ar fi simbolizat 1 logic pentru buton apsat, iar 0 logic pentru neapsat. Dei varianta cu Q7 ar fi fost una mai elegant pentru instruciunile noastre, Ale folosete totui Q7 pe post de citire a datelor. Motivul este dat de amplasarea pieselor pe plcu : alegerea lui Q7 n defavoarea lui Q7 ar fi nsemnat o alt amplasare fizic, nefavorabil a pieselor. Cu asta nu am fost de acord, iar Q7 a rmas. Semnalul PL trebuie controlat de creiera pentru c el i spune circuitului 74HC165 cnd s priveasc spre butonae i s nmagazineze intern starea lor. Ultima grupare, reprezentat de terminalul CP, controleaz deplasarea octetului, nmagazinat la momentul cererii aplicate pe linia PL , de la D0 la D7 i din D7 n Q7 i Q7 , cte unul pentru fiecare tranziie.

97

Aadar, prin folosirea acestui circuit integrat extern 74HC165, am putut reduce numrul de pini necesari citirii a 8 butonae de la 8 (cte unul pentru fiecare butona) la 3. Destul de bine, nu credei ? Nu vom putea ajunge pn la 2 terminale aa cum am putut s ajungem cu 74HC164 din cauza semnalului de ncrcare PL care trebuie s existe. Fr PL nu am putea nmagazina starea curent a butonaelor, iar fr nmagazinare nu le-am putea citi din exterior. Totui, reducerea 8 3 este una foarte bun i cel puin acceptabil pentru Attiny-ul nostru de 8 pini (din care 2, s nu uitm, sunt folosii pentru alimentare). Aadar, avem 3 terminale prin care putem citi cele 8 butonae, dar cum putem face asta ? Dac avem, suficiente cunotine tehnice i o stpnire bun a limbii engleze am putea urmri foaia de catalog a circuitului, dar noi nu vom face asta. Pentru moment, vom considera c aceast sarcin i aparine autorului. n acest sens, definim urmtoarea secven de pai : 1. Aplicm pe terminalul PL un 0 logic urmat de un 1 logic pentru a ncrca valoarea curent a butoanelor ntr-o zon intern, fcndu-le disponibile pentru citirea ulterioar. 2. Citim valoarea logic disponibil pe Q7 pentru a afla starea butonaului ce este legat la D7 (vom obine valoarea 0 pentru exemplul nostru) 3. Pulsm linia CP (0 1 0) pentru a pune valoarea butonaului de pe D6 pe Q7. Citim Q7 pentru a obine valoarea lui D6 (1, n cazul nostru) 4. Pulsm linia CP (0 1 0) pentru a pune valoarea butonaului de pe D5 pe Q7 apoi citim Q7 pentru a obine valoarea lui D5 (n exemplul nostru : 1) 5. [i ali pai identici pentru restul de butoane] 6. Pulsm linia CP (0 1 0) pentru a pune valoarea butonaului de pe D0 pe Q7 de unde, citind Q7, vom afla valoarea lui D0 (0 pentru cazul nostru) i secvena este complet : obinem, pe rnd, starea tuturor butoanelor de pe plcu de la dreapta la stnga (D7D0). Urmtorul pas este s vedem cum legm cele 3 terminale ale lui 74HC165 la creiera pentru a putea fi controlate din instruciunile pe care noi le scriem i le depozitm pe acesta. ncepem, din nou, cu imaginea fizic a pinilor lui Attiny :

Plcua pe care o deinei are urmtoarele legturi stabilite : Terminal 74HC165 Terminal Attiny

PL
PB4

CP PB1

Q7 PB2

Hopa! Ceva nu este n regul! Dac mai inei minte cnd discutam de circuitul 74HC164, ziceam c folosete PB1 pe post de date i PB0 pe post de ieire ceas/tact. Pi cum putem folosi PB1 i pe post de date n discuia despre modulul de LED-uri, dar i pe post de ceas

98

pentru modulul minitastaturii ? Nu se pap reciproc ? Rspuns firesc : nu se pap i PUTEM! Aducei-v aminte modul de funcionare al lui 74HC164 : valorile sunt trimise ctre LED-uri doar dac SEMNALUL DE TACT/CEAS tranziteaz. Cu alte cuvinte, pentru a nu afecta valoarea afiat, cu semnalul de date putem face orice att timp ct nu ne atingem de semnalul de tact. Ceea ce este adevrat deoarece PB0 este folosit doar n modulul de LED-uri! n felul acesta, Attiny-ul folosete doar 4 terminale cnd discut cu cele 2 module (minitastatur i LED-uri). 8 LED-uri i 8 butonae controlate prin 4 pini n loc de 16, nu gsii asta extraordinar ? Gata cu admiraia, s revenim la Ale nainte de a continua cu o bucic de cod prin care s vedem c cele discutate de noi mai sus au sens trebuie s rezolvm problema citirii strii unui picioru din creiera. Aici m refer, spre exemplu, la acel Q7 prin care valorile butonaelor sunt transportate din circuitul 74HC165 n microcreieraul plcuei. Am vzut cum putem scrie valori logice pe terminalele creieraui din instruciuni, dar oare cum putem face invers ? Cum putem citi valori logice venite din exterior ? Pentru a face acest lucru posibil, avem nevoie s cunoatem nc 2 regitri speciali : Unul l-am cunoscut deja la modulul cu LED-uri : DDRB-ul, iar cel nou este PINB1. Registrul de intrare PINB care este situat la adresa 0x0016 n spaiul regitrilor de control (0x0016 + 0x0020 = 0x0036 n spaiul real de memorie), iar biii si au urmtoare semnificaie : Rang Notaie Op. permise Val. iniial
7 6 5 4 3 2 1 0

--C 0

--C 0

PINB5

PINB4

PINB3

PINB2

PINB1

PINB0

S/C 0

S/C 0

S/C 0

S/C 0

S/C 0

S/C 0

Unde literele de la notaie au urmtoarele semnificaii : Denumire --Nume complet Nefolosit Semnificaie Valoarea bitului respectiv nu are nicio ntrebuinare electric de aceea ea nu poate fi dect citit (C), iar valoarea mereu citit va fi de 0 logic. Valoarea citit a oricrui bit din aceast mulime reflect valoarea logic a tensiunii aplicate din exterior pe PBi.

PINB5 PINB0

Valoarea logic citit a pinului PBi cu i=0,5

abreviere ce provine de la englezescul Port B Input, expresie ce s-ar traduce n romn aproximativ prin Portul B de Intrare

99

Registrul DDRB nu-l mai amintim pentru c l-am discutat atunci cnd am abordat modulul de LED-uri, dar trebuie aici amintit faptul c o valoarea de 0 logic scris n acest registru face ca respectivul PBi s fie interpretat ca i intrare (adic se poate citi din aplicaie), pe cnd o valoare de 1 logic permite trimiterea spre exterior a valorilor logice dorite (adic se poate scrie din aplicaie). Acest lucru l fceam, dac mai inei minte, prin registrul PORTB. Cele 3 registre : DDRB, PORTB i PINB alctuiesc ceea ce intern se numete pentru Attiny25 drept modulul de intrare/ieire. Denumirea este una potrivit dac ne gndim la rolul su pentru creiera : permite citirea/scrierea de valori logice din/n mediul exterior. Din cauza modului de operare al minitastaturii, noi vom fi nevoii att s citim (pentru Q7) ct i s scriem ( PL i CP). Aadar, pentru a activa i modulul minitastaturii, subrutina prin care iniializm perifericele sufer cteva modificri. Dac activm att LED-urile ct i minitastatura atunci urmtoarea secven ne este util : initializeaza_perif: ldi R16, 0b00010011 out DDRB, R16 ret Singurul bit care a suferit o modificare n DDRB a fost bitul 4 care n modulul actual controleaz semnalul PL . Acestea fiind spuse, considerm c avem bazele modulului explicate i putem astfel s trecem la o prim aplicaie. Nu vom introduce aici o subrutin complet prin care s putem citi starea tuturor butoanelor minitastaturii, dar vom aplica ceea ce am nvat pentru a vedea c informaiile ntr-adevr reflect modul de operare al minitastaturii. S presupunem c dorim s scriem o aplicaie prin care s afim un tipar dac D7 nu este apsat i alt tipar dac el este apsat. Practic, tiparul se va modifica n funcie de starea butonaului ce se afl conectat la pinul D7 (situat n partea dreapt, jos) a circuitului 74HC165. Iniializarea am scris-o i considerm c avem la dispoziie subrutinele afiseaza_r16 i intarzie_un_pic introduse n seciunile precedente. Ne vom ocupa, cu alte cuvinte, de secvena principal a aplicaiei. Un candidat la acest titlu ar putea fi urmtoarea bucat de cod : PINB = 0x16 ; definim registrul prin care citim valoarea intrrilor portului B PINB2 = 0x02 ; definim adresa pinului 2 relativ la PINB DDRB = 0x17 PORTB = 0x18 PB0 = 0x00 PB1 = 0x01 PB4 = 0x04 ; definim adresa pinului 4 relativ la PORTB .section .text .global main main: rcall initializeaza_perif ; iniializm perifericele utilizate de aplicaie (LED-uri i minitastatur) sbi PORTB, PB4 ; iniializm PL -ul la o valoare inactiv (1 logic) executa_vesnic: cbi PORTB, PB4 ; pulsm pinul de incrcare a tastelor n 74HC165

100

nop ; ateptm un pic doar s fim siguri c modulul recepioneaz cererea noastr sbi PORTB, PB4 ; resetm PL -ul la valoarea iniial ncheind pulsarea sbic PINB, PINB2 ; verificm dac butonul aflat pe D7 nu este apsat ldi R16, 0b01010101 ; ncrcm n R16 valoarea de afiat n caz de neapsare a butonului sbis PINB, PINB2 ; verificm dac butonul aflat pe D7 este apsat ldi R16, 0b10101010 ; ncrcm n R16 valoarea de afiat n caz de apsare a butonului rcall afiseaza_r16 ; afim tiparul ncrcat rcall intarzie_un_pic rjmp executa_vesnic ; bucla infinit Ale, suntem aici! Numai la apsarea butonului legat la D7 (dreapta jos pe plcu), Ale ne va simi prezena i ne va saluta cum poate ea mai bine : folosind LED-urile. Super! Codul mai prezint i iniializrile de adrese ale registrelor speciale (PINB), dar i poziii relative de bii aa cum i-am prezentat n tabelele dedicate registrelor : PINB2 i PB4. n aceast crulie vom folosi mai rar denumiri de bii pentru a lucra cu regitrii din pricina spaiului redus de care dispunem, dar pentru ca o aplicaie s se poat ntrein mai uor, este indicat folosirea acestor denumiri n locul unor valori directe. nainte de a ncheia discuia despre acest modul trebuie remarcat faptul c, dei exemplul acesta este unul potrivit pentru a ncepe s interacionm cu plcua, el nu se folosete de tot ce am nvat. Dac ne uitm mai bine pe codul de mai sus, nu vom gsi niciunde folosirea lui PB1 (semnalul de tact) pentru c noi citim doar primul buton i anume : D7. Din acest motiv, propun un alt exemplu, mai complet : S presupunem c, asemeni cazului precedent, dorim ca Ale s simt apsarea unui buton de pe minitastatur doar c, de data aceasta, n loc s fie D7 acel buton, vom cere ca Ale s rspund doar la apsarea butonului legat la pinul D6 a lui 74HC165. Cum am putea face acest lucru ? De data aceasta trebuie s folosim semnalul de ceas pentru c ne trebuie un impuls nainte ca pe Q7 s ajung valoarea butonaului conectat la D6. Noul nostru cod devine : main: rcall initializeaza_perif sbi PORTB, PB4 sbi PORTB, PB1 ; aducem i linia de ceas a lui 74HC165 la o valoare cunoscut, inactiv executa_vesnic:
; pulsm linia de ncrcare pentru a nmagazina starea curent a tastelor

cbi PORTB, PB4 nop sbi PORTB, PB4 cbi PORTB, PB1 nop sbi PORTB, PB1

; aplicm un puls de ceas pentru a avea acces la starea lui D6, ignornd D7 (pasul 3 din secven)

; ncrcm tiparul de afiat n funcie de starea butonaului D6

sbic PINB, PINB2 ldi R16, 0b01010101 sbis PINB, PINB2

101

ldi R16, 0b10101010


; afim tiparul + ntrzierea obinuit

rcall afiseaza_r16 rcall intarzie_un_pic rjmp executa_vesnic

Dup trimiterea codului pe Ale, ncercai s vedei dac va mai rspunde la fel la starea lui D7. Nu prea are cum, dar ncercai. Apoi ncercai butonaul de lng D7 i anume : D6. Pare firesc comportamentul! Folosind i semnalul de tact am reuit s demonstrm faptul c, ntr-adevr, acesta este modul de funcionare al circuitului 74HC165, i c, ntr-adevr, acestea sunt semnalele prin care creieraul comunic cu minitastatura. LED-urile, creieraul i minitastatura ne deschid portia unor exemple mult mai interesante i mai interactive, dar nainte de a le aborda, ar fi bine dac am crea o rutin i pentru citirea tastelor aa cum am fcut-o pentru folosirea afiorului. S continum ntrebri / Exerciii : 1. Verificai ce se ntmpl dac eliminai ntrzierea din ultimul nostru cod. Cum v justificai comportamentul plcuei ? 2. Scriei o secven de instruciuni care, neavnd niciun buton apsat, s afieze secvena 0b11110000, iar la apsarea lui D3 s rspund prin afiarea tiparului 0b00001111 3. Scriei o secven de instruciuni care, fr niciun butona apsat, s afieze tiparul 0b00000000 (niciun LED aprins), la apsarea butonului conectat la D7 s afieze tiparul 0b00000001, iar la apsarea butonaului D0 s aprind LED-urile dup tiparul 0b10000000 Indiciu: Pentru problemele 2 i 3 ncercai s folosii instruciuni de salt i etichete! Nu v gndii la elegan sau simplitate, orice secven care face ce se cere este un bun nceput. Odat codul funcional, putei s ncercai s-l facei mai rapid/compact dac dorii.

[8s] Ale, tot aici suntem


i nu vom pleca pn cnd nu vom rezolva problema citirii butonaelor. Dar ce ne deranjeaz la metoda noastr proaspt nvta ? probabil v ntrebai. Ei bine, asemeni primei abordri discutate n seciunea modulului de afiare, verificarea fiecrui butona n parte nu este o metod tocmai sntoas : o mulime de instruciuni s-ar repeta, iar aplicaia ar fi greu de neles. Se poate mai bine ... Cu toate acestea, odat cu introducerea noiunii de subrutin i avnd experiena LED-urilor, nu putem spune c nu avem nicio soluie. Totui, nainte de a o vedea, s definim efectiv ce ne propunem s realizm. Vrem s construim o subrutin, asemeni celei discutate la modulul de afiare, n care, n urma execuiei, starea tuturor celor 8 butonae s fie pus la dispoziia aplicaiei prin intermediul unui registru. Vom alege acel registru ca fiind R17 poate din cauza faptului c l urmeaz pe R16, registrul folosit de afior. Starea fiecrui butona va avea o valoare logic copiat pe biii respectivului registru.

102

Cu alte cuvinte, dac dorim s aflm care este starea butonului D5, executm subrutina i verificm bitul cu index 5 din registrul R17. Dac respectivul bit este 1 atunci vom considera c butonul a fost apsat, iar dac, dimpotriv, valoarea bitului este 0 atunci vom concluziona faptul c butonul nu a fost apsat. De observat este faptul c, dac n seciunea n care am introdus minitastatura am interpretat un 0 logic ca fiind starea unui buton apsat, iar 1 logic ca fiind starea unui buton neapsat, subrutina noastr interpreteaz lucrurile un pic mai corect sau cel puin mai firesc : 1 logic pentru un buton apsat i 0 pentru unul neapsat. Practic, rspunsul logic vine la ntreabarea: Este butonul Di apsat ?. Am fcut aceast corectur pentru a nu creea confuzii n aplicaiile care vor urma. Fr alte ntrzieri, aduc n discuie subrutina citeste_taste_r17 care i propune s fac ceea ce dorim : citeste_taste_r17: push R16 ; R16 va fi folosit n subrutin deci salvm vechea valoare pe stiv cbi PORTB, PB1 ; aducem pinul CP la o valoare cunoscut, inactiv pentru circuit
; pulsm linia

PL

pentru a pregti starea tastelor pentru citire

cbi PORTB, PB4 nop sbi PORTB, PB4 clr R17 ; resteaz registrul pentru a-l pregti pentru a ine valorile tastelor ldi R16, 8 ; folosete R16 ca variabil de control pentru ciclul de citire a butoanelor ciclu_citire_taste: lsl R17 ; deplasm spre stnga registrul fcnd loc strii urmtorului buton sbis PINB, PINB2 ; inspectm starea butonului curent ori R17, 0b00000001 ; ajungnd aici, butonul curent a fost apsat
; pulsm linia de ceas CP pentru extrage starea urmtorului buton ; srim peste urmtoarea instruciune dac el nu este apsat

cbi PORTB, PB1 nop sbi PORTB, PB1


; executm instruciuni de control a ciclului prin intermediul registrului R16

dec R16 cpi R16, 0 brne ciclu_citire_taste

pop R16 ; refacem valoarea original a lui R16 nainte de a ncheia subrutina ret S explicm un pic ce facem aici, un pic mai sugestiv dect o fac comentariile : Subrutina ncepe prin salvarea valorii registrului R16. R16 este folosit n subrutin pe post de variabil de control a ciclului prin care citim cele 8 butoane. nainte de ciclul propriu-zis, pulsm pinul PL conform modului de funcionare a circuitului 74HC165 i extragem, pe rnd, prin 8 pulsri a liniei de ceas (CP), starea celor 8 butoane. R17 este nsrcinat cu primirea strii celor 8 butoane aa cum am stabilit iniial.

103

i ca peisajul s fie complet, prezentm o secven de instruciuni prin care, folosind att noua subrutin introdus ct i subrutinele pe care le cunoatem deja, ne propunem s combinm tot ce tim ntr-un exemplu util : main: rcall initializeaza_perif executa_vesnic: rcall citeste_taste_r17 ; punem starea butoanelor n registrul R17 mov R16, R17 ; copiem R17 n R16 i rcall afiseaza_r16 ; afim exact starea registrului aa cum o primim de la subrutina citeste_taste_r17 rcall intarzie_un_pic rjmp executa_vesnic Exemplul propus este unul ct se poate de simplu i uor de urmrit : mai nti iniializm modulele apoi citim starea butoanelor n R17 prin rutina proaspt nvat. Valoarea lui R17 ajunge n R16 i apoi pe LED-urile afiorului. Ciclul se reia dup ce ateptm un pic pentru a vedea rezultatul clar pe modul. Ajungnd n acest punct cu exemplele noastre, tii ce este interesant ? Dac nlocuim creieraul cu o unitate central, minitastatura cu o tastatur normal (numit i tastatur QWERTY, dup literele consecutive de pe ea) i LED-urile cu un monitor, ghicii ce obinem ? Dac facem acest lucru nu avem nici mai mult, nici mai puin dect un calculator de birou n toat regula! Nu-i aa ? Gndii-v un pic. Ne mai lipsete ceva ? Acest fapt dovedete nc odat c modelul calculatorului, este complet explicabil prin plcua Ale. Practic, odat cu acest modul introdus i iniializat, putem s comunicm cu Ale n timp ce execut instruciuni i ea ne poate rspunde prin afior. n felul acesta, posibilitile de a creea aplicaii interesante cresc aa cum vom vedea n seciunea urmtoare ...

ntrebri / Exerciii : 1. Modificai subrutina citeste_taste_r17 pentru ca, n urma execuiei, starea butonului D7 s fie disponibil pe bitul cu index 0 din R17, starea butonului D6 s se poat citi din bitul aflat pe poziia 1 n R17, i aa mai departe. Practic, strile butoanelor vor fi pe poziii inversate n R17 fa de subrutina prezentat n crulie. 2. Modificai aceeai subrutin de citire a tastelor pentru ca strile butoanelor s ajung dup logica discutat n momentul n care am nceput minitastatura : un 0 s spun c respectivul buton a fost apsat, iar un 1 va preciza, evident, c butonul nu este apsat.

[9s] i dac totul este bine, s continum


Avem subrutine de folosire a afiorului i de citire a tastaturii precum i subrutine de iniializare a discuiilor cu respectivele module externe i chiar o secven de cod prin care putem s ntrziem o aplicaie. Avnd toate acestea i urmrind tabelul de instruciuni recunoscute de creiera, ne propunem s realizm un exemplu mai complex i complet de utilizare a ceea ce am nvat pn acum. Afiorul a avut 2 astfel de exemple mai complicate, pentru minitastatur vom aborda doar unul, dar nu vom avea nevoie de altele dup cum vom vedea.

104

Ne propunem s realizm o aplicaie care s reacioneze diferit n funcie de ultima tast apsat. Meniul i modul de reacie al aplicaiei va fi urmtorul : Dac nu este apsat nicio tast, imediat dup pornirea aplicaiei, Ale va numra cresctor din 1 n 1, La apsarea butonului D3 aplicaia va numra descresctor din 3 n 3, Apsarea butonului D2 va selecta o incrementare din 2 n 2, Butonul D1 va duce la o decrementare continu a valorii curente din 1 n 1, iar D0 va selecta o incrementare din 1 n 1. Practic, vom realiza o aplicaie care, printr-un meniu de 4 opiuni selectabile prin 4 butoane (D0-D3) va conduce la executarea unor secvene de instruciuni diferite. S introducem bucata de cod principal care rezolv acest exerciiu i apoi s-l discutm : main: rcall initializeaza_perif ldi R18, 1 ; R18 va conine numrul programului curent ce-l execut Ale executa_vesnic: rcall citeste_taste_r17 ; citete starea tastelor n R17 tst R17 ; verific dac nu s-a apsat niciun buton breq reinoire_nenec ; dac nu este apsat niciun buton, menine vechea opiune selectat mov R18, R17 ; ajungnd aici, nseamn c s-a apsat cel puin un buton
; valoarea lui R17 d noua selecie a programului ; === secven de instruciuni care actualizeaz valoarea afiat R16 dup programul curent === ; conform exerciiului, pornete cu opiunea lui D0 (program 1)

reinoire_nenec: sbrc R18, 0 ; programul 1 ? Da : rjmp incrementeaza_1 sbrc R18, 1 ; programul 2 ? Da : rjmp decrementeaza_1 sbrc R18, 2 ; programul 3 ? Da : rjmp incrementeaza_2 sbrc R18, 3 ; programul 4 ? Da : rjmp decrementeaza_3

incrementeaza_1: inc R16 ; opiune de incrementare din 1 n 1 rjmp afiseaza_secventa decrementeaza_1: dec R16 ; selecie de decrementare din 1 n 1 rjmp afiseaza_secventa incrementeaza_2: ldi R19, 2 add R16, R19 ; realizm adunarea dorit : R16 = R16 + 2 rjmp afiseaza_secventa decrementeaza_3: ldi R19, 3 sub R16, R19 ; realizm scderea dat de opiune : R16 = R16 - 3 afiseaza_secventa:

105

rcall afiseaza_r16 ; afim valoarea curent a programului rcall intarzie_un_pic rjmp executa_vesnic Ca i structur, putem s observm bucla principal n care facem, n ordine, urmtoarele aciuni : 1. citim starea tastelor pe care o ncrcm n R17, 2. dac nicio tast nu s-a apsat, folosete vechea selecie a aplicaiei pentru a actualiza valoarea ce va fi afiat, iar 3. dac s-a apsat unul din butoanele D0-D3, meniul alege alt regiune de cod s fie executat precum i alt mod de actualizare a valorii de afiat. Partea interesant a acestei aplicaii, pe lng posibilitatea de a putea controla n ce fel s se comporte, o constituie ideea de comunicare cu plcua. Nu trebuie mult s ne dm seama c n locul instruciunilor de la etichetele incrementeaza_2 sau decrementeaza_1, de pild, putem avea orice alte comenzi, realiznd orice alt lucru ne trece prin cap. Acum, avnd subrutine pentru afior i minitastatur, se pune ntrebarea dac putem rescrie chiar mai eficient aceste comportamente ? Prin eficien, vreau s m refer la spaiul ocupat de subrutine n mod special. Pn acum am avut de-a face cu module date de componente externe creieraului. Dup cum spuneam atunci cnd discutam prima dat despre Attiny, aceasta nu este chiar toat povestea. Dac mai inei minte, spuneam la un moment dat c regitrii DDRB, PORTB i PINB fceau posibile comunicaiile cu exteriorul (spuneam c ei fac parte din modului de intrare/ieire intern creieraului). n direcia posibilitilor interne ne vom ndrepta atenia pentru care vom construi, n seciunile ce urmeaz, metode mai eficiente de a lucra cu creieraul. Cu alte cuvinte, vom urmri s rescriem instruciunile apelnd nu la trucuri detepte date de instruciunile disponibile ci direct la capacitile interne ale creieraului. Ne vom ocupa, pentru nceput, de subrutina de ntrziere ...

ntrebri / Exerciii : 1. Ce se ntmpl dac, pentru aplicaia noastr, apsm deodat 2 butoane n loc de 1 (D0 i D2, de pild) ? De ce credei c se ntmpl asta ? 2. Modificai aplicaia de mai sus pentru a porni de la selecia dat de butonul D2 n loc de D0 3. Modificai aplicaia de mai sus adugnd opiunea D4 care, fololsind instruciunea SWAP, va inversa continuu cele 2 jumti ale octetului de afiare R16 4. Pentru aplicaia de mai sus, gsii alte instruciuni care pot nlocui aceast secven : tst R17 breq reinoire_nenec

[10s] ntrzieri mai bune


nainte de a avea ntrzieri mai bune, trebuie s nelegem de ce vrem ntrzieri mai bune. Dei avem o subrutin care face acest lucru, i o face chiar bine, se poate mai bine! Ce ai spune dac am putea face urmtoarele aciuni :

106

1. pornim ceasul i 2. ne uitm din cnd n cnd la el, iar atunci cnd a trecut perioada dorit, facem aciunea dorit, lsndu-ne posibilitatea s lucrm ntre timp la alte sarcini. Ar fi frumos, dar de unde ceas ? probabil ntrebai. Plcua nu are aa ceva. Ei bine, acum vine vestea oc! : ceasul respectiv exist i se afl direct pe creiera! Attiny-ul are chiar 2 astfel de ceasuri interne. V vine s credei c exist aa ceva n componenta aia aa de mic cu 8 piciorue ? Nici mie, dar dup cum vom afla, creieraul lui Ale ne rezerv multe surprize. S revenim. n seciunea de fa vom vedea cum putem s folosim unul din cele 2 ceasuri de pe Ale pentru a obine efectul de ntrziere, dar fr atta cod sau cel puin fr o subrutin n care s ardem timpul prin instruciuni. Vom discuta despre ceasul0, aa cum este cunoscut n foia de catalog a lui Attiny25. Este vorba de un ceas care poate numra de la 0 la 255 folosind un registru special de 8 bii, iar ca baz de timp, se pot folosi mai multe opiuni : se poate incrementa fie o dat cu baza de timp principal (o dat la

1 s=1 s ), fie o dat la 8, 64, 256 sau 1024 uniti 1000000

principale de timp. Asta se traduce, pentru o Ale proaspt scoas din cutie, la o incrementare a valorii ceasului odat la 81 s=8 s , 641 s=64 s , 2561 s=256 s sau 10241 s=1024 s=1.024ms . Asta nseamn c dac alegem un factor de 256 pentru incrementare, vor trece aproximativ 100256 s=25600 s=25.6ms pentru a numra 100 de valori ale ceasului. ntrzierea cea mai mare va fi, n acest caz, dac vom folosi un factor de 1024 i vom numra de la 0, oprindu-ne de 2551, vom consuma 2551.024ms=261.12ms . Ce ciudat! Vorbim de ntrzieri, dar nu am discutat nc cum putem porni ceasul. Dac nu i cerem noi explicit, odat cu alimentarea plcuei, ceasul precum i mai toate modulele interne sunt iniial nchise. Pentru a face asta, ai ghicit, trebuie s folosim registre speciale. Toate modulele interne au astfel de registre i ceasul0 nu face excepie de la regul. Pentru aceast seciune, este suficient s cunoatem 2 regitri (poate 3, vom vedea). Unul este folosit la iniializarea modulului i se noteaz TCCR0B2, iar cellalt reprezint valoarea efectiv a ceasului (ct a reuit el s numere) i se abreviaz TCNT03. ncepem cu iniializarea : TCCR0B este situat la adresa 0x0033 n spaiul regitrilor de control (0x0033 + 0x0020 = 0x0053 n spaiul real de memorie), iar biii si au urmtoare semnificaie :

dup atingerea acestei valori, ceasul nu se oprete, dar urmtoarea valoare va fi 0 i va continua s se incrementeze de acolo 2 provine din englez de la Timer/Counter Control Register B care se traduce n Registrul de control B al ceasului0. Exist i un Registru de control A, dar nu-l vom discuta aici 3 n englez, varianta complet ar fi Timer/Counter Register ceea ce reprezint Registrul de numrare al ceasului0

107

Rang Notaie Op. permise Val. iniial

FOC0A S 0

FOC0B S 0

---

---

WGM02

CS02

CS01

CS00

C 0

C 0

S/C 0

S/C 0

S/C 0

S/C 0

Unde literele de la notaie au urmtoarele semnificaii : Denumire FOC0A, FOC0B --Nume complet Foreaz compararea cu registrul A/B Nefolosit Semnificaie Asigur funcionalitti speciale de ntrzieri pe care le vom discuta un pic mai ncolo. Valoarea citit va fi mereu 0 logic. Valoarea bitului respectiv nu are nicio ntrebuinare electric de aceea ea nu poate fi dect citit (C), iar valoarea citit va fi de 0 logic. Bitul reprezint valoarea superioar a unui grup de 3 bii prin care se poate activa o funcionalitate avansat de generare de semnal direct din creiera prin pinii externi. Nu vom discuta aceste capaciti pentru Ale pentru c nu avem cum s punem n eviden acest comportament pe plcu, dar el exist i mai multe informaii le putei gsi n foaia de catalog a creieraului. Prin aceti bii se poate selecta acel factor de care discutam adineauri. Posibilele valori sunt : CS02 0 0 0 0 1 1 1 1 CS01 0 0 1 1 0 0 1 1 CS00 0 1 0 1 0 1 0 1 Factor Modul dezactivat 1 8 64 256 1024 Nefolosit Nefolosit

WGM02

Mod de generare a formei de und

CS00, CS01, CS02

Selectarea sursei de ceas

Dup cum observm, valoarea iniial este 000 dovedind c modulul este, la nceput, nchis. nainte de a iniializa modulul, s stabilim ce ne propunem s afim. S zicem c dorim s reimplementm numrtorul binar discutat acum cteva seciuni folosind noua metod de ntrziere. Avnd n vedere faptul c factori mici dicteaz o ntrziere foarte mic, vom

108

urmri alegerea unui factor mare pentru ceasul0. 1024 este cel mai mare i de aceea l vom folosi pe acesta. De asemenea, vom incrementa 255 de valori de la 0 la 255 plus nc o incrementare de la 255 la 0 care reseteaz contorul ceasului. n total, vom realiza 256 de incrementri nainte s mergem la urmtoarea valoare binar de afiat. Acest aspect, mpreun cu factorul ceasului, ne va conferi, aa cum am vzut, o ntrziere de circa 1 s1024256=1024 s256 ceea ce conduce la urmtorul rezultat : 1.024ms256=262ms . Pentru scurte clarificri precizm c 1 s reprezint baza de timp a creieraului, 1024 este factorul ales pentru ceas, iar 256 semnific numrul de incrementri suportate de ceasul0. Asta nseamn c vom vedea aproximativ valori binare pe secund pe afior. Dar nainte de cod, haidei s vedem i cellalt registru. Despre TCNT0 este vorba i este situat la adresa 0x0032 n spaiul regitrilor de control (0x0032 + 0x0020 = 0x0052 n spaiul real de memorie), iar biii si au urmtoare semnificaie : Rang Notaie Op. permise Val. iniial
7 6 5 4 3 2 1 0

1000 =3.81 262

TCNT07

TCNT06

TCNT05

TCNT04

TCNT03

TCNT02

TCNT01

TCNT00

S/C 0

S/C 0

S/C 0

S/C 0

S/C 0

S/C 0

S/C 0

S/C 0

Unde literele de la notaie au urmtoarele semnificaii : Denumire TCNT07 TCNT00 Nume complet Numrtorul ceasului0 Semnificaie Registru ce conine valoare de numrare a ceasului0 prin care se poate ine direct evidena timpului trecut

n regul, abordarea aplicaiei este simpl : 1. iniializm perifericile i modulul intern al ceasului0. Odat setat factorul de incrementare pe 1024, ceasul nostru va ncepe s numere. Important : Ceasul va numra n paralel cu aplicaia noastr! Gndii-v la el ca un obiect din fundal. Odat pornit, el va funciona i-att. Rezultatul l vom putea culege prin TCNT0 oricnd dorim. 2. Verificm continuu TCNT0 i incrementm valoarea afiat dac TCNT0 atinge valoarea de 255 3. Valoarea imediat a TCNT0-ului dup 255 va fi 0, ceasul resetndu-se i numrtoarea continund de la 0 S vedem cum rezolvm iniializarea. Pentru asta avem nevoie de o serie de definiii ale cuvintelor cheie pe care le vom folosi n soluie. Aceste noi definiii sunt : TCCR0B = 0x33 TCNT0 = 0x32 Vrem s folosim un factor de 1024, deci vom avea urmtoarea secven n subrutina de initializare_perif:

109

initializeaza_perif: ldi R16, 0b00000101 ; pornim ceasul0 cu un factor de 1024 ceea ce ne d, la un ceas de baz de out TCCR0B, R16 ; 8Mhz, o incrementare la aproximativ 128 s ldi R16, 0b00000011 ; minitastatura este oprit (nu o folosim) i afiorul este pornit out DDRB, R16 ret Odat cu iniializarea, trecem direct la aplicaia principal. Nu uitai : nu mai avem subrutina de intarzie_un_pic! main: rcall initializeaza_perif ldi R16, 0 executa_vesnic: in R17, TCNT0 ; citim valoarea contorului ceasului0 cpi R17, 255 ; verificm dac s-a atins valoarea 255 brne executa_vesnic ; dac nu, mai ateptm inc R16 ; dac da, incrementm valoarea curent i o afim rcall afiseaza_r16 rjmp executa_vesnic Dup trimiterea codului spre plcu i alimentarea sa, vei observa ceva ciudat : codul merge, dar primele 3 LED-uri par s nu se aprind. Ce se ntmpl ? Instruciunile noastre par s nu justifice acest comportament. Ce nu nelegem ? Rspunsul la aceast ntrebare vine dat de 2 indicii : ceasul i, n general, modulele interne funcioneaz n paralel cu execuia aplicaiei. Asta nseamn c ele nu stau pe loc n timp ce creieraul rumeg codul nostru, instruciune cu instruciune, iar o incrementare a contorului ceasului pentru o baz de timp de 1 Mhz cu un factor de 1024 necesit 1.024ms . Cu alte cuvinte, n urma atingerii valorii de 255 a lui TCNT0, brne executa_vesnic nu se mai execut i se trece la inc R16 i apoi la afiare, dar TCNT0 va pstra valoarea 255 timp de 1.024ms ct dureaz o incrementare. Aici este problema : stnd 1.024ms pe valoarea 255, de fapt nu se realizeaz o singur incrementare i afiare ci mai multe. Cte ? Attea cte ncap n cele 1.024ms sau aproximativ 8, dac este s numrm valorile ce ncap pe cele 3 LED-uri ce par mereu nchise. Dac dorim o demonstraie mai complet, putem lua n calcul faptul c un apel al subrutinei afiseaza_r16 dureaz aproximativ 110 s (vezi captura de osciloscop realizat la exemplul 4s) la care mai adugm cele 5 instruciuni (aproximate grosier prin 5 s ) din ciclul executa_vesnic, atunci practic secvena se execut n 1.024ms de

1024 s 1.024ms = =8.904 ori. Cum pe afior 110 s+5 s 105 s

vedem doar rezultate complete, iar timpul real de execuie a ciclului este supus unor erori de msurare, putem s ignorm partea zecimal a acestui rezultat ( 0.904 ) i s tragem concluzia c ntr-adevr, atunci cnd TCNT0 are valoarea 255, se realizeaz 8 execuii complete ale ciclului executa_vesnic i nu una.

110

Avnd n vedere c afiarea se face doar atunci cnd TCNT0 este 255, putem chiar s prindem aceste 8 apeluri de afiseaza_r16 i o facem n urmtoarea captur de osciloscop :

Canlul 1 a fost conectat la ceasul lui 74HC164, iar canalul 2 a cules tranziiile de pe pinul de date a aceluiai circuit. Mai observai v rog cum cele 8 afiri se deruleaz toate n x=1.08ms . Aceast valoare vine n sprijinul explicaiilor purtate mai sus. Probabil v ntrebai de ce nu vedem respectivele incrementri dac ele se tot ntmpl ? Rspunsul se poate observa din captura de osciloscop. Ele ntr-adevr se ntmpl, doar c se execut toate 8 n paroximativ 1.024ms , cut dureaz o incrementare. Un timp muuult prea mic pentru a putea s le distingem ca valori individuale. Totui, exist o dovad direct a faptului c cele 8 incrementri se realizeaz : plpirea slab a LED-urilor ntre actualizri. Plpirile se datoreaz deplasrilor rapide ce se petrec pe LED-uri conform modului de funcionare a afiorului. i atunci, ne putem gndi, putem face ceva s remediem comportamentul acesta ? Dup cum exemplele noastre precedente au artat-o, DA! Se poate repara. Mi-ar face plcere s tiu c reuii s v dai seama singuri cum ar putea fi dus la capt aceast dilem. Indiciu : privii operaiile permise pe registrul TCNT0. Dac nu reuii singuri, s nu v facei griji c o discutm mpreun. Cu Ale, niciodat nu suntem singuri. Mereu exist cineva care ne poate ajuta! O variant ar fi s form valoarea lui TCNT0 s fie 0 imediat dup ce ea atinge valoarea 255. n felul acesta, incrementarea lui R16 s-ar realiza o singur dat dup 255 de valori a lui TCNT0 sau aproximativ 262ms n timp real. Este n regul soluia, dar exist o mic problem cu timpii : fornd o resetare din instruciuni practic nghiim o incrementare a ceasului0 sau 1.024ms . Totui, aceast pierdere nu este aa de grav pentru noi astfel nct putem s folosim soluia fr prea mari probleme. Modificare const doar din 2 instruciuni introduse astfel :
; alte instruciuni din secvena principal

brne executa_vesnic ldi R17, 0 ; resetm TCNT0 pentru a se executa o singur dat incrementarea lui R16 out TCNT0, R17 ; pentru 255 de incrementri a lui TCNT0

111

inc R16
; restul de instruciuni din secvena principal

i aa rezolvm problema. Soluia nu este unic, iar alte variante sunt chiar ncurajate, dar aceasta funcioneaz i este un lucru suficient pentru crulie. Observai v rog cum, dei nu avem o subrutin de ntrziere, nici nu avem nevoie de una. Ceasul intern poate face fa cu uurin acestei sarcini. n felul acesta putem obine ntrzieri fr s scriem instruciuni care s consume timp. Obinem spaiu mai mult pentru instruciuni i respectiv, din cauza modului de operare n paralel a ceasului, obinem i timp pentru a executa un numr mai mare de comenzi. Ce zicei s mpingem lucrurile un pic mai departe ? Ce ai zice dac secvena principal ar fi asta : main: rcall initializeaza_perif clr R16 executa_vesnic: inc R16 rjmp executa_vesnic i efectul ar fi oarecum acelai : afiarea valorii incrementate ? Credei c este imposibil ? S ncepem discuia despre ntreruperi ntrebri / Exerciii : 1. ncercai exemplul de mai sus cu ali factori de incrementare (de exemplu 256) i vedei cum se comport aplicaia. 2. Ce se ntmpl dac nlocuim asta : cpi R17, 255 cu asta : cpi R17, 120 ? Cum explicai acest lucru ? 3. n exemplul de mai sus, nlocuii instruciunea aceasta : ldi R17, 0 cu asta : ldi R17, 250. Cum afecteaz asta comportamentul codului nostru? Argumentai.

[11s] Fr ntreruperi, v rog


ncep aceast seciune printr-o simpl ntrebare : ce ne-am face noi fr ntreruperi ? Ce sunt ntreruperile, m ntrebai ? Le-am mai discutat un pic atunci cnd am vorbit despre memoriile Attiny-ului, dar aici le vom explica mai n detaliu. Pentru c ne plac definiiile, vom ncerca s dm una i pentru noiunea de ntrerupere (de dragul corectitudinii). Astfel, o ntrerupere reprezint apariia, la un moment necunoscut n timp, a unui eveniment care trebuie bgat n seam. Aceasta ar fi o definiie pe nelesul tuturor, ne-electronic n mod special, pentru c termenul este unul general folosit. Noi, ca i oameni, suntem exemple bune de organisme care rspund la ntreruperi. S ne gndim pentru moment : servim micul dejun i, deodat, scpm lingura pe jos. Evenimentul nu a fost unul plnuit i noi reacionm imediat ridicnd lingura (eventual punnd-o la splat i lund alta n schimb). Fceam o aciune i, dintr-o dat, fr nicio avertizare, am fost nevoii s reacionm la un eveniment. Fie c suntem n cas sau pe strad, treji sau adormii, tineri sau n vrst trim ntr-un mediu dinamic i de cele mai multe ori impreivizibil. Evenimentele apar, iar noi rspundem la ele cum putem noi mai bine.

112

Ideea de ntreruperi nu este prezent doar la sisteme biologice cum sunt oamenii sau pisicile. Creatorii primelor calculatoare au vzut potenialul ntreruperilor i l-au implementat nc din momentul apariiei primelor maini de calcul. Cel mai simplu exemplu n acest sens ar fi tastatura unui calculator. Gndii-v ce plictisitoare ar fi viaa n care calculatoare nu ar face nimic pn nu le-am da o informaie ce o ateapt. i dac ar trebui s dm mai multe ? Spre norocul nostrul, modul n care tastaturile moderne funcioneaz este altul : calculatorul execut aplicaia sa neateptnd dup tastatur, dar cnd se apas o tast, o ntrerupere este generat i trimis ctre calculator pentru a se rezolva. Desigur, de acolo mai departe, calcualtorul poate alege ce s fac cu respectiva ntrerupere : s o ignore, sau, de cele mai multe ori, s o onoreze. Vedei utilitatea ? Nu ateptm dup un eveniment pe care nici nu tim cu siguran dac el va veni vreodat sau nu (apsarea unei taste) ci pur i simplu atunci cnd vine, rspundem la el. i Ale cunoate ntreruperi exact pe acelai principiu i la fel de puternice. Sursele de ntreruperi recunoscute de Ale sunt multe, dar majoritatea sunt date de modulele sale interne precum ceasurile (avem 2, mai inei minte ?). Desigur c ea poate s rspund i la schimbri de valori logice din exterior, dar noi ne vom ocupa de cele majoritar interne. Mecanismul de ntreruperi a lui Ale este simplu : Prima i prima dat creieraul pornete cu ntreruperile dezactivate (ea nu rspunde la niciun eveniment neateptat dect la modulul de Reset), de aceea trebuiesc activate acele surse de ntreruperi care ne intereseaz Odat ce un eveniment de ntrerupere care este recunoscut i activat de sistem este interceptat, execuia curent a programului este suspendat (starea creieraului este mpins pe stiv) i execuia sare la o tabel de adrese Fiecare adres este bine fixat i reprezint un punct de intrare n sistem pentru diferite surse de ntreruperi Tabela respectiv este una foarte compact i nu suport dect 1-2 instruciuni. De aceea ea conine, de obicei, instruciuni de salturi la subrutine de tratare a ntreruperilor Dup soluionarea ntreruperii respective (executarea ultimei instruciuni din subrutina de tratare), creieraul i reia starea sa salvat de pe stiv i continu execuia normal a aplicaiei de unde a rmas Attiny25 cunoate 15 surse de ntreruperi dintre care cu una noi am fcut deja cunotin : ntreruperea de Resetare. Atunci cnd sistemul pornete, el sare n tabelul de ntreruperi la adresa relativ 0x0000 (acolo aflndu-se punctul de intrare a ntreruperii de Reset) i ncepe execuia din acel punct. Noi i spunem la Ale c prima instruciune de dup resetare este dat, mai tot timpul, de adresa etichetei main din urmtoarea instruciune : .global main , iar pentru alte surse de ntreruperi, vom folosi aceleai procedeu. n aceast seciune ne vom ocupa de capacitatea creieraului de a rspunde la evenimente generate de ceasul0. n mod special, ne vom ocupa de capacitatea ceasului0 de a genera o ntrerupere dup ce face pasul de la valoarea 255 la valoarea 0. Adic dup ce valoarea numrtorului se reseteaz sau, mai corect spus, depete valoarea maxim ce o poate pstra. Din acest motiv, aceast ntrerupere mai poart denumirea de ntrerupere de depire a ceasului0.

113

Ceasul0 (despre el discutm aici, dar noiunile sunt adevrate i pentru ceasul1), are indexul 6 n tabel i adresa relativ 0x0005. Coaserea subrutine de tratare a ntreruperii n vectorul de ntreruperi se face n felul urmtor : .global __vector_5 Important : De regul, denumirile etichetelor pentru rutinele de tratare a ntreruperilor urmresc o regul bine stabilit. Ele ncep cu __vector_ la care se adaug indexul din tabel pe care dorim s o gestionm. Cum indexul este dat de adresa relativ a subrutinei dorite scris n baza 10, eticheta prin care avem acces la subrutina de tratare a ntreruperii de depire a valorii ceasului0 devine __vector_5. Bineneles c va trebui s avem i subrutina de tratare fizic, cu instruciuni. Ea se va completa pe urmtorul ablon : __vector_5:
; instruciuni de rspuns la evenimentul

reti Observai v rog terminarea bucii de cod cu instruciunea reti. Acest lucru, dup cum vom vedea, nu este o greeal de scriere i nu este ales ntmpltor. S o lum cu nceputul. La ce este bun un schelet, dac ntreruperile sunt iniial dezactivate n sistem ? S le activm. n aceast idee exist 2 nivele de activare . De ce dou ? Poate pentru este mai convenabil aa : exist posibilitatea de a dezactiva toate ntreruperile sistemului prin resetarea bitului I din registrul SREG (l-am discutat) i posibilitatea de a dezactiva ntreruperi individuale cum ar fi ntreruperea care ne intereseaz pe noi la ceasul0. Acest lucru se poate face dintr-un registru special al modulului : TIMSK1. Dar pe noi nu ne intereseaz resetarea/dezactivarea ntreruperilor ci din contr : vrem s tim cum s le pornim. Pentru aceasta, s ne uitm un pic la componena registrului TIMSK care este situat la adresa 0x0039 n spaiul regitrilor de control (0x0039 + 0x0020 = 0x0059 n spaiul real de memorie), iar biii si au urmtoare semnificaie : Rang Notaie Op. permise Val. iniial
7 6 5 4 3 2 1 0

---

OCIE1A

OCIE1B

OCIE0A

OCIE0B

TOIE1

TOIE0

---

C 0

S/C 0

S/C 0

S/C 0

S/C 0

S/C 0

S/C 0

C 0

Unde literele de la notaie au urmtoarele semnificaii : Denumire --OCIE1A, OCIE1B, OCIE0A,


1

Nume complet Nici unul Controlul ntreruperii la potrivirea valorilor

Semnificaie Bitul nu are nicio influen asupra sistemului i la citire are mereu valoarea 0. Surse de ntreruperi ale ceasului[0 i 1] care se declaneaz atunci cnd valoarea numrtorului este egal cu o valoare dorit. Scrierea unui 1

din englezescul Timer/Counter Interrupt Mask Register sau Registrul de control al ntreruperilor ceasului0 i ceaslui1. Din cauza numrului redus de ntreruperi i pentru a economisi spaiu, ambele ceasuri au aelai registru de control al ntreruperilor

114

OCIE0B TOIE1, TOIE0 Controlul ntreruperii de depire a valorii maxime (255, n mod uzual)

logic activeaz ntreruperea pe cnd un 0 logic o deactiveaz. Asigur rspunsul la ntreruperi de depire a valorii maxime posibile de ctre numrtorul ceasului. Pentru activare, scriem pe bitul respectiv 1, iar pentru dezactivare scriem 0.

De SREG nu ne vom ocupa, discutndu-l ntr-o seciune precedent (vezi. seciunea cu instruciunile recunoscute de Ale). Aadar, pentru iniializarea ntreruperii dorite, procedm n felul urmtor : Iniializm modulele dorite, Iniializm ntreruperile modulelor folosite i apoi Activm ntreruperile globale (setm bitul I din SREG cu instruciunea SEI) Noi avem un singur modul cu ntrerupere i acesta este ceasul0. Adugm, mai nti, la tabelul de definiii i registrul TIMSK : TIMSK = 0x39 i continum cu modificarea subrutinei de iniializare a perifericelor : initializeaza_perif: ldi R16, 0b00000101 ; iniializm ceasul0 cu un factor de 1024 out TCCR0B, R16 ldi R16, 0b00000010 ; activm ntreruperea de depire a ceasului0 out TIMSK, R16 sei ; activm ntreruperile globale ldi R16, 0b00000011 ; minitastatura - oprit; afiorul - pornit out DDRB, R16 ret i asta a fost tot : mpreun cu subrutina de rspundere la eveniment, ntreruperea este implementat. Ce scriem n subrutina respectiv, ntrebai ? Aciuni ce dorim s se realizeze o dat ce au trecut cele aproximativ 262ms (n cazul nostru). Ce ziceti de asta ? : __vector_5: rcall afiseaza_r16 reti Din cauza faptului c am discutat multe noiuni, redau aici esena aplicaiei noastre : TIMSK = 0x39 TCCR0B = 0x33 TCNT0 = 0x32 DDRB = 0x17 PORTB = 0x18 PB0 = 0x00 PB1 = 0x01

115

.section .text .global main .global __vector_5 main: rcall initializeaza_perif clr R16 executa_vesnic: inc R16 rjmp executa_vesnic __vector_5: rcall afiseaza_r16 reti initializeaza_perif: ldi R16, 0b00000101 out TCCR0B, R16 ldi R16, 0b00000010 out TIMSK, R16 sei ldi R16, 0b00000011 out DDRB, R16 ret Mai lipsete definiia complet a subrutinei de afiare, dar ea este aceeai pe care o tim i din motive de economie a hrtiei, nu o mai rescriem. Aadar dac trecem aceste instruciuni pe plcu ce vom vedea? De fapt, ce ne ateptm s vedem? S nu uitm c ceasul0 numr deodat (n paralel, ne place nou s spunem) cu aplicaia principal. Dup ce ceasul0 incrementeaz valoarea sa de la 255 la 0, subrutina ntreruperii este executat. Singura instruciune ce o avem n ea este apelarea subrutinei de afiseaza_r16. Dar R16 se incrementeaz continuu n codul principal : executa_vesnic: inc R16 rjmp executa_vesnic n concluzie, afiorul va renoi valoarea LED-urilor o dat la aproximativ 262ms cu valoarea ce o gsete n R16. Avnd n vedere c R16 se modific continuu n fundal, ea va apuca s se reseteze (s se incrementeze de la 255 la 0 fiind pe 8 bii) de foarte multe ori pn cnd subrutina de ntrerupere se va declana. Rezultatul nu va arta deloc cu o incrementare binar normal ci, mai degrab, cu nite secvene haotice de LED-uri aprinse. Dac ncercai s le urmrii mai bine, vei observa c ele se repet din cnd n cnd. Acest lucru se datoreaz preciziei ceasului0. Dac perioada de declanare nu ar fi fost fix (n cazul nostru aproximativ 262ms ), atunci rezultatul ar fi artat foarte diferit. Pentru a nelege mai bine ce se ntmpl cu execuia aplicaiei noastre, propun s urmrim urmtorul desen :

116

n aceast diagram putem vedea, pe axa timpului care curge de la stnga la dreapta, cum ceasul0 incrementeaz n paralel TCNT0 cu aplicaia principal. Aplicaia principal incrementeaz, aa cum am discutat, R16. La un moment dat, la trecerea lui TCNT0 de la 255 la 0, aplicaia principal este ntrerupt, subrutina de tratare a ntreruperii este executat i apoi execuia firului principal se reia. Observai ct de puternice sunt aceste ntreruperi ? Am obinut acest efect cu minimul de instruciuni folosite (cteva atunci cnd am iniializat sistemul de ntreruperi) i minimum de efort intelectual : urmrii ct de goale sunt subrutinele. Dac nu am folosi ntreruperi ele ar fi pline de cod (salturi, instruciuni aritmetice : adunri, scderi, etc.) pentru a obine comportamentul dorit. Nu sunt ntreruperile o chestie tare ? n continuare, aa cum ne-am obinuit, vom prezenta o alt surs ntrerupere ce este generat de ceasul0. Vom discuta de precizie ntrebri / Exerciii : 1. Ce se ntmpl dac o subrutin de tratare a ntreruperii se termin, tradiional, cu instruciunea ret i nu cu reti ? ncercai asta n aplicaie. Cum v-ai explica acest comportament ? 2. Ce credei : putem folosi liniile acestea : .global __vector_0 __vector_0:
; .. instruciuni din secvena principal

n locul acestor linii : .global main main:


; instruciuni ale aplicaiei noastre

Verificai pe plcu. 3. Rescriei aplicaia de mai sus pentru a folosi ceasul0 cu un factor de 64 n loc de 1024. Ce putei spune despre viteza de modificare a LED-urilor ? Este normal comportamentul ?

117

[12s] Alt ntrerupere, acelai ceas0...


Haidei s ncercm ceva am vzut cum putem folosi ntreruperea de depire a valorii maxime a ceasului0 pentru a obine generarea unei ntreruperi la aproximativ 262ms folosind un factor de 1024. 262 este un numr tare ne-rotund. S ncercm s ne gndim cum am putea s rezolvm asta. S zicem c dorim s generm o ntrerupere la 250ms , de exemplu. Se poate aa ceva ? i dac da, cum ? S nu uitm c ntreruperea ce o tim noi se declaneaz la trecerea lui TCNT0 de la 255 la 0. O modalitate ar fi s folosim alt factor pentru ceasul0. Dar care ? Dac folosim 256, la 1 Mhz vitez de execuie a aplicaiei, vom avea generat o ntrerupere la fiecare (255+1)256 s=256256 s (vezi i explicaia de la exemplul 10s) sau 65536 s=65.536ms . Noi vrem precizie, vrem 100ms , deci nu ne prea ajut valoarea. Dac folosim un factor de 64, ceasul0 va genera o ntrerupere o dat la 25664 s=16384 s=16.384ms . Tot nu este bun. Mai mult, pe msur ce scdem factorul folosit, perioada de generare a ntreruperii scade i ea. Noi vrem fix (sau ct mai exact cu putin) o ntrerupere la fiecare 250 de milisecunde scurse. Ce putem face ? La un factor de 1024, singurul care genereaz ntreruperi cu un interval mai mare de

250ms , valoarea urmrit de noi, TCNT0 va avea valoarea

250 =244.14 sau 1024

aproximativ 244. Problema este c noi nu putem genera o ntrerupere la orice valoare a lui TCNT0 prin ntreruperea precedent nvat (care se declaneaz ntre 255 i 0). Corect. Nu putem folosi ntreruperea nvat, dar alta ? Exista alt ntrerupere generat de ceasul0 care este perfect pentru acest scop i pe care o putem folosi. Se numete ntrerupere de egalare sau ntrerupere de echivalen i se declaneaz atunci cnd TCNT0 este egal, ca i valoare, cu un anumit registru. Alegnd valoarea TCNT0 pentru care o ntrerupere a ceasului0 s se declaneze, obinem un control mai bun asupra perioadei de execuie a codului dorit. Ceasul0 are dou astfel de ntreruperi de egalare i, n consecin, doi astfel de regitri : OCR0A1 i OCR0B2. Putem face ca la potrivirea lui TCNT0 cu valoarea dorit pe care o pstrm n registrul OCR0A, s executm ntreruperea ce are adresa relativ 0x000A (sau 10, n sistem zecimal) din tabelul de ntreruperi. De asemenea, se poate ca la potrivirea lui TCNT0 cu OCR0B, s facem creieraul s sar n tabela de ntreruperi i s execute secven ce o gsete la adresa relativ 0x000B (= 11, n baza 10). Pentru scopul nostru, vom folosi doar una din cele 2 ntreruperi, dar nu stric dac tim de pe acum de ambele. Vom utiliza registrul OCR0A care este situat la adresa 0x0029 n spaiul regitrilor de control (0x0029 + 0x0020 = 0x0049 n spaiul real de memorie), iar biii si au urmtoare semnificaie :

din englez Output Compare Register A care n romn ar nsemna Registrul de comparare A al ceasului0 2 provine din englezescul Output Compare Register B care se traduce n romn prin Registrul de comparare B al ceasului0

118

Rang Notaie Op. permise Val. iniial

OCR0A7

OCR0A6

OCR0A5

OCR0A4

OCR0A3

OCR0A2

OCR0A1

OCR0A0

S/C 0

S/C 0

S/C 0

S/C 0

S/C 0

S/C 0

S/C 0

S/C 0

Unde literele de la notaie au urmtoarea interpretare : Denumire OCR0A7 OCR0A0 Nume complet Registrul de comparaie A al ceasului0 Semnificaie n el pstrm valoarea cu care TCNT0 din ceasul0 se compar. La potrivire, putem face s se genereze o ntrerupere specific.

Doar ca i informaie general, OCR0B are aceeai structur ca i OCR0A. Odat definit registrul, pentru activarea ntreruperii respective, trebuie s scriem un 1 logic pe bitul OCIE0A din TIMSK. Registrul TIMSK l-am discutat mai sus pentru cei ce nu-l cunosc. Trecem definiia registrului OCR0A n capul surselor noastre : OCR0A = 0x29 i srim n rutina de iniializare a perifericelor pentru a activa respectiva ntrerupere (nu mai folosim ntreruperea de depire deci ea nu va mai fi prezent) : initializeaza_perif: ldi R16, 244 ; fixm valoarea de comparare n registrul OCR0A out OCR0A, R16 ldi R16, 0b00010000 ; activm ntreruperea de potrivire TCNT0 <-> OCR0A out TIMSK, R16 ldi R16, 0b00000101 ; pornim ceasul0 cu un factor de 1024 out TCCR0B, R16 sei ; activm ntreruperile globale ldi R16, 0b00010011 ; afior - pornit, minitastatur - pornit out DDRB, R16 ret Dup cum se poate vedea, pe lng activarea ntreruperii de potrivire a registrului 0, avem i ncrcarea efectiv a valorii de potrivit n OCR0A. Acest lucru l realizm cu un scop aici : din cauza faptului c OCR0A pornete pe valoarea 0, dac am activa ntreruperea cu OCR0A 0, innd cont c TCNT0 ncepe, de asemeni de la 0, atunci imediat dup activarea ntreruperii globale prin instruciunea SEI, ntreruperea de egalitate s-ar fi declanat din cauza faptului c respectiva condiie de declanare (TCNT0 = OCR0A) ar fi fost adevrat. Pentru a evita

119

acest comportament, ncrcm n OCR0A valoare de comparat nainte de a porni ntreruperile i ateptm ca TCNT0 s ating respectiva valoare. Nu mai ne rmne altceva de fcut dect s inserm subrutina de tratare a ntreruperii. Aceasta, conform regulii de formare mai sus discutate, va avea denumirea __vector_10. n ea nu vom face dect s afim valoarea curent a lui R16. Coaserea precum i implementarea subrutinei o vedem n secvena ce urmeaz : .global __vector_10
; alte instruciuni/subrutine

__vector_10: push R17 rcall afiseaza_r16 clr R17 out TCNT0, R17 pop R17 reti Observai v rog cum, de ndat ce afim R16, tergem TCNT0. De ce facem asta? Pentru c dac nu o facem, TCNT0 va ajunge la 255 i se va reseta singur, iar perioada de declanare a ntreruperii ar fi aceeai ca o ntrerupere de depire indiferent de ce valoare am alege pentru OCR0A. Noi nu vrem asta ... Mai departe Secvena de cod principal astfel rezultat care execut automat a subrutin ce ncepe la adresa __vector_10 o dat la aproximativ 250ms n loc de 262ms, aa cum am vzut n seciunea precedent, este urmtoarea : TIMSK = 0x39 TCCR0B = 0x33 TCNT0 = 0x32 OCR0A = 0x29 ; proaspt introdus PORTB = 0x18 DDRB = 0x17 PB0 = 0x00 PB1 = 0x01 .section .text .global main .global __vector_10 main: rcall initializeaza_perif clr R16 executa_vesnic: inc R16 rjmp executa_vesnic __vector_10: push R17

120

rcall afiseaza_r16 clr R17 out TCNT0, R17 pop R17 reti initializeaza_perif: ldi R16, 0b00010000 out TIMSK, R16 ldi R16, 0b00000101 out TCCR0B, R16 ldi R16, 244 out OCR0A, R16 sei ldi R16, 0b00010011 out DDRB, R16 ret i asta este tot. La trimiterea codului pe plcu, vom vedea o mrire considerabil a vitezei de noire a LED-urilor. Chiar dac diferena este de doar 262ms250ms=12ms , cu puin antrenament, ochiul uman poate percepe aceste intervale de timp. n cazul n care nu este timp pentru antrenament, am realizat urmtoarea captur de osciloscop pentru a ne ajuta un pic :

(Canalul 1 : ceasul afiorlui, iar Canalul 2 : terminalul de date ) V rog observai cum distana dintre dou actualizri ale afiorului este de x=250ms .

121

ntrebri / Exerciii: 1. Ce valoare trebuie s fie configurat OCR0A pentru a obine o perioad de declanare a ntreruperii o dat la 100ms la un factor de 1024 ? Se poate obine aceast perioad i la un factor de 256 ? 2. Putem folosi __vector_A n loc de __vector_10 (s folosim valoarea n baza 16 a adresei relative) ? Argumentai.

[12.1s] Atenie la ntreruperi!


Au pit ceva ntreruperile ? Nu, ele nu au nimic, dar s-ar putea cpuoarele noastre s fie n pericol. De ce? ntrebai. S lum urmtoarea secven de cod : TIMSK = 0x39 TCCR0B = 0x33 TCNT0 = 0x32 PINB = 0x16 PINB2 = 0x02 OCR0A = 0x29 DDRB = 0x17 PORTB = 0x18 PB0 = 0x00 PB1 = 0x01 PB4 = 0x04 .section .text .global main .global __vector_10 main: rcall initializeaza_perif clr R16 executa_vesnic: rcall citeste_taste_r17 mov R16, R17 rjmp executa_vesnic __vector_10: push R18 rcall afiseaza_r16 clr R18 out TCNT0, R18 pop R18 reti initializeaza_perif: ldi R16, 0b00010000 out TIMSK, R16 ldi R16, 0b00000101 out TCCR0B, R16

122

ldi R16, 255 ; valoare iniial alui OCR0A poate fi orict, out OCR0A, R16 ; ea este folosit doar ca surs de ntrerupere sei ldi R16, 0b00010011 out DDRB, R16 ret n mod normal, ne-am atepta ca aplicaia noastr s citeasc mereu tastatura i s afieze ceea ce citete: butoanele care sunt apsate s se vad prin LED-urile, corespondente, aprinse, pe cnd butoanele neapsate s pstreze LED-uri respective stinse. Totui, n urma trimiterii codului spre plcu, observm un lucru ciudat : dei nu apsm niciun buton, afiorul arat altceva. Putem observa, din cnd n cnd, ca i cum unele butoane ar fi apsate! Ce se ntmpl aici ? Am greit noi funcia de citire a butoanelor ? De ce vedem acest comportament ciudat ? Stai linitii, nu am greit-o, dar nici nu am gndit-o pentru a lucra n siguran cu mecanismul de ntreruperi. S revenim la subrutina noastr de citire a tastelor : citeste_taste_r17: push R16 cbi PORTB, PB1 cbi PORTB, PB4 nop sbi PORTB, PB4 clr R17 ldi R16, 8 ciclu_citire_taste: lsl R17 sbis PINB, PINB2 ori R17, 0b00000001 cbi PORTB, PB1 nop sbi PORTB, PB1 dec R16 cpi R16, 0 brne ciclu_citire_taste pop R16 ret Problema o reprezint acel R16 folosit att n subrutina de citire a tastelor ct i ca valoarea afiat de subrutina de afiare. Ea apare atunci cnd ntreruperea (nu uitai c ceasul0 numr deodat cu execuia secvenei principale) se declaneaz ct timp instruciunile executate sunt n urmtoarea regiune :

123

ciclu_citire_taste:
; alte instruciuni din ciclu

brne ciclu_citire_taste Atunci cnd se ntmpl asta, valoarea afiat prin R16 nu este cea dorit ci este valoarea curent folosit pentru a controla ciclu_citire_taste. Asta explic de ce pe afior vedem doar valori din domeniul {8,7,6,5,4,3,2,1,0 } pentru c acestea sunt valorile pe care le are R16 ct timp execuia se afl n subrutina citeste_taste_r17. Cum rezolvm problema asta ? ntrebai. Exist o soluie clasic care o vom folosi i noi i care presupune dezactivarea tuturor ntreruperilor att timp ct ne aflm n subrutina minitastaturii i reactivarea lor imediat ce ieim din ea. Pentru asta vom folosi grupul de instruciuni CLI pentru tergere i respectiv SEI pentru reactivarea tuturor ntreruperilor. Pentru a scpa ct mai repede de acest risc, vom dezactiva ntreruperile nc din prima instruciune a subrutinei i le vom reactiva imediat nainte de a prsi subrutina. Cam n felul urmtor : citeste_taste_r17: cli push R16
; instruciuni ale subrutinei care nu vor fi ntrerupte de nimeni i nimic!

pop R16 sei ret Cu aceste modificri, dup completarea i rencrcarea codului pe plcu se va observa comportamentul cel corect ateptat. ntreruperile, dup cum am vzut, pot fi un instrument foarte puternic prin care putem crea aplicaii foarte interesante, dar aceast putere vine cu o responsabilitate : protejarea codului de ntreruperi neanunate. Acest lucru este greu de prezis pentru c oamenilor le este greu s urmreasc activiti ce se desfoar concomitent. Noi, ca i indivizi, putem urmri mult mai uor o succesiune de instruciuni.

Important : n exemplele din continuare vom folosi corecia adus la subrutina citeste_taste_r17 dac nu precizm altceva. n seciunea urmtoare vom utiliza ceea ce am nvat aici pentru a ilustra un exemplu mai drgu ce are la baz mecanismul de ntreruperii

ntrebri / Exerciii : 1. Ce credei, mai exist subrutine create de noi care pot suferi de aceeai problem ?

124

[13s] ntreruperi, din nou i din nou ...


S lum un exemplu un pic mai complicat. Plecm de la ideea c secvena de baz folosit la numrtorul ciudat prin care am introdus ntreruperea de egalitate (TCNT0 - OCR0A) : executa_vesnic: inc R16 rjmp executa_vesnic poate fi fcut un pic mai interesant. Cum? Dac tot am activat minitastatura, propun s folosim un meniu. Pentru a vedea diferenele dintre diferitele valori alese pentru OCR0A, propun urmtoarea soluie : S realizm o aplicaie bazat pe un meniu de 3 opiuni date de starea butoanelor D0, D1 i D2 prin care observm comportamentul exemplului nostru de mai sus la diferite valori ale lui OCR0A astfel : D0 apsat va seta OCR0A pe 1, D1 apsat va ncrca n OCR0A valoarea 127, iar D2 apsat va face ca OCR0A s ncarce valoarea 255 Pentru aceast exerciiu vom folosi ceasul0 cu un factor de 1024. Ei bine, aceast problem are nevoie de subrutina de citire de taste pe lng cea de afiare, dar nu i cea de ntrziere pentru c vom lucra eficient folosind ntreruperi. Fr a mai pierde timpul i pornind de la exemplul minitastaturii, avem urmtoarea secven principal conturat : main: rcall initializeaza_perif clr R16 executa_vesnic:
; == citim tastele i executm meniul ==

rcall citeste_taste_r17 sbrc R17, 0 ; D0 apsat ? : rjmp D0_apasat ; Da sbrc R17, 1 ; D1 apsat ? : rjmp D1_apasat ; Da sbrc R17, 2 ; D2 apsat ? : rjmp D2_apasat ; Da rjmp continua_executia ; dac nimic nu s-a apsat, pstrm valoarea lui OCR0A D0_apasat: ldi R17, 1 out OCR0A, R17 rjmp continua_executia D1_apasat: ldi R17, 127 out OCR0A, R17 rjmp continua_executia D2_apasat: ldi R17, 255

125

out OCR0A, R17 continua_executia: inc R16 rjmp executa_vesnic Dup ncrcarea ei pe plcu, orice apsare pe butonaele D0, D1 sau D2 va conduce la o schimbare a vitezei de afiare a LED-urilor, aa cum ne-am i dorit. Important : Programul NU va funciona corect dac subrutina citeste_taste_r17 nu a fost protejat de ntreruperi, aa cum am vzut n seciunea anterioar. Verificai!

ntrebri / Exerciii : 1. De ce, la apsarea lui D0, vedem aproape toate LED-urile pornite ? 2. n secvena de mai sus : se pot reduce numrul de instruciuni folosite fr a afecta comportamentul aplicaiei ? Dac da, cum ? 3. Mai adugai, la progrmelul de mai sus, o sarcin pentru butonul D3 : OCR0A ia valoarea 100, D4 pentru a ncrca n OCR0A valoarea 200 , D5 pentru a opri ceasul0, iar D6 pentru a-l reporni iar. Pentru D7 nu alegem nicio ntrebuinare.

[14s] Cnd una nu este suficient


tii ce este ciudat ? Dac Ale tie s gestioneze attea ntreruperi, putem s avem mai multe surse de evenimente urmrite deodat ? Dac da, apare o dilem : ce se ntmpl atunci cnd apare o ntrerupere n timpul n care creieraul se afl n subrutina de tratare a unei alte ntreruperi ? Exact acest lucru ne propunem s observm n aceast seciune. Practic, vom exemplifica o situaie n care ntreruperile pot fi i sunt, la rndul lor, ntrerupte. Pentru a face asta, avem nevoie de cel puin 2 surse de evenimente active. S spunem c alegem pentru aceast sarcin ntreruperea de echivalen TCNT0 - OCR0A precum i echivalena TCNT0 - OCR0B. Desigur c am fi putut alege ntreruperea de depire a ceasului0 i echivalena TCNT0 - OCR0A, dar alegnd echivalena TCNT0 - OCR0B n locul evenimentului de depire avem ocazia s nvm despre un nou tip de ntrerupere. Firete c ea este foarte asemntoare cu TCNT0 - OCR0A, dar i are adresa de gestionare diferit n tabelul de ntreruperi i acest lucru este suficient pentru noi. V-a putea lsa pe voi singuri s activai noua ntrerupere, i chiar v-a ncuraja s o facei dar dac nu v descurcai, precizm aici c pentru activarea ntreruperii de egalitate TCNT0 - OCR0B trebuie s setm bitul OCIE0B din TIMSK pe 1. nainte de a scrie orice bucic de cod, trebuie s fixm OCR0B pentru aplicaia noastr. Cunoscndu-i adresa (0x0028), aceast sarcin devine una uoar : OCR0B = 0x28 Evident, primul i primul lucru ce-l vom face va fi s completm subrutina de iniializare. Vom face acest lucru astfel :

126

initializeaza_perif: ldi R16, 0b00011000 ; activm ntreruperile de echivalen out TIMSK, R16 ; TCNT0 - OCR0A i TCNT0 - OCR0B ldi R16, 8 ; OCR0A va avea o valoare mai mic dect OCR0B ceea ce nseamn c out OCR0A, R16 ; ntreruperea sa de echivalen sa se va declana prima ldi R16, 16 ; apoi va ncepe ntreruperea TCNT0 - OCR0B out OCR0B, R16 ldi R16, 0b00000010 ; pornim ceasul0 cu un factor de 8 out TCCR0B, R16 sei ldi R16, 0b00000011 ; afior pornit, minitastatur oprit out DDRB, R16 ret Ceea ce este diferit la aceast iniializare fa de celelalte n care am folosit ceasul0 este factorul de 8 ales spre deosebire de tradiionalul 1024. S nu uitm : am ales un factor mic pentru a realiza incrementri mai rapide ale ceaului0. Cu ct factorul este mai mic, cu att mai rapid se incrementeaz TCNT0 i cu att mai multe ntreruperi de chivalen avem ntr-o secund. ntreruperea de egalitate TCNT0 - OCR0B este situat la adresa relativ 0x000B (11, n baza zece) n tabelul de ntreruperi prin urmare va avea urmtoarea etichet la subrutina de tratare : __vector_11. Cu acestea fiind spuse, s vedem n ce va consta experimentul : Vom avea o secven principal i 2 subrutine de ntreruperi. Ne propunem ca secvena principal s conin apelul de afiare pe cnd cele 2 ntreruperi nu vor face altceva dect s ncarce n R16 o secven unic de bii prin care s recunoatem execuia subrutinei atunci cnd ea este afiat din secvena principal. S spunem c valorile unice de afiat sunt urmtoarele : main), OCR0A i pentru subrutina ntreruperii TCNT0 OCR0B. pentru subrutina ce rspunde la evenimentul TCNT0 pentru secvena principal (ce pornete de la eticheta

Haidei s urmrim codul prin care facem ce ne propunem : TIMSK = 0x39 TIFR = 0x38 TCCR0B = 0x33 TCNT0 = 0x32 DDRB = 0x17 OCR0B = 0x28 OCR0A = 0x29 PORTB = 0x18 PB0 = 0x00

127

PB1

= 0x01

.section .text .global main .global __vector_10 ; subrutina de tratare a ntreruperii de egalitate TCNT0 - OCR0A .global __vector_11 ; subrutina de gestionare a evenimentului TCNT0 - OCR0B main: rcall initializeaza_perif executa_vesnic: ldi R16, 0b00001111 ; ncrcm secvena prin care recunoatem c s-a executat secvena principal rcall afiseaza_r16 rcall intarzie_un_pic rjmp executa_vesnic __vector_10: ldi R16, 0b00111100 ; secvena prin care identificm execuia subrutinei TCNT0 - OCR0A reti __vector_11: ldi R16, 0b11110000 ; amprenta subrutinei de gestionare a evenimentului TCNT0 - OCR0B reti initializeaza_perif: ldi R16, 0b00011000 out TIMSK, R16 ldi R16, 8 out OCR0A, R16 ldi R16, 16 out OCR0B, R16 ldi R16, 0b00000010 out TCCR0B, R16 sei ldi R16, 0b00000011 out DDRB, R16 ret Observai v rog c am folosit vechea noastr subrutin de ntrziere. Evident, acest lucru lam fcut din motive de afiare corect : dorim ca ceea ce afim s rmn pe LED-uri suficient ct s fie observat uor de ctre ochiul nostru uman. ncrcm codul pe plcu i ce vedem ? n primul i primul rnd observm c ntreruperile funcioneaz : Din cnd n cnd afiorul i actualizeaz starea cu valori unice ce sunt ncrcate din cele 2 subrutine, dar de cele mai multe ori, valoarea afiat este cea dat de secvena principal. Este oarecum firesc s se ntmple aa dac ne gndim c pentru a se modifica valoarea afiat ntreruperea trebuie s se declaneze ntre aceste 2 instruciuni : ldi R16, 0b00001111 rcall afiseaza_r16

128

ori acest lucru este destul de dificil, dar nu imposibil altfel nu s-ar fi afiat dect secvena ncrcat n codul principal. Uneori se ntmpl ca secvena ce apare pe afior s fie o valoare total neprevzut. Valorile afiate care provin de nicieri sunt datorate faptului c subrutina afiseaza_r16 nu a fost protejat mpotriva ntreruperii aa cum am protejat citeste_taste_r17, de pild. n tot cazul, punctul de vedere a fost atins : pot exista 2 sau mai multe ntreruperi active simultan pe creiera. Problema nu este declanarea lor ci, mai degrab, coordonarea lor i urmrirea evoluiei lor. O aplicaie cu mai multe ntreruperi active devine foarte greu de urmrit i neles, dar, evident, nu i imposibil. Seciunea urmtoare va duce ceasul0 la un alt nivel de timp. n mod principal, ea va rspunde la ntrebarea : i ce facem dac dorim s declanm ntreruperi la nivel de secunde i nu la intervale de milisecunde aa cum am discutat pn acum ?

ntrebri / Exerciii : 1. Alegei alte valori de start pentru OCR0A, OCR0B i factorul ceasului0. Ce observai ? Cum este influenat secvena afiat n funcie de aceste valori de pornire ? 2. Rescriei exemplul de mai sus n care s avei activat i ntreruperea de depire a ceasului0 (2550) n care s mutai codul din seciunea principal n subrutina de tratare a evenimentului de depsire. Secvena principal va rmne goal, doar cu ciclul infinit : main: rcall initializeaza_perif executa_vesnic: rjmp executa_vesnic Putem s eliminm apelul la subrutina de ntrziere n acest caz? Argumentai. 3. Protejai subrutina afiseaza_r16 mpotriva ntreruperilor i re-ncrcai aplicaia pe plcu. Ce observai ? Cum influeneaz asta comportamentul afiorului ?

[15s] Cnd milisecundele nu sunt suficiente


ce facem? S zicem c avem o aciune ce trebuie s o realizm din secund n secund. O astfel de aciune ar putea fi citirea temperaturii sau a luminii din exterior (vom reveni la aceste exemple). Pentru aceste activiti, nu avem nevoie de multe citiri pe secund pentru c, n general, parametrii lor (temperatura, intensitatea luminoas, etc.) se modific foarte lent n timp. Din acest motiv, o verificare mai rar este suficient. O variant ar fi s folosim o variabil de control i ntreruperi de echivalen care s se declaneze o dat la 250ms . Variabila de control (care este un registru normal), s-ar incrementa o dat pe eveniment ceea ce ar nsemna c la 4 incrementri, avem certitudinea c a trecut o secund i c putem s executm secvena respectiv. Nu vom discuta o implicare real a acestei soluii ci, mai degrab, una la nivel de nelegere. O astfel de soluie ar putea urmri secvena urmtoare de aciuni :

129

1. Iniializm o ntrerupere de echivalen care va avea o perioad de declanare de 250ms 2. n secvena principal : resetm registrul de control. S spunem c alegem R18 pentru aceast sarcin 3. n subrutina de gestionare a ntreruperii de echivalen : incrementeaz R18 4. n secvena principal : Ct timp R18 nu este egal cu 4 (nu a trecut 4250ms=1000ms sau 1s ) rmnem la punctul 3 5. n codul principal : Ajungnd aici, avem garania c a trecut secunda dorit, facem aciunile urmrite, resetm R18 i srim la punctul 4 pentru a atepta scurgerea urmtoarei secunde Am putea proceda n felul acesta i chiar ar merge. n modul acesta am putea chiar obine ntrzieri muuult mai mari, poate de ordinul zecilor de secunde i chiar minute/ore dac am folosi registrele duble X/Y/Z pe post de numrtoare. Totui, noi ncercm s gsim soluia cea mai elegant cu cel mai puin cod i ct mai eficient din punct de vedere al instruciunilor folosite. Ceasul1 (cellalt ceas prezent n creiera), dup cum vom vedea, are capacitatea de a atinge aceti timpi uor printr-o capacitate extins a factorilor folosii, dar de acest modul ne vom ocupa un pic mai n colo, dup ce mai nvm nite lucruri. n aceast seciune, noi vrem s utilizm ceea ce cunoatem deja : ceasul0. Se pare c exist o soluie. Exist o posibilitate de a ntrzia unitatea de timp de baz a creieraului. Noi am putut obine acelai efect de ntrziere folosind un factor de execuie ridicat (1024, care era maxim) pentru ceasul0 ceea ce ne-a permis o perioad de aproximativ 262ms ntre momentele de declanare a evenimentelor. S nu uitm c n calculul acestei perioade am folosit o baz de timp de

1 =1 s . Totui, prin 1000000

modificarea unitii de timp de baz are de suferit ntreg creieraul (i viteza de execuie a instruciunilor, i modulele sale interne, tot!) pe cnd factorul ceasului0 influeneaz numai modulul respectiv i doar att. Cu toate acestea, dac putem modifica acea baz de timp mrind-o atunci am putea crea i perioade mai mari ntre evenimentele de depire. Un alt avantaj al acestei metode ar fi obinerea unui consum mai redus de energie din partea creieraului(vom mai discuta noi despre asta). Ideea este c acest lucru este posibil! Exist un registru n creiera numit CLKPR1 prin care putem modifica aceast baz de timp. CLKPR este situat la adresa 0x0026 n spaiul regitrilor de control (0x0026 + 0x0020 = 0x0046 n spaiul real de memorie), iar biii si au urmtoare semnificaie : Rang Notaie Op. permise Val. iniial
1

CLKPCE

---

---

---

CLKPS3

CLKPS2

CLKPS1

CLKPS0

S/C 0

C 0

C 0

C 0

S/C 0

S/C 0

S/C 1

S/C 1

provine din englezescul Clock Prescale Register i are traducere aproximativ n romn : Registrul de diminuare a bazei de timp principale

130

Unde literele de la notaie au urmtoarele semnificaii : Denumire CLKPCE Nume complet Activarea modificrii registrului Nici una Factorul de modificare a bazei de timp principale Semnificaie Scrierea unui 1 logic pe aceast poziie confer posibilitatea modificrii bazei de timp ce ajunge la ceasul0. Nu are nicio importan pentru creiera i, la citire, mereu va avea valorea 0. Baza de timp rezultat va fi baza de timp principal mprit la valoarea logic dat de aceast secven de bii.
CLKPS3 CLKPS2 CLKPS1 CLKPS0 Factor de mprire

--CLKPS3 CLKPS0

0 0 0 0 0 0 0 0 1

0 0 0 0 1 1 1 1 0

0 0 1 1 0 0 1 1 0

0 1 0 1 0 1 0 1 0

1 2 4 8 16 32 64 128 256

[Orice alt combinaie nu are niciun efect.] Aa cum o gsim n cutie, plcua pornete de la un factor de mprire de 8. Acum, creieraul funcioneaz cu un factor de mprire de 8 ceea ce ne conduce la o baz de timp de 1 s . Dac respectivul factor ar fi 1, atunci creieraul ar executa de 8 ori mai multe instruciuni n acelai interval de timp. Am avea astfel o baz de timp de

1 s=0.125 s=125ns i asta ne-ar conduce la o perioad maximal de declanare a 8 262 ms=32.75ms . Aceast valoare nu ne convine ntreriperii de depire de aproximativ 8 pentru c ntrzierea astfel obinut ar fi chiar mai mic dect cea iniial de 262ms . 256 =32 de ori mai 8 mare dect cel curent de 8, atunci am avea o baz de timp de 1 s32=32 s ceea ce, la
Pe de alt parte, dac am mri factorul de mprire la 256, adic de un factor de 1024 ales pentru ceasul0, ar face ca ntreruperea de depire s se declaneze o dat la 262ms32=8384ms=8.384s ! Perfect!

131

Ca i regul general de calcul a acestor timpi, tot ce e mai mic dect factorul iniial 8 duce la o micorare a bazei de timp dup relaia : baz de timp=

1 s . Un factor de mprire factor de mprire s . 8

factor de mprire mai mare dect cel iniial prezent pe o plcu nou, pe de alt parte, mrete baza de timp conform formulei : baz de timp=1

Cu alte cuvinte, un factor de mprire de 256 ne poate acorda o generare de ntrerupere de depire la fiecare 8.384s . Desigur c pentru a obine o declanarea la secund noi vom fragmenta aceast perioad folosind evenimente de echivalen. Pentru aceasta, trebuie s alegem o valoare pentru OCR0A, de pild, care ne va permite acest lucru. Facem nite calcule pentru o baz de timp de 32 s . Asta, printr-un factor de modul de 1024 va conduce la o incrementare a luit TCNT0 la fiecare 32 s1024=32768 s=32.768ms . n concluzie, o secund va fi atins dup

1000 ms=30.517 incrementri ale lui TCNT0. Cu 32.768

riscul de a pierde din precizie (nu putem ncrca n OCR0A o valoare zecimal), vom considera c 31 este o valoare suficient de bun pentru registrul OCR0A. Dac stocm n OCR0A aceast valoare, n condiiile de mai sus, vom obine o declanare a ntreruperii de echivalen TCNT0 - OCR0A la fiecare 1.015 secunde ceea ce este n regul ... Dar tii ce ? nainte de a scrie ceva cod, haidei s definim o problem prin care putem vedea diferitele valori ale lui CLKPR n aciune. Haidei s implementm un meniu cu 3 opiuni : D0 va selecta un factor de mprire de 1 (de 8 ori mai rapid dect unitatea de timp de baz), D1 va alege un factor de mprire de 8 (cea iniial, creieraul comportndu-se normal), iar prin apsarea lui D2 vom alege cel mai mare factor de mprire : 256 ceea ce va avea ca i consecin executarea de 32 de ori mai lent a codului/modulelor interne Vom folosi ceasul0 cu un factor de 1024 i o ntrerupere de echivalen TCNT0 - OCR0A cu 31, valoarea lui OCR0A. Aplicaia principal va numra continuu folosind registrul R16, iar subrutina de gestionare a ntreruperii va afia valoarea curent a respectivului registru. Dac totul decurge conform celor nvate, apsarea lui D0 va face ca afiorul s se actualizeze repede pe cnd D2, va folosi secunda calculat de noi ca perioad de actualizare. D1 va reseta viteza de afiare la cea original. nainte de a scrie soluia, mai este un ultim aspect ce trebuie s-l clarificm : modalitatea prin care putem selecta un alt factor de mprire pentru Attiny. Din cauza faptului c o modificare a acestui element are implicaii asupra ntregului creiera, msuri speciale de sigurant s-au luat pentru a ne asigura c o modificare are loc doar atunci cnd o vrem i nu n mod accidental. Din acest motiv, cei ce au construit creieraul descriu urmtoarea secven de pai ce trebuie realizai pentru a modifica acest registru : 1. Scrierea n CLKPR a octetului 0b10000000 (CLKPCE ia valoarea 1) i apoi 2. n pasul imediat urmtor se scrie n CLKPR factorul dorit cu CLKPCE pus pe 0. Asta nseamn c octetul respectiv va avea urmtoarea structur : 0b0000aaaa unde aaaa sunt valorile biilor CLKPS3 CLKPS0.

132

iii .. un pic de cod! Fixm mai nti noul registru : CLKPR = 0x26 i ncepem cu vechea noastr subrutin de iniializare a perifericelor : initializeaza_perif: ldi R16, 0b00010000 ; activm ntreruperea de egalitate TCNT0 - OCR0A out TIMSK, R16 ldi R16, 31 ; valoarea 31 a fost aleas pentru OCR0A ca la un factor de mprire de 256, out OCR0A, R16 ; s obinem o perioad de generare a ntreruperii de aproximativ 1 secund ldi R16, 0b00000101 ; alegem un factor de 1024 i pornim ceasul0 out TCCR0B, R16 sei ldi R16, 0b00010011 ; afior i minitastatur pornite out DDRB, R16 ret Dup iniializare prezentm subrutina de tratare a ntreruperii : .global __vector_10
; alte intrusciuni

__vector_10: push R17 rcall afiseaza_r16 clr R17 ; resetm numrtorul ceasului0 pentru a pstra aceai perioad de generare out TCNT0, R17 ; a ntreruperii curente pop R17 reti n afar de resetarea lui TCNT0, nu avem nimic special n aceast subrutin. Dac nu resetm registrul de numrare, ceasul0 va continua cu 31, 32, 33, , 255, 0, 1, 2, 29, 30, 31, 32. Ceea ce nseamn alte 256 de valori pn se redeclaneaz. Noi vrem mereu ca la 31 de uniti s se execute respectiva subrutin. Prin urmare resetm numrarea nainte s prsim secvena de cod a subrutinei. Ultima, dar nu cea mai puin important, bucat de cod este secvena prin care se leag aplicaia noastr : secvena principal. main: rcall initializeaza_perif clr R16 executa_vesnic:
; == regiunea meniului ==

rcall citeste_taste_r17 sbrc R17, 0

133

rjmp D0_apasat sbrc R17, 1 rjmp D1_apasat sbrc R17, 2 rjmp D2_apasat rjmp incrementeaza_r16 ; nu recunosc nimic de pe tastatur aa c sari la incrementarea lui R16 D0_apasat: ldi R17, 0b10000000 out CLKPR, R17 ldi R17, 0b00000000 ; alegem un factor de mprire de 1 out CLKPR, R17 rjmp incrementeaza_r16 D1_apasat: ldi R17, 0b10000000 out CLKPR, R17 ldi R17, 0b00000011 ; resetm factorul de mprire la valoarea sa original de 8 out CLKPR, R17 rjmp incrementeaza_r16 D2_apasat: ldi R17, 0b10000000 out CLKPR, R17 ldi R17, 0b00001000 ; mrim baza de timp de 32 de ori fa de valoarea iniial prin out CLKPR, R17 ; alegerea unui factor de mprire de 256 (cel mai mare posibil) incrementeaza_r16: inc R16 rjmp executa_vesnic Scriem, trimitem pe plcu i ce observm ? D0/D1/D2 modific viteza de afiare a valorilor pe LED-uri aa cum am discutat. Urmtoarele capturi de osciloscop ce suprind activitatea subrutinei afiseaza_r16 demonstreaz acest comportament. Toate imaginile au fost realizate avnd canalul 1 conectat la terminalul de ceas i canalul 2 la cel de date. Pentru D0 apsat ( x=110 s :8=13.75 s , valoarea calculat ):

Pentru D1 apsat ( x=110 s , valoarea msurat la exemplul '4s' ):

134

Pentru D2 apsat ( x=110 s32=3520 s=3.52ms , valoarea calculat ):

O ultim precizare la aceste capturi : valoarea de referin a fost un timp de baz normal de execuie a lui afiseaza_r16, timp ce l-am mai vzut i-n exemplul 4s. La fiecare imagine avei i valoarea teoretic calculat pentru a o compara cu cea surprins de osciloscop. n aceast seciune am vzut cum putem mri baza de timp pentru a realiza aciuni periodice la distane mai mari n timp folosind factorul de mprire al Attiny-ului. Desigur c putem pune n subrutina de gestionare a ntreruperii orice aciuni dorim, dar folosirea unui factor de mprire nu vine fr consecine : datorit faptului c baza de timp rezultat ajunge peste tot n creiera, viteza de execuie a instruciunilor este i ea afectat. Ca i regul general : o frecven redus nseamn, aa cum spuneam mai sus, un consum redus de energie, dar i performane reduse. n continuare vom vorbi despre o soluie ce vine din partea altui modul intern al creieraului. O soluie prin care aceste pierderi de performane sunt evitate. Este vorba despre ceasul1.

ntrebri / Exerciii : 1. Putem obine o generare de ntrerupere la 5 secunde folosind un factor de ceas de 512 i un factor de mprire de 128 ? Dac da, ce valoare ar trebui s alegem pentru OCR0A pentru a genera aceste perioade ? Dac nu, care este perioada maxim ce se poate obine n aceste condiii (pentru ntreruperea de depire) ? 2. Modificai exemplul de mai sus, n orice mod credei voi de cuviin, pentru a genera o ntrerupere de echivalen o dat la aproximativ 4 secunde.

135

[16s] Un ceas mai capabil


Dei nu am epuizat subiectul ceasul0, s considerm, pentru moment, c am discutat suficient despre el sau cel puin att ct a putut Ale s ne arate i practic. Mai exist cteva funcionaliti ale sale, dar ele sunt destul de avansate i putem tri, deocamdat, fr ele. n aceast seciune introducem, din dorina de a nu penaliza viteza de execuie a creieraului atunci cnd dorim perioade mai mari la generarea de ntreruperi, un alt modul intern al creieraului. Este vorba de cellalt ceas intern, notat aici ceasul1. Ceasul1 are o mulime de caracteristici comune cu ceasul0, cel studiat de noi pn acum. Dintre acestea, amintim : 8 bii pentru a ine valoarea numrat (acel TCNT0), capacitatea de a se configura cu diferii factori de timpi i posibilitatea de a genera ntreruperi (3 surse : una de depire a valorii maxime i dou de echivalen). Cu toate acestea, exist i caracteristici noi pe care le aduce noul modul n peisaj : vine cu 4 factori noi ce extind local baza de timp : 2048, 4096, 8192 i 16384, are un al 3-lea registru de echivalen care nu poate fi folosit pentru a genera o ntrerupere, dar prezint alte funcionaliti interesante i dispune de posibilitatea de a alege ntre 2 baze de timp : a. una a sistemului asemeni ceasul0-ului b. una de foarte mare precizie (64 sau 32 de Mhz), independent de cea a sistemului Ca i baz de timp, noi vom folosi doar cea a sistemului, cealalt fiind utilizat n aplicaii care cer un grad ridicat de precizie. Dintre toate aceste caracteristici noi, una pare deosebit de util pentru aplicaia noastr : cei 4 factori noi. Dac ceasul0 se oprea la un factor de 1024 ceea ce ne ddea o perioad maxim de aproximativ 262ms , ceasul1 are un factor de 4096, de exemplu prin care vom obine o perioad maxim de repetare a sursei de ntreruperi de aproximativ

262ms

4096 =262ms4=1048ms=1.048s . 1024

Foarte frumos! Putem, aadar, s generm o ntrerupere la fiecare 1 secund folosind evenimente de echivalen fr s ne atingem de factorul de mprire. Asta nseamn c viteza de execuie a aplicaiei nu va avea de suferit. Minunat! Pare promitor, dar nainte de a trece la sevena de cod prin care putem s facem acest lucru, s discutm un pic despre regitrii de control ai ceasului1. i vom introduce pe cei de care vom avea nevoie pentru aplicaia noastr aici i-i vom prezenta fcnd legtur cu cei ai ceasului0. TCCR11 este primul i are aceeai funcionalitate ca i TCCR0B din ceasul0 : este folosit pentru iniializarea i pornirea ceasului1.

n englez are denumirea complet de Timer/Counter1 Control Register, iar n romn nseamn Registru de control al ceasului1

136

TCCR1 este plasat la adresa 0x0030 n spaiul regitrilor de control, iar biii si au urmtoare importan pentru creiera : Rang Notaie Op. permise Val. iniial
7 6 5 4 3 2 1 0

CTC1

PWM1A

COM1A1

COM1A0

CS13

CS12

CS11

CS10

S/C 0

S/C 0

S/C 0

S/C 0

S/C 0

S/C 0

S/C 0

S/C 0

Unde literele de la notaie au urmtoarele semnificaii : Denumire CTC1 Nume complet Reseteaz numrtorul la echivalena OCR1C Semnificaie Prezena unui 1 logic pe aceast poziie va duce la resetarea numrtorului curent atunci cnd valoarea sa este egal cu cea prezent n registrul OCR1C. Un 0 logic aflat pe aceast poziie dezactiveaz aceast capacitate. O funcionalitate mai complex i special a modulului ce nu o vom aborda n aceast crulie. Idem : Funcionalitatea controlat de aceti bii este una complex, neabordat n crulia de fa. Acest grup de bii aleg factorul ceasului1. Valorile posibile se pot urmri din tabelul urmtor : CS13 0 0 0 0 0 0 0 0 1 1 1 1 1 CS12 0 0 0 0 1 1 1 1 0 0 0 0 1 CS11 0 0 1 1 0 0 1 1 0 0 1 1 0 CS10 0 1 0 1 0 1 0 1 0 1 0 1 0 Factor
Modul inactiv

PWM1A

Activarea modulrii n pulsaie A Manifestare a comparatorului la atingerea valorii OCR1A Controleaz factorul modulului

COM1A1, COM1A0 CS13 CS10

1 2 4 8 16 32 64 128 256 512 1024 2048

137

CS13 1 1 1

CS12 1 1 1

CS11 0 1 1

CS10 1 0 1

Factor 4096 8192 16384

TCNT1 are aceeai interpretare precum TCNT0 (chiar i n denumire) i reprezint registrul valorii ceasului1. Din cauza simplitii sale, nu-i vom acorda o descriere detaliat a structurii sale, n afara precizrii faptului c adresa sa relativ n tabela regitrilor de control este 0x002F. Un alt grup de registre simplue din punct de vedere structural sunt registrele de egalitate OCR1A, OCR1B sau chiar al 3-lea registru de comparaie : OCR1C. Biii lor nu au nicio semnificaie pe cont propriu, iar forma lor o urmrete pe cea a regitrilor de comparaie prezente n ceasul0 : OCR0A i OCR0B. Ca i adrese, aflm urmtoarele valori : OCR1A are adresa 0x002E, OCR1B este plasat la adresa 0x002B, iar OCR1C se gsete la adresa 0x002D. n continuare, pentru c vom lucra cu ntreruperi, va trebui s le activm n faza de iniializare a perifericelor. Pentru asta, vom folosi biii OCIE1A (index 6), OCIE1B (pe poziia 5) sau TOIE1 (situat pe poziia 2) din registrul TIMSK, registru ce l-am cunoscut deja atunci cnd am discutat despre ceasul0. i pentru ca peisajul s fie complet, precizm adresele de gestionare a ntreruperilor din tabela de ntreruperi : potrivirea cu registrul OCR1A are adresa relativ 0x0003 (3, n baza zece), echivalarea cu registrul OCR1B ne trimite execuia la adresa relativ 0x0009 (n baza zece : 9), iar depirea de ctre TCNT1 a valorii maxime are adresa de salt 0x0004 (4, pentru a putea fi folosit la creearea etichetei subrutinei de gestionare) i cam asta a fost tot n materie de control. Vi s-a prut greu? n afar de acele cteva puncte de nouti, ceasul1 se controleaz i se comport identic precum ceasul0 lucru ce ne-a permis s trecem aa de rapid prin aceti regitri, de altfel, foarte importani. S integrm toi aceti regitri n aplicaia noastr mai nti denumindu-i : TCCR1 = 0x30 TCNT1 = 0x2F OCR1A = 0x2E OCR1B = 0x2B OCR1C = 0x2D i apoi, s ne reamintim ce urmrim : vrem s scriem o aplicaie n care s generm o ntrerupere cu o perioad de aproximativ 1 secund folosind ceasul1. Toate aceste lucruri le vom face fr a ne atinge de factorul de mprire.

138

Am vzut cum un factor de 4096 ne poate ajuta n acest scop. Pentru asta vom folosi ntreruperea de echivalen TCNT1 - OCR1A. Asta nseamn c va trebui s alegem o valoare pentru registrul OCR1A. Aceast valoare o putem afla dup urmtoarea formul :

perioada dorit n secunde . Prin urmare, baza de timp folosit n secundefactor ales pentrumodul 1 OCR1A= =244.14 . Rotunjim i alegem pentru OCR1A valoarea 244. 0.0000014096 OCR1A=
Fr prea mult vorbrie, introducem noua secven de iniializare a perifericilor : initializeaza_perif: ldi R16, 0b01000000 ; activm ntreruperea de echivalen TCNT1 - OCR1A out TIMSK, R16 ldi R16, 244 ; ncrcm valoarea de comparat prin care obinem o perioad de generare a out OCR1A, R16 ; evenimentului de echivalen o dat pe secund la 1 Mhz ldi R16, 0b00001101 ; pornim ceasul1 cu un factor de 4096 out TCCR1, R16 sei ; activm ntreruperile globale ldi R16, 0b00000011 ; afior pornit, minitastatur oprit out DDRB, R16 ret Odat iniializat modulul, restul de subrutine se construiesc, firesc, uor. Continum cu subrutina de tratare a ntreruperii : .global __vector_3
; ... eventual alte instruciuni/subrutine

__vector_3: push R17 rcall afiseaza_r16 clr R17 out TCNT1, R17 pop R17 reti Observai v rog cum folosim acelai mecanism de resetare pentru a respecta perioadele de timp dorite. Pentru a lega toate aceste elemente, mai rmne s prezentm secvena principal de instruciuni : main: rcall initializeaza_perif clr R16 executa_vesnic:

139

inc R16 rjmp executa_vesnic Ea este aceeai simpl bucat de cod prin care nu facem nimic altceva dect s iniializm modulele periferice i apoi s increment continuu valoarea ce o vom afia. Aceste buci de cod ntr-adevr sunt tot ce ne trebuie pentru a realiza un lucru pe care ceasul0 nu l-a putut realiza de unul singur i anume : obinerea unor perioade mai extinse de timp. ntocmai ce ne-am propus! Putem lsa soluia aa sau putem continua s ne folosim de capcitile ceasului1 i s o mbuntim. Ghicii ce vom face mai departe ? Exact : o vom mbunti! Dac privim explicaiile bitului CTC1 din registrul TCCR1, observm ceva util : se poate reseta automat valoarea lui TCNT1 atunci cnd valoarea sa ajunge s fie egal cu cea a registrului OCR1C. n felul acesta, folosind ce-l de-al doilea punct al listei de faciliti noi ale ceasului1, putem s reducem codul din subrutina de tratare a ntreruperii de egalitate la : __vector_3: push R17 rcall afiseaza_r16 clr R17 out TCNT0, R17 pop R17 reti Asta nseamn o singur instruciune : apelarea subrutinei de afiare. Resetarea se va face acum n mod automat. Cum facem asta, ntrebai ? Pe lng instruciunile eliminate din subrutin, va trebui s lucrm i la subrutina de iniialiare. Noi dorim ca TCNT1 s se reseteze imediat dup gestionarea ntreruperii deci imediat dup ce TCNT1 atinge valoarea lui OCR1A (registrul folosit pentru generarea ntreruperii). Pentru asta va trebui s ncrcm n OCR1C aceeai valoare ce o avem n OCR1A adic, n cazul nostru, 244. Era mai uor dac OCR1C putea genera de unul singur ntrerupere. n felul acesta nu am mai fi avut nevoie de OCR1A, dar nu este nicio problem, ne descurcm noi i fr! Cu noile modificri, subrutina de iniializare a modulelor devine : initializeaza_perif: ldi R16, 0b01000000 out TIMSK, R16 ldi R16, 244 out OCR1A, R16 ldi R16, 244 ; din motivele discutate, OCR1C va avea aceeai valoarea precum OCR1A out OCR1C, R16 ldi R16, 0b10001101 ; pe lng ceas1 (pornit cu un factor de 4096), activm i capacitatea out TCCR1, R16 ; de autoresetare a lui TCNT1 cnd valoarea aceasta atinge cea stocat n OCR1C

140

sei ldi R16, 0b00000011 out DDRB, R16 ret Ctigul ? ntrebai. Ei bine, pe lng faptul c am scpat de 4 instruciuni cu preul adugrii a nc dou rezultnd ntr-o economie de 2 instruciuni, am aerisit subrutina de gestionare a ntreruperii folosind, ntr-un mod eficient, capacitile creieraului. Cum exist mai multe moduri de a rezolva o problem, adevrata plcere vine din cutarea unei soluii elegante, plcute ochilor, prin care suntem mulumii de noi. Acesta ar trebui s fie spiritul n care abordm o problem ... ncheiem aceast seciune cu urmtoarea precizare : Dei ceasul1 vine cu nite noiuni mai sofisticate, n final, el are acelai comportament ca i ceasul0. Cu alte cuvinte : tot ce funcioneaz folosind ceasul0, va funciona i utiliznd ceasul1, dar nu i invers. n aceast seciune am putut urmri capacitile unui alt modul aflat pe Attiny. n continuare, ce zicei s combinm cele 2 ceasuri ntr-un exemplu care pclete logica ? Nu m credei ? Haidei s vedem ...

ntrebri / Exerciii : 1. Care este perioada de timp maxim ce se poate obine folosind ceasul1 fr a ne atinge de factorul de mprire a sistemului ? Vom pleca de la o baz de timp standard de 1 s . 2. Reconstruii aplicaia de mai sus pentru a folosi o perioad de 2.5 secunde pentru afiare.

[17s] mpreun facem lucruri frumoase


Noi suntem obinuii s credem c lumea digital, din care face parte i plcua, nu poate oferi dect surprize n 1 i 0. C totul are 2 valori : ori este adevrat, ori este fals, fie este aprins, fie este stins i tot aa. C nu exist nuane de gri. Dar dac am demonstra contrariul ? Dac, folosind valori binare, am reui s pclim creierul nostru n a percepe o valoare continu ? Dac, folosind LED-urile, am putea crea senzaia c ele lumineaz lin, cu diferite grade de vizibilitate, de la nchis la complet deschis + toate valorile dintre ? Se poate, iar n aceast seciune vom vedea cum. Tot ce va urma se va cldi pe o proprietate a ochiului uman de a fi pclit de imagini n micare. Pe acest principiu este construit i televizorul : o succesiune de 23 de imagini, de regul, care difer foarte puin ntre ele i care se deruleaz una dup alta pe o perioad de o secund. Creierul este pclit s cread c de fapt el vede micare cnd, n realitate, adevrul este cu totul altul.

141

S revenim i s vedem ce ne propunem s facem aici : dorim s scriem o bucat de cod care s ne pcleasc ochii n a crede c intensitatea afiorului se poate modifica direct din aplicaie. S ncercm s ne imaginm cum am putea transpune efectul imaginilor mictoare n intensitate luminoas. Un pas esenial n a vedea o soluie l reprezint exemplul discutat la factorul de mprire (cu registrul CLKPR). Mai inei minte ? D0 apsat realiza o actualizare rapid a afiorului unde, puteam observa noi, se ntmpla ceva interesant : existau regiuni ale afiorului care se actualizau cu 1 i 0 mai repede dect altele. Realizat la o vitez foarte mare, acest observaie ddea impresia c unele regiuni sunt mai aprinse dect altele. Super! Aadar putem controla luminozitatea prin alternri rapide de tip nchis/deschis a afiorului. Imaginea urmtoare ajut s nelegem mai bine conceptul :

Din desenul acesta rezult c va trebui s respectm o serie de relaii matematice : timp pornit +timp oprit=constant . Unde constant va fi, aa cum i spune i numele, o valoare fix dup care ntreg ciclul se repet si

timp pornit , o expresie un pic mai complicat, va dicta luminozitatea timp pornit +timp oprit
afiorului. Avnd n vedere c valoarea maxim a fraciei este 1 (atunci cnd timp oprit=0 ), majoritatea valorilor sunt ntre 0 (cnd timp pornit=0 ) i 1. Pentru a uura exprimarea spunem c atunci cnd acest raport are valoarea 0.93, de exemplu, el se traduce prin 93% din timp LED-ul este pornit sau luminozitatea LED-ului este de 93%.

142

Astfel, pentru a obine mai multe nivele de luminozitate, trebuie s alegem o constant pentru prima relaie i s ajustm timp pornit din relaia a 2-a. Noi ne vom juca cu aceste valori i le vom genera automat din aplicaia noastr. Pentru asta vom avea nevoie de ambele ceasuri : Un ceas, ceasul1, va fi rspunztor pentru modificarea lui timp pornit i Cellalt ceas, ceasul0, va fi rspunztor pentru generarea graficului din imaginea de mai sus astfel nct s obinem intensitatea dorit. Abordarea noastr va fi una simpl : vom considera constanta ca fiind valoarea 100 (pentru c este un numr rotund), iar la fiecare generare a ntreruperii ceasului1, timp pornit va crete cu cte 5. Pentru a respecta prima relaie, timp pornit se va reseta dup ce a atins valoarea maxim dat de constant. Pe de alt parte, ceasul0, care va avea o vitez de declanare mult mai mare dect a ceasului1, va urma graficul descris mai sus mprind constanta n 100 de pai pe care-i aloc strilor de oprit/pornit dup valoarea curent a lui timp pornit . Practic, la nceputul celor 100 de declanri, subrutina aprinde afiorul timp de timp pornit gestionri i l las stins timp de constanttimp pornit executri dup care ciclul se repet. i aa se vor desfura lucrurile n aplicaia noastr : afiorul va fi o perioad de timp pornit, iar restul de timp oprit. Obinerea diferitelor intensiti se poate realiza prin simpla modificare a perioadei n care LED-urile sunt pornite. Fr a aduga alte detalii, ncepem codul nostru cu subrutina de iniializare a modulelor : initializeaza_perif: ldi R16, 0b01000010 ; activm ntreruperea de depire a ceasului0 i out TIMSK, R16 ; ntreruperea de echivalen TCNT1 - OCR1A a ceasului 1 ldi R16, 0b00000001 ; pornim ceasul0 cu un factor de 1 i ntrerupere la depire out TCCR0B, R16 ldi R16, 30 ; iniializm ceasul1 cu un factor de 4096 i out OCR1A, R16 ; generarea de ntreruperi de echivalene TCNT1 - OCR1A la fiecare aproximativ
;

1 s409630=122880 s

sau

0.12 secunde

ldi R16, 30 out OCR1C, R16 ldi R16, 0b10001101 out TCCR1, R16 sei ldi R16, 0b00000011 ; afior pornit, minitastatur oprit out DDRB, R16 ret n continuare, prezentm subrutina ceasului1 n care modificm perioada de timp n care LED-urile sunt pornite. Aceast valoare este pstrat n registrul R17.

143

__vector_3: ; ceasul1 - TCNT1 - OCR1A push R18 ldi R18, 5 add R17, R18 cpi R17, 105 brne r17_inca_mic clr R17 r17_inca_mic: pop R18 reti La fiecare execuie registrul R17, ales pentru a ine noiunea de timp, crete cu 5 de la 0 la 100 ceea ce nseamn c sunt necesare aproximativ

valoarea maxim 100 = =20 de valoare incrementat 5

execuii ale subrutinei pentru a trece afiorul de la complet nchis la complet deschis. Cum ceasul1 a fost configurat s genereze aceast ntrerupere la aproximativ 120ms , asta nseamn c afiorul trece prin toate strile n aproximativ 20120ms=2400ms=2.4s . Ultima valoare util pentru R17 va fi 100, valoare aleas pentru a respecta constrngerile de mai sus. Dup depirea acestei valori, R17 se reseteaz la 0 i ciclul se reia. Subrutina de gestionare a ntreruperii de depire a valorii maxime (255) este aceea care are grij ca starea LED-urilor s evolueze corect n timp. Codul pentru aceast subrutin poate fi urmtorul : __vector_5: ; ceasul0 - depire inc R19 cp R19, R17 brsh afiseaza_perioada_inchisa ser R16 rcall afiseaza_r16 rjmp continua_intreruperea afiseaza_perioada_inchisa: clr R16 rcall afiseaza_r16 cpi R19, 100 brne continua_intreruperea clr R19 continua_intreruperea: reti n aceast bucat de cod, R19 reprezint registrul prin care subrutina tie ce este de fcut cu afiorul la fiecare execuie. De aceea ea mai poart i denumirea de variabil de stare a subrutinei. Pai sunt simpli : afiorul este complet deschis, dac valoarea din R19 va fi mai mic dect timpul de a sta pornit pstrat n R17 i

144

este complet nchis, dac valoarea lui R19 este mai mare sau egal cu cea pstrat n R17. Fiecare execuie a subrutinei incrementeaz R19 pentru a ine evidena timpului trecut i pentru a putea genera corect instruciunile astfel nct s se obin luminozitatea dorit. Evident, din cauza faptului c formele se repet periodic, R19 se reseteaz i el dup ce atinge maximul dat de constanta aleas : 100. O perioad complet (timpul necesar lui R19 s treac de la 0 la valoarea maxim de 100) o putem aproxima ca necesitnd nr. de incrementri255baza de timp a numrtorului secunde. Unde : nr. de incrementri reprezint valoarea constantei alese adic 100, iar baza de timp a numrtorului ine cont de baza de timp a sistemului ( 1 s ) i de factorul su (1) pentru a fi calculat. Rezultatul : numrtorul se incrementeaz o dat la 1 s deci baza de timp a numrtorului=1 s=0.001ms=0.000001 s . Aadar, o perioad de trecere prin toate cele 100 de valori pentru a obine o poriune din grafic necesit 1002550.000001s=0.0255s . Asta nseamn c ntre 2 modificri a lui R19 realizate n ntreruperea ceasului1, ceasul0 i execut ciclul complet de

perioada de generare a ntreruperii ceasului1 0.12 = =4.7 ori sau, rotunjind timpul necesar generriiunei poriuni complete de grafic 0.0255
n sus, de 5 ori. Ne mai rmne de prezentat doar aplicaia principal care nu surprinde pe nimeni c arat n felul urmtor : main: rcall initializeaza_perif clr R17 ; pornim de la valori cunoscute pentru clr R19 ; regitrii folosii de aplicaie executa_vesnic: rjmp executa_vesnic Arat destul de frumos pentru o secven principal, nu credei ? Pare bine aerisit ... Trimitem codul spre plcu i observm c rezultatul nu e mai puin dect cel ateptat : Afiorul va ncepe s pulseze de energie verde. Vedei ? Distana dintre cele dou lumi : cea a digitalului i cea a analogicului (cu valori mai multe dect 0 i 1) nu este chiar aa de mare ! n continuare vom prsi domeniul ceasurilor i ne vom ocupa de un modul cu o denumire neobinuit. Ne vom ocupa de cinele de paz al aplicaiilor din creiera

ntrebri / Exerciii : 1. Pentru aplicaia de mai sus : codul mai funcioneaz aa cum ne dorim dac alegem un factor de 64 pentru ceasul0 ? Dar un factor de 8 ? Argumentai. 2. Se poate realiza aplicaia de mai sus folosind un singur ceas ? Argumentai. 3. La modul n care este scris aplicaia de mai sus, afiorul crete n intensitate de la complet nchis la complet deschis i apoi se reseteaz. Modificai codul astfel nct

145

dup ce se atinge starea de complet deschis, afiorul s nceap s-i micoreze treptat intensitatea LED-urilor pn la complet nchis.

[18s] Cinele, cel mai bun prieten al omului i nu numai ...


Pe msur ce aplicaiile noastre vor deveni mai complexe i mai lungi riscul ca noi, ca i oameni, s greim atunci cnd scriem instruciuni va crete. O deosebit problem n acest sens o reprezint controlul ciclurilor. S lum un exemplu, Considerm urmtoarea bucic de cod : ciclu_mare :
; instruciuni din ciclu

ldi R20, 0x05


; alte instruciuni din ciclu care nu modific valoarea lui R20 ci doar o folosesc (pentru add de exemplu)

dec R20 brne ciclu_mare

De ndat apare o problem : dac noi mereu ncrcm informaie n R20, dar o i folosim pe post de valoare de control pentru oprirea ciclului. ntrebare : va depi vreodat creieraul aceast secven de instruciuni ? Rspunsul firesc ar fi c nu, cu excepia ntreruperilor, dar nu le bgm n seam pe ele pentru simplul motiv c nu toate aplicaiile le folosesc. Noi discutm aici de cel mai ru caz posibil. Dei nu este ceea ce ne-am propus, din cauza unei neatenii, aplicaia nu va funciona nicodat cum ne-am fi dorit rmnnd blocat n acest ciclu. De reparat se poate repara, dar gndii-v dac ciclul nostru ar fi parte dintr-o secven foarte mare i greu de parcurs (cu multe etichete i salturi de execuie). Atunci sarcina noastr de a gsi vinovatul s-ar complica teribil de mult. n aceste condiii, ce putem face ? Nu e nici prima i nici ultima dat cnd Ale vine cu soluia: folosim cinele de paz al aplicaiilor. S nu credei c este o denumire exagerat, chiar aa se numete i n literatura de specialitate (watchdog n englez). Dar ce este acest cine de paz i cum ne poate el ajuta ? Cinele de paz al aplicaiilor reprezint un modul din creiera care are grij ca secvena de cod pe care o scriem s nu o ia razna. n esen, modulul este un ceas care are o instruciune special asociat, este vorba de WDR, prin care timpul inut n eviden este resetat. Dac ceasul ajunge s depeasc timpul maxim ce-l poate pstra fr s fie resetat, atunci tim c ceva nu este n regul, c a aprut o eroare i c sistemul trebuie fie s genereze aciuni corectoare ntreruperi, fie, n cel mai frecvent caz, s se reseteze complet i s reia execuia codului de la adresa 0. n principal, folosind modulul cinelui de paz avem posibilitatea de a urmri i controla execuia corect a codului. Am spus c modulul este un ceas. Nu am minit! La baza sa se afl un ceas care poate genera aciunea corectoare la diferite intervale de timp dup cum vom vedea. Totui, trebuie s precizm faptul c ceasul utilizat de modul nu este la fel de capabil ca cele speciale (ceasul0 i ceasul1); nu avem acces direct la valoarea sa curent, iar el servete, spre deosebire de celelalte module, doar ca element de inere a evidenei timpului trecut de la ultima resetare.

146

Dac am lua exemplul de mai sus i l-am proteja cu acest modul, codul ar arta cam aa :
; instruciuni de iniializare a modulelor printre care i a modulului cinelui de paz

ciclu_mare :

; instruciuni din ciclu

brne ciclu_mare wdr ; resetm cinele pentru c ciclul s-a terminat cu succes
; alte instruciuni ale aplicaiei

Iniializarea modulului presupune precizarea, printre altele, a timpului maxim de ateptare dup care aciunea corectoare se aplic. Dac, n secvena de mai sus, execuia ciclului ar fi durat mai mult dect aceast perioad de depire atunci aciunea corectoare este invocat. Dac, pe de alt parte, ciclul ar fi corect scris i s-ar fi executat ntr-un timp mai mic dect aceast perioad de depire, atunci instruciunea WDR ar reui s reseteze celul nainte ca acesta s latre i s cear aciune. Desigur c acest lucru presupune aproximarea duratei de execuie a ciclului, dar, dup cum vom vedea, opiunile modulului sunt suficient de ngduitoare i cu timpi mai mari (de ordinul secundelor). Cinele are asociat un singur registru special prin care i se controleaz toate aspectele activitilor sale. Acest registru se numete WDTCR1 i este situat la adresa 0x0021 n spaiul regitrilor speciali. Ca i semnificaie a biilor, urmrim mai nti amplasarea lor n urmtorul tabel : Rang Notaie Op. permise Val. iniial
7 6 5 4 3 2 1 0

WDIF

WDIE

WDP3

WDCE

WDE

WDP2

WDP1

WDP0

S/C 0

S/C 0

S/C 0

S/C 0

S/C X

S/C 0

S/C 0

S/C 0

apoi denumirile i semnificaiile n urmtorul : Denumire WDIF Nume complet Semnalizeaz declanarea unei ntreruperi Semnificaie Atunci cnd valoarea de timp alocat este depit i modulul este configurat s genereze o ntrerupere, acest bit se seteaz automat pe 1. tergerea sa se face fie prin scrierea unui 1 logic pe aceast poziie, fie n mod automat, prin execuia subrutinei de ntrerupere. Acest bit controleaz mpreun cu WDE, aciunea ce se va lua n momentul depirii timpului alocat de ctre cel. Posibilele combinaii de valori se pot citi din urmtorul tabel :

WDIE

Activeaz generarea de ntreruperi de ctre modul

denumirea complet n englez ar suna cam aa : Watchdog Timer Control Register, iar echivalentul ei n limba romn ar fi Registrul de control al cinelui de paz

147

Denumire

Nume complet

Semnificaie
WDE WDIE Stare cel Aciune corectoare

0 0 1 1

0 1 0 1

Oprit Pornit Pornit Pornit

Nici una
ntrerupere Resetarea creieraului ntrerupere

n mod de ntrerupere, WDIE se terge automat dup executarea subrutinei de tratare a ntreruperii. n acest fel, urmtoarea depire va avea ca efect resetarea creiraului. WDCE Bit de control al modificrii celului Pentru a seta bitul WDE pe 0, trebuie mai nti s setm bitul WDCE pe 1. Dup aceast perioad (n 4 uniti de timp), WDCE se reseteaz automat, iar resetarea lui WDE devine imposibil. Un 1 logic activeaz modulul pe cnd un 0 logic (mpreun cu WDCE) oprete modulul. Valoarea sa iniial, reprezentat n tabel prin acel X, simbolizeaz faptul c ea nu este fix (1 sau 0) ci de fapt este aceeai, n unele situaii, cu bitul WDRF din registrul MCUSR (vezi exemplul din seciunea urmtoare). Aceti bii confer urmtorii timpi de siguran : WDP3 0 0 0 0 0 0 0 0 1 1 WDP2 0 0 0 0 1 1 1 1 0 0 WDP1 0 0 1 1 0 0 1 1 0 0 WDP0 0 1 0 1 0 1 0 1 0 1 Timp alocat 16 ms 32 ms 64 ms 0.125 s 0.25 s 0.5 s 1s 2s 4s 8s

WDE

Activarea modulului

WDP3 WDP0

Secven ce selecteaz timpul maxim permis acordat de modul

[Restul de valori posibilie nu au niciun efect.]

148

ntreruperea generat are adresa relativ 0x000C n tabela de ntreruperi sau 12, dac folosim baza 10 pentru a scrie eticheta subrutinei (__vector_12). Perfect! tim suficient ct s abordm un mic exemplu . Observm c modulul are capacitatea de a genera ntreruperi la intervale precise de timp. Propun s realizm o aplicaie care s numere n mod binar cu renoirea valorii o dat la 2 secunde, de pild. tiu c aceasta nu este utilizarea normal pentru acest modul (la fel de bine puteam face asta cu unul din ceasuri) pentru c, n mod special, nu vom folosi instruciunea WDR, dar rbdare cci vom avea i un astfel de exerciiu. Vom construi, n seciunea imediat urmtoare, un exemplu n acest sens imediat dup ce vom mai nva cte ceva. Am ales s folosim cinele de paz pentru aceast generare de ntrerupere deoarece aceste intervale sunt simplu de selectat i nu necesit calcule speciale cum fceam atunci cnd lucram cu ceasuri. Aadar, introducem registrul nostru n aplicaie : WDTCR = 0x21 i prezentm subrutina de iniializare a modulelor : initializeaza_perif: ldi R16, 0b01000000 ; activm nteruperea cinelul de paz out WDTCR, R16 ldi R16, 0b01001111 ; selectm o perioad de 2 secunde ca timp maxim de atepare al celului out WDTCR, R16 sei ; activm nteruperile globale ldi R16, 0b00000011 ; pornim doar afiorul, nu avem nevoie de minitastatur out DDRB, R16 ret Destul de simplu, nu credei ? Totui, nu este la fel de simplu ca secvena principal : main: rcall initializeaza_perif clr R16 executa_vesnic: rjmp executa_vesnic Tot codul se mut astfel n subrutina de tratare a ntreruperii celului : __vector_12: push R17 inc R16 ; incrementm numrtorul i rcall afiseaza_r16 ; afim valoarea curent in R17, WDTCR ; activm din nou nteruperea celului pentru ca, la urmtoarea depire ori R17, 0b01000000 ; s nu reseteze creieraul out WDTCR, R17 pop R17 reti

149

(s nu uitai de .global __vector_12!) Neutiliznd instruciunea WDR, celul nostru va ltra odat la 2 secunde, moment n care noi afim valoarea numrat i reactivm celul pentru a nu ne da socotelile peste cap i resetndu-ne Attiny-ul la urmtoarea depire. Aadar, acesta este celul creieraului i aa funcioneaz el pentru modul de lucru cu ntreruperi. n seciunea urmtoare vom vedea cum opereaz el cu situaii mai grave n care nu se poate aduce sistemul la o stare cunoscut dect prin resetarea sa. Acest aspect ridic o problem : dac i celul poate reseta creieraul, cum ne putem da noi seama din ce direcie a venit resetarea ? Poate am vrut noi s resetm creieraul prin butonul de reset sau poate celul a fcut-o. Cum putem ti ? Exist o modalitate.

ntrebri / Exerciii : 1. Gsii dou deosebiri ntre modulul celului i cel al unui ceas obinuit de pe creiera. 2. ncercai aplicaia de mai sus cu aceast subrutin de gestionare a ntreruperii : __vector_12: inc R16 rcall afiseaza_r16 reti Cum se va comporta plcua ? Putei gsi o explicaie pentru acest comportament ?

[19s] i pe mine cine m-a resetat ?


Acum c avem 2 modaliti de a reseta creieraul : prin celul aplicaiei sau de ctre noi prin apsarea butonului de reset, apare inevitabil ntrebarea : poate Attiny-ul s i dea seama cine l-a resetat ? Dar poate v ntrebai, de ce am vrea noi s tim asta ? S ne gndim la urmtorul scenariu : avem o aplicaie a crei execuie a ajuns ntr-un ciclu bucluca. Avem activat celul i ne bazm pe el c va salva aplicaia printr-o aciune de resetare a creieraului. Pi dac aa stau lucrurile, cine mpiedic creieraul s mai ajung o dat s rmn blocat n acelai ciclu ? Rspuns : nimeni! Dac nu suntem ateni i nu acionm, creieraul va ajunge s rmn blocat mereu n respectiva regiune de cod i, n consecin, va fi mereu resetat de ctre cel. Pe de alt parte, dac am ti din ce motiv s-a resetat Attiny-ul am putea, eventual, lua msuri pentru a ncerca s mpiedicm reintrarea n respectivul ciclu. Aadar, exist situaii n care este util s cunoatem cine ne-a resetat aplicaia. Pentru asta avem un registru special care ne poate ajuta. Acel registru se numete MCUSR1. MCUSR este situat la adresa 0x0034 n spaiul regitrilor speciali i are urmtoarea configuraie de bii :

MCU Status Register n englez i Registrul de stare a sursei de reset pentru creiera n romn. MCU este la rndul su o prescurtare pentru microcontroller sau creiera, aa cum ne place nou s l numim

150

Rang Notaie Op. permise Val. iniial

---

---

---

---

WDRF

BORF

EXTRF

PORF

C 0

C 0

C 0

C 0

S/C ?

S/C ?

S/C ?

S/C ?

Interpretarea acestor bii este dup cum urmeaz : Denumire --Nume complet Bit nesemnificativ Semnificaie Aceti bii nu au nicio influen asupra creieraului, ei putnd fi numai citii. La fiecare citire va rezulta valoarea 0. Dac creieraul a fost resetat de ctre cel, acest bit are valoarea 1 i 0 n caz contrar. Aceast surs de resetare nu o vom discuta n crulie, dar ea exist i i permite creieraului s reacioneze atunci cnd tensiunea sa de alimentare scade sub un anumit prag. n felul acesta, creieraul poate s-i salveze starea rapid, de pild, i s se pregteasc pentru ncetarea alimentrii. Dac creieraul s-a resetat din aceast cauz, acest valoare va fi 1, iar 0 n caz contrar. Are valoarea 1 dac Attiny-ul a fost resetat forat din exterior i 0, dac nu. 1 logic ne spune c a trecut prin aceast secven pe cnd 0 logic ne spune contrariul. secvena de iniializare reprezint faza prin care toi regitrii din creiera iau valoarea lor iniial prezent la fiecare registru pe rndul de jos al tabelului su.

WDRF BORF

Creiera resetat de cel Creiera resetat de nivel de alimentare redus

EXTRF PORF

Attiny resetat din exterior Creieraul trece prin secvena de iniializare a regitrilor

Fiecare bit reprezentnd un motiv de resetare, problema noastr se reduce la a inspecta acest registru. Vom lua un exemplu clarificator. Presupunem c dorim s afim valoarea acestui registru pentru a vedea motivul resetrii i a observa celul n aciune. Aciunile vor fi clare i simple : 1. iniializm afiorul, minitastatura i celul de paz pentru a reseta creieraul atunci cnd nu apelm instruciunea WDR dup o perioad fix de timp (2 secunde s zicem), 2. afim starea registrului MCUSR, 3. intrm ntr-o bucl infinit n care apsarea lui D0 va calma celul (va apela instruciunea WDR), iar 4. dac D0 nu este apsat sau dac trec mai mult de 2 secunde ntre 2 apsri celul va reseta creieraul i noi vom vedea asta prin valoarea afiat la punctul 2. Aadar, MCUSR este introdus n aplicaia noastr prin urmtoarea linie : MCUSR = 0x34 , iar iniializarea perifericelor devine simpl prin discuiile avute n ultimele 2 seciuni :

151

initializeaza_perif: ldi R16, 0b00001111 ; selectm o perioad de 2 secunde pentru cel i capacitatea de a out WDTCR, R16 ; reseta creieraul dac nu-l calmm (prin WDR) n acest interval sei ; pornete ntreruperile globale ldi R16, 0b00010011 ; att afiorul ct i minitastatura sunt pornite out DDRB, R16 ret Neavnd nicio ntrerupere, nu ne mai rmne dect secvena principal : main: rcall initializeaza_perif in R16, MCUSR ; afim motivul resetrii precedente rcall afiseaza_r16 clr R16 ; resetm registrul pentru a nu rmne motive mai vechi de resetare n el out MCUSR, R16 executa_vesnic: rcall citeste_taste_r17 sbrc R17, 0 ; dac D0 nu este apsat, wdr ; srim peste instruciunea de calmare a celului rjmp executa_vesnic Observai, v rog, cum curm MCUSR de ndat ce l citim. Acest lucru se face, aa cum scriam, pentru a nu pstra motivele celorlalte resetri. Dup apsarea butonului de Reset, se va observa cum LED-ul corespunztor bitului EXTRF din MCUSR va lumina aa cum ne ateptm. Dou secunde mai trziu i niciun D0 apsat i celul va ltra, iar Attiny-ul se va reseta i motivul resetului l vom vedea pe afior. n felul acesta, LED-ul corespunztor bitului WDRF se va aprinde. Probabil v ntrebai de ce nu s-a aprins i LED-ul 0 (PORF) ? Nu se iniializeaz valoarea registrelor ori de cte ori creieraul se reseteaz ? Ei bine, nu chiar! Iniializarea registrelor se face o singur dat atunci cnd creieraul este alimentat prima i prima dat! Drept urmare, dac scoatei cablul de alimentare i apoi l bgati din nou vei observa c, ntradevr, LED-ul 0 se va aprinde, ceea ce arat faptul c, ntr-adevr, iniialziarea registrelor a avut loc. n alt ordine de idei, s ne gndim un pic : dac iniializarea registrelor ar avea loc la fiecare Reset, nu ar mai trebui s curm manual registrul MCUSR, nu? Aciunea ar fi fcut n mod automat de ctre sistem. Ori este clar c acest lucru nu se realizeaz. Din acest motiv, bitul PORF poate fi folosit pentru a determina dac aplicaia a pornit prima i prima dat din cauza alimentrii cu tensiune a creieraului. Cam att despre capacitatea creieraului de a-i da seama att de motivul su de reset ct i dac sau nu aplicaia ruleaz pentru prima dat de la alimentarea sa. n continuare vom discuta despre un subiect de foarte mare actualitate : eficientizarea consumul de energie. Cum rspunde creieraul la eforturile societii actuale de a fi eco ?

152

ntrebri / Exerciii : 1. n aplicaia discutat mai sus, de ce credei c nu putem discuta despre activarea bitului BORF a lui MCUSR ? 2. Modificai aplicaia de mai sus astfel nct, la detectarea unei resetri cauzate de ctre cel, s se afieze pe LED-uri tiparul , s se dezactiveze celul i s se plaseze execuia ntr-un ciclu infinit fr instruciuni utile.

[20s] Eco Ale!


ntr-o lume n care tehnologia i electronica caut alternative ct mai eficiente de consum energetic, a aprut Ale! Dar unde este Ale n acest peisaj ? Avem mecanisme prin care putem s controlm consumul de putere n creiera ? Evident, universul ar fi un pic mai monoton i seciunea aceasta ar fi un pic mai scurt sau chair inutil dac rspunsul ar fi fost nu. Noroc c nu este cazul : Da, avem controlul acestor aspecte pe Attiny. Ale cunoate chiar 3 astfel de moduri pentru a reduce consumul su : 1. Mod 1 (Idle n literatura de specialitate) - nucleul, poriunea din creiera care execut instruciuni este oprit mpreun cu funcionalitatea memoriei nevolatile (cea care deine instruciuni), dar restul de module funcioneaz n continuare. Funcioneaz i ntreruperile lor care pot trezi execuia instruciunilor dac sunt activate i sunt generate 2. Mod 2 (ADC Noise Reduction) - are aceleai module dezactivate ca i cele din Mod 1 , dar mai are n plus dezactivat i modulul de intrare ieire (capacitatea creieraului de a citi, respectiv scrie valori logice pe pinii si) 3. Mod 3 (Power Down) - este cel mai restrictiv mod dintre toate prezente n care aproape toate modulele sunt dezactivate mai puin ntreruperea celului, ntreruperile venite pe pinii din exterior i identificarea unei secvene de comunicaii ntre mai multe creierae Pentru a ne face o impresie despre noiunea de eficien, precizm urmtoarele : dac n modul normal de lucru (s-i acordm o denumire : Mod 0) consumul ar fi avut valoarea 1, Mod 1 ar primi valoarea 0.24 (mai mult de 4 ori mai eficient dect Mod 0!), iar celelalte moduri ar avea un consum chiar mai mic. Mod 3 este cel restrictiv avnd o valoarea asociat ce merge pn la 0.002 (de 500 de ori mai eficient dect Modul 0!). Dar de ce avem nevoie de consum redus ? E bun ntrebarea dac ne gndim c plcua i trage energia din calculator, iar acesta din urm dispune din plin de energie. Dac vei continua s lucrai cu aceste creierae mai mult ca sigur c va veni ziua n care vei dori s v alimentai dispozitivul folosind o surs regenerabil de energie : de la soare, de exemplu. Ei bine, panourile solare (mijlocul prin care circuitele care funcioneaz pe lumin se alimenteaz), sunt extrem de fragile n cantitatea de energie ce o pot colecta. De aceea, vei fi nevoii s limitai consumul oriunde vei putea. Atunci probabil v vei gndi la acest capitoul i vei ti imediat ce vei avea de fcut. Punerea creieraului n una din cele 3 moduri de consum redus de energie se face cu instruciunea special SLEEP mpreun cu un registrul de control special numit MCUCR1. MCUCR are adresa relativ 0x0035 n regiunea de regitri de control i are urmtoarea structur :

n englez : MCU Control Register, iar n romn : Registrul special de control al creieraului

153

Rang Notaie Op. permise Val. iniial

BODS

PUD

SE

SM1

SM0

BODSE

ISC01

ISC00

C 0

S/C 0

S/C 0

S/C 0

S/C 0

S/C 0

S/C 0

S/C 0

Desigur, completm tabelul de mai sus cu urmtorul : Denumire BODS Nume complet Adormirea detectrii ntreruperii alimentrii Semnificaie Pentru a dezactiva capacitatea de a genera o ntrerupere de cdere sub nivelul normal de alimentare atunci cnd creieraul doarme, se scrie un 1 pe acest bit. Valoarea sa citit va fi mereu 0, de aceea singura operaiune permis este citire (C). Folosit n modulul de intrare/ieire n funcii avansate de comportament. Scrierea unui 1 logic pe acest bit face creieraul s rspund la instruciunea SLEEP pe cnd un 0 logic face inutil demersul de a adormi Attiny-ul. Cei 2 bii controleaz Mod-ul de adormire dorit de ctre creiera. Valorile sale posibile sunt : SM1 0 0 1 1 BODSE Activarea adormirii detectorului de nivel SM0 0 1 0 1 Mod de adormire Mod 1 Mod 2 Mod 3 Rezervat

PUD

Dezactivarea rezistenelor ridictoare de linie Activarea capacitii de a dormi Modul de adormire dorit

SE

SM1, SM0

Funcioneaz mpreun cu bitul BODS pentru a controla comportamentul detectorului de nivel n momentul adormirii creieraului. Nu v facei griji dac nu nelegei aceast capacitate, ea oricum este abordat n aplicaii speciale ce nu le vom discuta n aceast crulie. Nu vom aborda aceast capacitate a creieraului, dar e bine de amintit c aceti 2 bii precizeaz la ce tip de aciune ar trebui Attiny-ul s fie sensibil pentru a genera o ntrerupere dictat din exterior. Ca s v facei o idee : creieraul poate s rspund la o tranziie de la 0 la 1 pe un pin exterior sau, invers, de la 1 la 0.

ISC01, ISC00

Tipul de sensibilitate a ntreruperilor externe

Aadar, pentru a adormi creieraul, procedm n felul urmtor : 1. alegem Mod-ul de adormire dorit i activm capacitate de adormire apoi

154

2. executm instruciunea SLEEP pentru a adormi efectiv Attiny-ul i totu-i calm i bine. Desigur c peisajul ar fi mai complet dac am avea o mic aplicaie n care s vedem ceva, dar , vedei voi, este un pic mai dificil de a demonstra aspectul consumului redus al plcuei. Totui, folosind un aparat de msur extern, am reuit s surpind cum se aplic teoria consumului redus de energie pe Ale. Astfel, dou msurtori ale curentului (component care ne indic consumul circuitului) au fost realizate n 2 situaii : 1. de rulare n mod 0, unde am ncrcat pe plcua exemplul numrtorului de la 6s i am obinut 1.67mA1, i 2. de rulare n mod 3, cu aplicaia scris n acest exemplu, unde am obinut o valoare a consumului de 0.006mA! Cu alte cuvinte, mod-ul 3 a fost de aproximativ

consum mod 0 1.67mA = =278 de ori mai consum mod 3 0.006mA

puin consumator de energie dect modu 0! Nu gsii acest aspect fascinant ? Dar s revenim cu picioarele pe pmnt i s definim cerina progrmelului. Va trebui s realizm un numrtor binar (nu v-ai sturat de ele nc ?) care s se incrementeze o dat la 1 secund prin intermediul ntreruperii datorate celului de paz. Nu ne oprim aici pentru c cerina asta ar trebui s vi se par cunoscut (vedei o seciune precedent). O dat cu afiarea noii valori, creieraul va adormi intrnd n cel mai adnc somn posibil dat de Modul 3 de adormire. ntreruperea va trezi Attiny-ul, va incrementa valoarea curent i o va afia. Apoi el va adormi ateptnd urmtorul eveniment i aa mai departe. ncepem soluia cu introducerea noului registru n aplicaie : MCUCR = 0x35 i apoi continum cu iniializarea perifericelor : initializeaza_perif: ldi R16, 0b00110000 ; activm instruciunea "sleep" i Mod-ul 3 de manifestare al adormirii out MCUCR, R16 ldi R16, 0b01001110 ; activm celul cu perioad de 1 secund i manifestare prin ntrerupere out WDTCR, R16 sei ldi R16, 0b00000011 ; pornim doar afiorul out DDRB, R16 ret Dup iniializare, verificm subrutina de tratare a ntreruperii celului : __vector_12: push R17 inc R16
1

mA-ul este o subdiviziune a Amperului (simbolizat cu litera A), unitate de msur internaional pentru curent aa cum V (voltul) este unitatea de msur internaional pentru tensiune. 1mA=0.001A sau 1A=1000mA

155

rcall afiseaza_r16 in R17, WDTCR ; reactivm nteruperea celului ori R17, 0b01000000 out WDTCR, R17 pop R17 reti Nimic special aici, dar, ce s vezi vine subrutina principal : main: rcall initializeaza_perif clr R16 executa_vesnic: sleep rjmp executa_vesnic care difer prin o instruciune fa de exemplul original : insturciunea SLEEP care adoarme efectiv creieraul. i, dac logica nu ne neal, asta este tot : trimis pe plcu, aceast cod se va comporta identic precum exemplul iniial discutat n seciunea celului. n fundal, noi tim c de fapt creieraul e de cteva sute de ori mai eficient din punct de vedere al consumului de energie, iar lumea este un pic mai sntoas. Dar, stai un pic! Noi am spus c Mod 3 pornete de la Mod 2 care pornete de la Mod 1 i la care adaug alte module deconectate. Mod 1 dezactiveaz modulul de intrare/ieire, dar dac acest lucru se ntmpl, LED-urile cum de stau aprinse ? Ei bine, dac mai inei minte, LED-urile nu sunt legate direct la creiera! Aici este rspunsul : afiorul consum energie din circuitul su 74HC164, circuit pe care instruciunea de adormire nu l afecteaz i a crei stare se pstreaz. S nu uitm faptul c adormirea este doar a creieraului i a nici unei alte componente de pe plcu, dar este suficient. Orice economie conteaz i oricum, dac vei fi nevoii s construii ceva eficient, probabil c vei folosi creieraul, dar sigur nu vei folosi restul de circuite, nlocuindu-le cu componente care la rndul lor consum mai puin energie. Lucrurile sunt deosebit de interesante la acest capitol de eficientizare a consumului de energie. Soluiile eficiente, n acest sens, sunt foarte valoroase, dar i dificil de gsit. Gata dragii mei, putem s nchidem i acest subiect. Ideea sa de baz este urmtoarea : intii spre consum mic pentru c doar aa putem s respectm mediul n care trim noi i semenii notrii. Un consum redus de putere se traduce n mai puin combustibil fosil ars n uzinele electrice i asta nseamn o mai puin poluarea a aerului pe care-l respirm. n continuare vom aduce memoria special sub lup i vom vedea cum putem comunica cu ea din aplicaiile noastre apoi vom continua seria de exemple frumoase.

156

ntrebri / Exerciii : 1. Calculai cu ct este mai eficient Mod-ul 3 fa de Mod-ul 1 de adormire. 2. Noi am artat mai sus, conform specificaiilor productorului, faptul c mod 3 este de 500 de ori mai eficient dect mod 0, dar n realitate am obinut faptul c el este mai eficient doar de 278 ori. Cum explicai aceast diferen ? 3. Modificai aplicaia de mai sus astfel nct s rspund la ntreruperea ceasului1 cu o perioad aleas de voi, dar pstrai Mod-ul de adormire folosit. Ce observai ? De ce credei c se comport n acest mod aplicaia rezultat ? ncercai acelai experiment pentru Mod-ul 2 i 1. Care v place mai mult ?

[21s] Un psAle i o Ale. Ceau Ale!


Cnd am nceput discuia despre creiera, spuneam noi c el are 3 tipuri de memorie : volatil, nevolatil i una special (atunci o numeam EEPROM) care are din caracteristicile amndurora. n aceast seciune vom vedea cum putem interaciona cu aceast memorie pentru a citi respectiv scrie informaii din i n ea. Pentru aceast aciune precum i datorit caracteristicilor speciale de adresare ce le are aceast memorie, exist o serie de regitri care trebuie s-i folosim atunci cnd vrem s ne nelegem cu ea. Aceti regitrii, 3 la numr, sunt urmtorii : 1. EEAR - registrul n care se va afla adresa octetului, o valoare ntre 0 i 127, conform specificaiile creieraului, cu care interacionm. El are adresa 0x001E n spaiul de adrese al regitrilor de control, iar biii si nu au funcionaliti speciale aa cum am vzut la celelalte registre de control, 2. EEDR - este registrul prin care culegem respectiv plasm octetul ce-l vrem citit respectiv scris la adresa dat de EEAR. Adresa acestui registru este 0x001D, iar biii si, asemeni registrului EEAR, nu au alt interpretare funcional pentru creiera i 3. EECR - reprezint registrul de control al memoriei EEPROM. Adresa sa este 0x001C i structura sa intern se poate urmri pe urmtorul tabel : Rang Notaie Op. permise Val. iniial
7 6 5 4 3 2 1 0

---

---

EEPM1

EEPM0

EERIE

EEMPE

EEPE

EERE

C 0

C 0

S/C x

S/C x

S/C 0

S/C 0

S/C x

S/C 0

O explicaie mai detaliat a acestor bii poate fi citit din urmtorul tabel : Denumire --Nume complet Neutilizai Semnificaie Modificarea acestor bii nu are niciun impact asupra creieraului, iar valoarea lor citit va fi mereu 0 logic. Gruparea specific comportamentul memoriei atunci cnd se scrie bitul EEPE. Astfel, exist urmtoarele posibiliti : EEPM1 0 EEPM0 0
Durat Operaiune tergere1 +

EEPM1, EEPM0

Modul de folosire al memoriei

3.4 ms

157

Denumire

Nume complet

Semnificaie EEPM1 EEPM0


Durat Operaiune Scriere

0 1 1 EERIE Activarea ntreruperii memoriei EEPROM

1 0 1

1.8 ms 1.8 ms -

tergere Scriere Rezervat

Scrierea unui 1 logic activeaz ntreruperea generat de memorie prin care se ntiineaz aplicaia c operaiunea curent s-a terminat. Un 0 logic, dezactiveaz aceast capacitate. Un 1 logic scris pe acest bit va activa posibilitatea de a folosi imediat bitul EEPE. Dup 4 baze de timp de la activare, acest bit se reseteaz automat i orice aciune ulterioar pe bitul EEPE nu se duce la bun sfrit de ctre creiera. Funcioneaz mpreun cu EEMPE i grupul {EEPM1, EEPM0} pentru a duce la capt aciunea de scriere a memoriei. Un 1 logic realizeaz aciunea de programare la adresa EEAR a aciunii alese de grupul {EEPM1, EEPM0} i a valorii pstrate n registrul EEDR. Pe parcursul duratei necesare operaiunii de scriere, EEPE se va citi 1, iar la terminarea operaiunii EEPE va fi resetat automat de ctre creiera. Scrierea unui 1 logic pe aceast poziie va genera o citire automat n EEDR a octetului ce se gsete la adresa dat de valoarea registrului EEAR din memoria special. Spre deosebire de scriere, informaia citit va fi disponibil imediat dup apel. Memoria special poate fi citit doar dac nu exist o operaiune de scriere n derulare (EEPE are valoarea 1).

EEMPE

Siguran pentru operaiuni pe memorie

EEPE

Activeaz programarea memoriei

EERE

Activeaz citirea memoriei

Din aceste explicaii putem trage o serie de cuncluzii : 1. Operaiunile de citire/scriere se desfoar diferit de cele cu care ne-am obinuit noi, existnd un procedeu special pentru fiecare tip de aciune dorit 2. Scrierea unui octet este un procedeu alctuit din 2 etape : a. tergerea octetului i b. scrierea valorii dorite 3. Din cauza proprietilor memoriei, scrierea sa necesit destul de mult timp (de ordinul milisecundelor) i asta poate duce la o serie de probleme, n special de sincronizare, pentru aplicaiile noastre. De aceea o ntrerupere special a fost prevzut pentru aceast memorie. ntreruperea se declaneaz atunci cnd aciunea de scriere s-a ncheiat i este util atunci cnd dorim s trimitem memoriei mai muli octei deodat, dar nu vrem s pierdem timp cu verificarea manual a condiiilor de terminare a scrierii.
1

prin tergere nelegem punerea respectivului octet pe valoarea 0xFF (0b11111111)

158

Un alt aspect interesant i util al acestui tip de memorii este acela c el poate fi citit din exterior. i aici nu m refer la mijloace electrice. Aici vorbim despre citirea memoriei direct din aplicaia nsoitoare psAle. Pentru a vedea cum se poate realiza acest lucru, vizitai seciunea adiional de la sfritul crtuliei numit Instruciuni de folosire a aplicaiei psAle. Dar s revenim ... Vom lua afiorul, creieraul, celul i memoria i vom construi un mic exemplu demonstrativ pe baza vechiului nostru numrtor binar. Ce dorim s realizm ? Vom face ca la fiecare valoare nou generat, pe lng afiarea sa pe LED-uri, s fie salvat ntr-o locaie de memorie (s zicem adresa 0) din EEPROM. Cnd creieraul va fi alimentat pentru prima dat, el se va uita la respectiva adres, va lua valoarea ce o va gsi acolo i va continua numrarea de la acea valoare. n felul acesta, putem avea certitudinea c n orice condiii, numrtorul va numra n continuare de la vechea valoare dac parametrii de funcionare (alimentarea) sunt coreci. nainte de a sri n cod, mai precizm c generarea ntreruperii de ctre cel se va face o dat la 8 secunde pentru a nu exagera numrul de operaii cu acest tip de memorie1. Astfel, definim cei 3 regitrii pentru aplicaia noastr : EEAR = 0x1E EEDR = 0x1D EECR = 0x1C i introducem direct subrutina de iniializare a modulelor : initializeaza_perif: ldi R16, 0b01101001 ; activm celul cu generarea ntreruperii la 8 secunde out WDTCR, R16 sei ldi R16, 0b00000011 ; afior pornit, restul de module externe : nchise out DDRB, R16 ret Observai v rog cum nc nu am introdus nicio operaiune cu EEPROM-ul, dar asta este pentru c el nu necesit efectiv iniializare. Datorit modului de operare al registrului de control, memoria EEPROM se folosete direct, oriunde este nevoie de ea. ncepem cu subrutina principal unde avem o astfel de operaie : main: rcall initializeaza_perif clr R16 out EEAR, R16 ; ncrcm registrul de adrese al memoriei cu adresa dorit 0 sbi EECR, 0 ; realizm o cerere de citire pentru a ncrca valoarea octetului n EECR in R16, EEDR ; plasm valoarea citit n R16 pe post de valoare iniial a numrtorului executa_vesnic:
EEPROM-ul suport un numr limitat de intervenii (tergeri/scrieri) de aproximativ 100000. Valoarea este suficient pentru viaa creieraului, dar trebuie avut totui grij s nu abuzm de ea dac nu este necesar.
1

159

rjmp executa_vesnic i continum cu subrutina de tratare a ntreruperii celului unde avem instruciunile de actualizare a memoriei : __vector_12: push R17 inc R16 rcall afiseaza_r16 clr R17 out EEAR, R17 ; alegem adresa 0 a memoriei speciale out EEDR, R16 ; depozitm valoarea ce dorim s o scriem sbi EECR, 2 ; dezactivm sigurana de scriere sbi EECR, 1 ; declanm salvarea octetului dorit in R17, WDTCR ; reactivm nteruperea celului ori R17, 0b01000000 out WDTCR, R17 pop R17 reti Scriem i trimitem spre plcu 8 secunde mai trziu vom avea prima valoarea afiat : 0 apoi dup alte 8 secunde : 1 i aa mai departe. Dac vom scoate alimentarea i o vom introduce la loc, vom vedea c, ntr-adevr, valoarea afiat dupa primele 8 secunde va fi ultima valoare la care s-a ajuns nainte de a tia alimentarea. Acesta este un mod de folosire al memorie. De regul, acest tip de memorie gzduiete valori care dicteaz comportamentul aplicaiei. De exemplu, dac am face 2 stropitori automate, prima care pornete la fiecare 30 minute, iar cealalt care se declaneaz la fiecare 45 de minute, EEPROM-ul ar putea fi folosit pentru a nmagazina acest tip de ateptare. Dei stropitorile ar fi identice din punct de vedere fizic, valorile pstrate n memoria special sunt cele care le-ar dicta comportamentul. Afior, minitastatur, module interne ce zicei, mergem mai departe i i dm lui Ale posibilitatea de a simi mediul su ? Ce zicei dac ncepem cu temperatura ?

ntrebri / Exerciii : 1. Dac folosim o ntrerupere la fiecare 8 secunde, calculai n ct timp am consuma cele 100000 de tergeri/scrieri ale EEPROM-ului ? Procedai la fel i pentru o ntrerupere aleas de 1 minut respectiv o ntrerupere de 1 secund.

[22s] Ale, tii cumva ce temperatur este ?


Ha haa n aceast seciune vom nva ceva meseria. Vom vedea cum creieraul lui Ale poate s priveasc n mediu i s citeasc un pic natura ce o nconjoar.

160

De ce nu am discutat despre asta mai devreme, v ntrebai ?! Ei bine, aa cum am vzut atunci cnd am pclit ochii s cread c Attiny-ul poate controla intensitatea LED-urilor, exist 2 lumi care sunt foarte diferite : pe deoparte avem universul fizic n care trim i n care evenimentele sunt continue i sentimentele sunt reale, iar pe de alt parte avem creieraul i semenii lui unde tot ce este construit are la baz 2 elemente fundamentale : 1 i 0, valori logice. Interaciunea dintre cele 2 universuri se face cu mare dificultate dup cum am vzut n exemplul cu intensitatea. Atunci discutam, dac mai inei minte, de modalitatea prin care Ale poate s trimit spre exterior semnale continue (cu intensiti variabile) pe care mediul i observatorii si (noi) s le recunoasc. Dar invers ? Cum am putea folosi creieraul s citim valorile continue din mediul n care exist ? Cum am putea sensibiliza creieraul la lucrurile ce se petrec n jurul su ? Haidei s vedem cu ce ne confruntm mai nti ca s nelegem unde ar fi dificultatea cci exist o problem ... Aa cum spuneam, natura este plin de lucruri continue. Putem nelege continuitatea printrun simplu experiment mental : s zicem c am avea un microscop care are capacitatea de a mri ori de cte ori dorim noi obiectul studiat. Alegem un obiect pe care l punem sub lup, orice obiect. S spunem c alegem o frunz de tei pentru c este mic. Punnd frunza sub lup, continuitatea ne spune c putem mri ori de cte ori vrem imaginea c sigur vom avea ce vedea. Cu alte cuvinte, obiectele fizice nu sunt compuse din elemente indivizibile i numrabile ci din substan plin, liniar i continu.

Aceali lucru se poate spune i despre un grafic (o manifestare a unei valori continue) :

161

Orict am ncerca s mrim un punct pe un grafic vom vedea c vom da peste alt linie i alt linie i alt linie. Adevrul este c linia graficului este continu : nu vom gsi intervale ntre care s putem trece dintr-o parte a liniei n cealalt parte peste o ntrerupere imaginar. i atunci apare problema : cum putem s depozitm aceste valori ntr-o valoare binar ? Cum putem s depozitm o valoare continu (cu un numr nelimitat de zecimale) ntr-o variabil binar de 8 bii ? Greu Dar nu imposibil. Trebuie totui s nelegem ceva : nu vom putea pstra niciodat n mod exact valoarea fizic ntr-o variabil binar, dar putem ncerca. Un alt motiv pentru care nu pstrm valoarea exact este unul de utilitate : uneori nici nu trebuie s cunoatem valoarea real a unui parametru. Cu alte cuvinte, uneori ne putem mulumi i cu 3.27 dac valoarea real este 3.2744573427235262378745009030... Asta putem face i asta poate face i Ale. nainte de toate, trebuie s nelegem c Attiny-ul lui Ale poate msura tensiuni. Nu viteze, nu fore ci doar tensiuni electrice. Modalitatea prin care putem pstra astfel de valori n Ale este simpl : avem 10 bii la dispoziie, 8 bii ntr-un registru i 2 n altul, n care putem ncrca valoarea fizic citit. Aceti 10 bii ne confer posibilitatea inerii a 22...2 =2 =1024 valori.
de10 ori

10

Dar cum interpretm aceste valori i ce ne poate spune o informaie citit din aceti bii despre valoarea real a tensiunii prezente ? Procedeul este simplu : exist o valoarea maxim de referin care are asociat valoarea binar 0b1111111111 i o valoare minim (0 Voli de obicei) care are atributi valoarea binar 0b0000000000. Asta nseamn c de la 0Voli la valoarea de referin i este asociat un domeniu binar 0b0000000000 0b1111111111 sau 1024 de valori binare unice. n acest sens, fiecare incrementare binar ar aduga o valoare final citit de

tensiunea de referin Voli. Avnd aceste informaii, 1024

putem merge invers s aproximm valoarea real a tensiunii citite. Cel mai bine nelegem acest procedeu printr-un exemplu. Vom considera tensiunea de referin ca fiind 5.00 Voli. Conform formulei noastre, asta nseamn c o incrementare se traduce n o modificare a valorii reale cu aproximativ

5.00 V sau 4.88 miliVoli (1 milivolt, 1024

prescurtat mV reprezint a mia parte dintr-un Volt). Cu alte cuvinte, dac cei 10 bii ar avea valoarea zecimal 137 n ei, atunci am putea spune c valoarea real a tensiunii citite de ctre creiera ar fi aproximativ 1374.88mV=0.6685V . i n felul acesta rezolvm problema nmagazinrii valorii continue reale : printr-o interpretare a informaiei stocate dup paii de mai sus. Observai v rog cum am folosit cu atenie cuvntul aproximativ n aceast propoziie. Motivul este unul simplu : avnd n vedere c unei incrementri binare i corespunde o valoare real de 4.88mV , asta nseamn c nu putem msura tensiuni mai mici dect aceasta. Nu putem msura tensiuni cum ar fi 4mV sau, mai ru, 2.5mV . De aceea, valoarea celor 10 bii va fi o bun aproximare a valorii reale, dar nu i una teribil de exact.

162

Un lucru important pentru ca acest procedeu s funcioneze este acela ca tensiunea de referin aleas s fie una foarte stabil. Gndii-v ce s-ar ntmpla dac n loc de 5.00 Voli am avea 5.05 Voli, dar noi am crede c folosim 5.00V. Dac aa ar sta lucrurile, atunci 1 bit ar valora acum 4.93mV ceea ce difer semnificativ fa de valoarea real calculat de 4.88mV . Cu aceast nou valoare, 137 s-ar traduce n 1374.93mV=0.67541V . Eroarea msurat ar fi de 0.67541V0.6685V=0.00691V sau 6.91mV . Pi asta ar nsemna unul sau poate chiar 2 incrementri diferen ale valorii celor 10 bii fa de valoarea real. Aadar, eroarea este una semnificativ chiar i pentru o deviere de 0.05 voli a tensiunii de referin. Acum c am neles cum am putea interpreta aceste valori reale printr-o aproximare binar, haidei s ne ntoarcem la creieraul nostru i s discutm un pic despre modulul de conversie analogdigital1 (cci aa se numete transpunerea valorilor electrice ~ tensiunea ~ n valori digitale ~ regitrii ~) este implementat pe creiera cu ajutorul unor serii de registre. Sunt 4, ca s fim mai exaci : 1. ADMUX2 2. ADCSRA3 3. ADCSRB4 4. ADCL5 5. ADCH6 S vedem care ce face. Vom ncepe cu cele 2 registre care in valoarea binar a conversiei (acei 10 bii de care discutam adineauri). Acetia sunt ADCL i ADCH. ADCL este situat la adresa 0x0004 n spaiul de regitri speciali pe cnd ADCH este poziionat la adresa 0x0005, n imediata vecintate a lui ADCL. De regul, ADCL ine primii 8 bii, iar ultimii 2 bii se afl pe poziiile 0 respectiv 1 n ADCH. Spun de regul pentru c acest lucru nu este tot timpul adevrat. Dup cum vom vedea, exist un bit n registrul de control ADMUX care modific aceast ordine. Dar de ce ar vrea cineva o alt interpretare a acestei valori? ntrebai. Ca regul de baz a convertorului trebuie spus c valoarea binar prezent n aceti 10bii nu se actualizeaz dect dup citirea lui ADCH. Asta nseamn c, indiferent de ct de mult precizie avem noi nevoie (poate ne-ar satisface doar primii 8 bii ai valorii, sau, poate doar ultimii 8 bii), trebuie s citim i valoarea superioar a rezultatului pentru a putea actualiza valoarea. Pentru c acest lucru nu ne convine tot timpul, proiectanii creieraului au lsat o porti de scpare prin acel bit din ADMUX. Aadar, introducem direct aici liniile de definire pe care le putem folosi n aplicaia noastr : ADCL = 0x04 ADCH = 0x05

1 2

prescurtat : CAD (Convertor Analog Digital), iar n englez : DAC (Digital to Analog Converter) n englez : ADC Multiplexer Selection Register 3 ADC Control and Status Register A 4 ADC Control and Status Register B 5 ADC Low Data Byte 6 ADC High Data Byte

163

Haidei s ne uitm un pic i la ADMUX, dac tot veni vorba de el. ADMUX este situat la adresa 0x0007 i are urmtoarea structur : Rang Notaie Op. permise Val. iniial
7 6 5 4 3 2 1 0

REFS1

REFS0

ADLAR

REFS2

MUX3

MUX2

MUX1

MUX0

S/C 0

S/C 0

S/C 0

S/C 0

S/C 0

S/C 0

S/C 0

S/C 0

Unde, continund analiza biilor, aflm urmtoarele : Denumire REFS2 REFS0 Nume complet Grup de selecie a tensiunii de referin Semnificaie Prin aceti bii se poate controla tensiunea de referin dorit pentru convertor. Creieraul dispune intern de surse de tensiune foarte stabilizate, dar dac acest lucru nu ne satisface, se pot aduce valori din exterior. Valorile posibile ale acestui grup sunt :
REFS2 REFS1 REFS0 Interpretare Folosete tensiuena de alimentare a creieraului ca referin a tensiunii Folosete o tensiune aplicat pe pinul PB0 ca tensiune de referint Utilizeaz o tensiune de referin intern a creieraului de 1.1V Rezervat Folosete o tensiune de referin intern de 2.56V fr condensator de filtrare exterior Aceeai interpretare ca la 110 : o tensiune de referin intern de 2.56V, dar de data asta mpreun cu un condensator de filtrare exterior

0 1

1 1

1 0

! 110 i 111 funcioneaz doar dac creieraul este alimentat de la o surs de tensiune de 3V ceea ce, pe plcua noastr, nu este adevrat ! ADLAR Controleaz poziionarea informaiei n registrele ADCH ADCL Un 0 logic prezent pe acest bit va face ca ADCH s conin cei mai semnificativi 2 bii pe poziiile 1 si 0, iar restul de 8 bii s fie depozitai pe ADCL pe cnd un 1 logic scris pe aceast poziie va face ca ADCH s conin cei mai importani 8 bii din rezultat cu primii 2 bii prezeni pe poziiile 7 i 6 din registrul ADCL. Aceast capacitate ajut

164

aplicaiile n discuia purtat de noi mai sus. MUX3 MUX2 Grup prin care selectm sursa ce o dorim convertit Aceast surs de tensiune poate veni din exterior (ca tensiune cules pe pinii lui Attiny) sau din interior (de la termometrul intern). Cele mai importante configuraii ale acestor bii poate fi urmrite din tabelul urmtor : MUX[3:0] 0000 0001 0010 0011 0100 - 1011 Sursa inspectat ADC0 (de pe pinul PB5) ADC1 (PB2) ADC2 (PB4) ADC3 (PB3) [Folosite n aplicaii mai complexe, cu nregistrare a semnului tensiunii] VBG , aprox. 1.1V GND Nefolosit ADC4 (Termometru intern)

1100 1101 1110 1111

Dup cum putei s v dai seama, acest registru este important pentru noi din 3 motive : 1. Ne permite alegerea tensiunii de referin, 2. Putem, prin acest registru, s conotrolm modul n care informaia este plasat pe registrele de date ADCH - ADCL i 3. Tot prin acest registru se poate selecta sursa tensiunii de convertit. Tot aici merit s amintim faptul c datorit construciei plcuei, exemplele noastre vor folosi doar tensiuni de referin interne. Opiuni care folosesc surse externe necesit circuite electrice n plus fa de cele ce se gsesc pe plcu. Noi avem 2 valori de referin ceea ce este mai mult dect suficient pentru a nva s lucrm cu modulul. Dup ADMUX urmeaz 2 registre de control prin care putem porni/opri/configura n plus modulul. Unul dintre aceste registre este ADCSRA. ADCSRA este situat la adresa 0x0006 i are urmtoarea componen: Rang Notaie Op. permise Val. iniial
7 6 5 4 3 2 1 0

ADEN

ADSC

ADATE

ADIF

ADIE

ADPS2

ADPS1

ADPS0

S/C 0

S/C 0

S/C 0

S/C 0

S/C 0

S/C 0

S/C 0

S/C 0

, iar biii au urmtoarea semnificaie :

165

Denumire ADEN

Nume complet Activeaz modulul CAD

Semnificaie 1 logic activeaz modulul convertorului, iar 0 logic l dezactiveaz. Prin activare nelegem punerea lui sub tensiune, dar nu i pornirea explicit a convertorului. Un 1 logic pornete conversia, iar o citire ulterioar a lui va rezulta valoarea 1 att timp ct conversia este n desfurare. Dup ce rezultatul este disponibil n registrul de date (ADCH ADCL), acest bit automat trece pe valoarea 0. Scrierea unui 1 logic va face ca modulul s funcioneze continuu, extrgnd valori binare i plasndu-le n registrele de date de ndat ce ele au fost citite (vezi discuia de mai sus) Acest bit se seteaz automat atunci cnd o conversie s-a ncheiat. El este folosit de sistemul de ntreruperi pentru a genera o ntrerupere a modulului CAD. Bitul se terge automat atunci cnd subrutina ntreruperii s-a ncheiat sau, manual, prin scrierea unui 1 pe aceast poziie.

ADSC

Pornete conversia CAD-ului

ADATE

Activarea autodeclanrii conversiei Marcaj pentru ntrerupere

ADIF

ADIE

Activarea ntreruperii de Un 1 logic d posibilitatea ca modulul s CAD genereze o ntrerupere atunci cnd rezultatul unei conversii este disponibil, iar un 0 logic anuleaz aceast capacitate. Grup de selectare a factorului CAD Aceast secven de bii selecteaz factorul modulului. Este vorba desore acea valoare care mrete baza de timp a sistemului nainte de a ptrunde n CAD i a-l controla. Valorile i semnificaiile acestui grup se pot observa din tabelul urmtor : ADPS[2:0] 000 001 010 011 100 101 110 111 Factor rezultat 2 2 4 8 16 32 64 128

ADPS2 ADPS0

Ce trebuie s reinem noi din acest registru sunt urmtoarele aspecte :

166

Modulul i are factorul su care controleaz viteza de conversie. n general, rezultatul unei operaii de CAD este disponibil la 13 baze de timp, excepie o face prima conversie care este disponibil dup 25 de astfel de baze de timp. Convertorul are capacitatea de a genera ntreruperi care atrag atenia atunci cnd un nou rezultat este disponibil Activarea modulului este un lucru separat de pornirea lui CAD-ul suport posibilitatea de a se reporni ori de cte ori un rezultat a fost produs, iar momentul de repornire este dat de o grupare de bii a celuilalt registru de control al modulului : ADCSRB

ADCSRB se poate gsi la adresa 0x0003 n spaiul regitrilor de control i are urmtoarea form : Rang Notaie Op. permise Val. iniial
7 6 5 4 3 2 1 0

BIN

ACME

IPR

---

---

ADTS2

ADTS1

ADTS0

S/C 0

S/C 0

S/C 0

C 0

C 0

S/C 0

S/C 0

S/C 0

, cu urmtoarea structur : Denumire BIN Nume complet Activeaz intrare cu semn Semnificaie Funcionalitate special prin care ntiinm modulul de CAD c urmeaz s aproximeze o valoarea binar pentru o valoare real cu semn. 1 logic indic o conversie cu semn pe cnd un 0 logic arat generarea unor valori fr semn. Are efect doar cnd nu folosim CAD-ul (ADEN din ADSCSRA pus pe 0). Asigur un comportament complex, nediscutat n lucrarea din faa dumneavoastr. Funcioneaz mpreun cu bitul BIN pentru a spune ce semnal este negativ i care este pozitiv. Cum aceste noiuni sunt relative, putem considera c -1.7V prezeni pe un canal surs poate s controleze o valoare binar negativ sau pozitiv n funcie de acest bit IPR. IPR pus pe 0 nu inverseaz semnul pe cnd o valoare de 1 inverseaz semnul. Aceti bii nu au nicio importan electric pentru circuit i se vor citi mereu cu valoarea zero. Aceast grupare are efect doar dac bitul ADATE din ADCSRA are valoarea 1 (autodeclanare activ). Practic, aceti bii selecteaz cine s genereze urmtoarea cerere de conversie. Opiunile disponibile sunt dup cum urmeaz :

ACME

Activeaz selecia comparatorului

IPR

Activeaz inversarea semnului

--ADTS2 ADTS0

Nesemnificativ Selecteaz sursa de declanare a CAD-ului

167

Denumire

Nume complet

Semnificaie ADTS[2:0] 000 001 Sursa declanrii


Imediat dup rezultat Comparatorul analogic (funcionalitate nou pentru noi, nediscutat n aceast crulie) ntrerupere extern venit pe un pin extern La generarea ntreruperii de echivalen TCNT0 - OCR0A La generarea ntreruperii de depire a valorii ceasului0 La generarea ntreruperii de egalitate TCNT0 - OCR0B La modificarea exterioar a strii unui pin

010 011 100 101 110

Registrul prezint interes pentru noi n mod special prin gruparea ADTS[2:0] prin care putem selecta momentul iniializrii unei noi conversii atunci cnd modulul funcionez n mod continuu. Neatingndu-ne de acest registru i lsnd gruparea pe valorea sa iniial 000 practic spunem modulului s nceap o nou conversie de ndat ce s-a produs un rezultat, nemaiateptnd dup nimeni. Dup attea discuii (5 registre explicate nu sunt o cifr mic), cred c un prim exemplu de folosire a CAD-ului este n regul. Fr a sta prea mult pe gnduri, alegem capacitatea modulului de a-i msura temperatura. Haidei s formulm i o cerin de exerciiu n acest sens : Va trebui s realizm o secven de cod care, prin intermediul unei surse de ntreruperi ce se declaneaz n mod periodic (cel sau ceas, dar noi vom alege cel pentru a scrie mai puine instruciuni) afim temperatura intern a creieraului. Dei elementele citirii temperaturii sunt prezentate risipit mai sus, le aducem aici i le completm pentru a le vedea mai bine i pentru a avea o baz de pornire pentru soluia noastr : Citirea temperaturii necesit ca respectiva secven MUX[3:0] din registrul ADMUX s fie setat cu valoarea 1111 selectnd astfel canalul ADC4 unde se afl modulul intern de citire a temperaturii. Modulul intern poate fi selectat i folosit doar cu o tensiune de referin de 1.1V (vezi registrul ADMUX). Pentru a ajunge la valoarea n grade celsius (prescurtat C) a temperaturii citite, va trebui s scdem din rezultatul prezent n ADCH-ADCL valoarea 273. Creatorii creieraului ne spun c modulul temperaturii are o sensibilitate de aproximativ 1 incrementare la 1 C. Asta nseamn c dac pentru 25C vom citi

168

valoarea 298 (273 + 25), atunci pentru 26C va trebui s avem cu unu mai mult : 299 (273 + 26), iar pentru 50C am avea n registrul de date ADCH-ADCL valoarea 323 (273 + 50). Modulul de temperatur poate da valori ce difer fa de cele reale cu pn la 10C. Este ntr-adevr o deviere destul de mare, dar, pentru cultura noastr general, precizm c ea se poate reduce pn la 2-3C. Totui, modalitatea prin care putem atinge o astfel de performan (operaiune numit uneori i calibrare) depete nivelul de cunoine accesate i predate de crulie. Pe lng aceste informaii ce vin de la sursa CAD-ului i a modulului intern de msurare a temperaturii, mai precizm nite valori alese de noi pentru configurarea CAD-ului : Vom folosi un factor de 32 (l-am ales oarecare) cu declanare automat a unei noi conversii de ndat ce avem un nou rezultat. Nu vom folosi ntreruperea modulului CAD. Timpul de 1 secund acordat de generatorul de ntreruperi a celului va fi mai mult dect suficient pentru a obine un rezultat din partea convertorului. i cred c aceste informaii sunt suficiente. Prezentm cei 3 regitrii nc neintrodui n aplicaie: ADMUX = 0x07 ADCSRA = 0x06 ADCSRB = 0x03 Observai v rog cum am introdus i ADCSRB dei noi nu-l vom folosi n exerciiul nostru curent. Am ales s-l introduc pentru a avea gruparea complet de regitri ai modulului n aplicaie. Continum cu secvena de iniializare : initializeaza_perif: ldi R16, 0b01001110 ; activm celul cu generarea ntreruperii la 1 secund out WDTCR, R16 sei ; i activm ntreruperile globale
; selectm termometrul intern ca i surs de valori i o tensiune de referin de 1.1V aa cum ne cere modulul ; ADCL va conine primii bii ai conversiei, iar ADCH pe ultimii 2

ldi R16, 0b10001111 out ADMUX, R16


; activm CAD-ul, setm s se autodeclaneze la obinerea unui nou rezultat i pornim conversia ; nu folosim capacitatea de ntrerupere, dar utilizm un factor de 32, aa cum ne-am vorbit

ldi R16, 0b11100101 out ADCSRA, R16 ldi R16, 0b00000011 ; afior pornit, minitastatura nu out DDRB, R16 ret Numai este o surpriz pentru nimeni faptul c secvena noastr principal arat aa : main: rcall initializeaza_perif executa_vesnic:

169

rjmp executa_vesnic , dar ne ndreptm atenia spre subrutina de tratare a ntreruperii celului unde avem ceva de observat : __vector_12: push R26 push R27
; colectm informaia pus la dispoziie de ctre modulul de temperatur

in R26, ADCL in R27, ADCH sbiw R26, 60 sbiw R26, 60 sbiw R26, 60 sbiw R26, 60 sbiw R26, 33

; scdem 273 conform celor discutate pentru a obine C

; afim temperatura curent a creieraului

mov R16, R26 rcall afiseaza_r16

in R27, WDTCR ; reactivm nteruperea celului ori R27, 0b01000000 out WDTCR, R27 pop R27 pop R26 reti Principiul urmrit este unul simplu : valoarea obinut nu ncape pe 8 bii, ct este dimensiunea unui registru normal aa c folosim registrul extins X (R27:R26) pentru a ine aceast informaie. Apoi scdem 273 ( 604+ 33=240+33=273 , vedei n tabelul de instruciuni suportate limitrile instruciunii SBIW) din valoarea lui X pentru a obine temperatura exprimat n grade celsius pe care o afim. Avnd codul complet, l trimitem spre plcu i observm temperatura creieraului remprosptndu-se o dat la o secund, aa cum dorim. ntr-o zi de var, afiorul arat 3031C, ceea ce nu este departe de adevr. i asta este tot : Ale poate simi temperatura mediului su. Acum luai o surs de cldur (sugerez un usctor de pr) i vedei dac creieraul simte aceast modificare de temperatur. Avei grij dac inei prea mult aerul cald pe plcu s nu v ardei. Merge i dac inem degetul pe carcasa creieraului, dar nclzirea este lent i variaiile sunt mici (temperatura unui corp sntos uman este undeva n jurul valorii de 37C, dar ea este mai redus n degete : poate 35C). n continuare, vom folosi modulul CAD pentru a citi din exterior lumina mediului n care se afl plcua.

170

ntrebri / Exerciii : 1. La o baz de timp a sistemului de 1 s i un factor de 64 ales pentru modulul CAD, calculai dup ct timp obinem prima valoare convertit de la pornirea modulului, dar n cazul unei conversii normale ? 2. Pentru aplicaia de mai sus : de ce nu putem folosi n locul secvenei de instruciuni sbiw R26, 60 sbiw R26, 60 sbiw R26, 60 sbiw R26, 60 sbiw R26, 33 o instruciune condensat de forma sbiw R26, 273 ? Argumentai. 3. De ce credei c scdem 273 din rezultat pentru a obine temperatura n grade celsius i nu alt valoare ? (ntrebarea folosete noiuni de cultur general neexplicate n seciune) 4. Pentru aplicaia de mai sus : eliminai instruciunea in R27, ADCH din subrutina celului i trimitei codul spre plcu. Ce putei spune despre valorile afiate ? Explicai. 5. Pentru aplicaia de mai sus : modificai secvena de cod ce o gsim n subrutina de iniializare : ldi R16, 0b10001111 out ADMUX, R16 cu urmtoarele instruciuni : ldi R16, 0b10101111 out ADMUX, R16 Explicai ce s-a ntmplat i cum afecteaz aceast modificare codul nostru ?

[23s] Lui Ale nu-i trebuie ochelari


Poate seciunea precedent a fost un pic cam lung, dar nu am avut ncotro. CAD-ul este n sine un subiect destul de complex i serios i nc nu am discutat despre tot ce poate el oferi, dar am discutat suficient. Acum vom trece direct la subiect i vom vorbi despre ultimul modul fizic ce ni-l pune la dispoziie plcua pentru a nva (mai un pic i terminm crulia, v vine s credei ?). S ncepem cu problema ce o dorim rezolvat : se va folosi celul cu o generare de ntrerupere periodic de o secund n care vom afia cei mai semnificativi 8 bii ai valorii citite de pe modulul optic. CAD-ul nu va genera ntrerupere, se va auto-declana n mod imediat, i va folosi un factor de 64. nainte de a prezenta soluia, vom discuta un pic despre acest modul fizic pentru a nelege mai bine funcionarea lui. Principiul electric l-am abordat mai n detaliu atunci cnd am vorbit la modul general despre toate modulele plcuei. Esena discuiilor noastre (pe care v

171

sftuiesc s le revizuii dac nu a-i parcurs-o pn acum) este urmtoarea : lumina din mediu modific rezistena fotoelementului care, prin principiul divizorului de tensiune, dicteaz o tensiune de ieire care ajunge s fie dependent de cantitatea de lumin ce cade pe respectiva component. n felul acesta, citind aceast tensiune, putem spune c plcua este contient de cantitatea de lumin ce cade pe suprafaa sa. Tensiunea maxim ce o poate genera modulul foto (aa l vom numi de acum nainte) se apropie de tensiunea de alimentare a creieraului. Valoarea minim nu ne intereseaz deoarece numai valoarea maxim ne dicteaz tensiunea de referin ce trebuie aleas la configurarea CAD-ului. Cu alte cuvinte, pentru modulul foto va trebui s alegem tensiunea de referin egal cu tensiunea de alimentare a Attiny-ului, iar 1.1V nu va fi suficient! Un alt aspect important este canalul prin care creieraul va citi aceast tensiune. Plcua e configurat astfel nct pinul pe care cade aceast tensiune s fie PB3. Prin urmare, canalul de colectare a respectivei valori va fi ADC3. i astfel avem informaiile lips prin care putem rezolva problema noastr. Vom ncepe cu subrutina de iniializare : initializeaza_perif: ldi R16, 0b01001110 ; iniializm celul cu generare de evenimente la fiecare 1 secund out WDTCR, R16 sei
; alegem tensiunea de alimentare a creieraului ca tensiune de referin ; canalul ce va fi citit va fi canalul ADC3 (de pe pinul PB3) ; plasm cei mai semnificativi 8 bii n registrul ADCH i restul de 2 bii n registrul ADCL

ldi R16, 0b00100011 out ADMUX, R16 ldi R16, 0b11100110 out ADCSRA, R16

; activm i pornim CAD-ul cu generare n mod continuu i factor de 64

ldi R16, 0b00000011 ; pornim afiorul, dar nu i minitastatura out DDRB, R16 ret O dat cu iniializarea, o mare parte din problem este rezolvat. Mai avem subrutina principal prin care, dup cum vedei, cam bate vntul : main: rcall initializeaza_perif executa_vesnic: rjmp executa_vesnic , iar cea mai ateptat bucat de cod, subrutina de gestioanre a ntreruperii, se prezint n feulul urmtor : __vector_12: in R16, ADCH rcall afiseaza_r16

172

in R16, WDTCR ; celul este reactivat pentru a genera o nou ntrerupere ori R16, 0b01000000 out WDTCR, R16 reti Avnd n vedere c cei mai semnificativi 8 bii se afl n registrul ADCH (dup cum am iniializat CAD-ul), este suficient numai citirea lui pentru a iniializa un o nou conversie conform celor discutate n seciunea precedent. i asta este tot am spus c o inem scurt, m-am inut de cuvnt ? Dup ce trimitem codul spre plcu, miracol mare! : n funcie de orientarea plcuei i de cantitatea de lumin la care este expus, vom vedea afiorul aprinzndu-se i afind o anumit valoare. Vai dup attea instruciuni, module interne/externe, configuraii i grupri de bii, propun s nchidem seciunea de exemple cu un ultim cntec de lebd sau, mai bine zis, jocule de lebd. Aadar, s ne jucm

ntrebri / Exerciii : 1. Dac cunoatem tensiunea de alimentare a creieraului. Putem calcula cu aproximaie valoarea rezistenei foto-elemetului cunoscnd numai valoarea tensiunii afiate ? Nu cerem neaprat modul n care putem face asta ci doar un rspuns de tipul da/nu. 2. Modificai codul de mai sus pentru a afia cei mai puin semnificativi 8 bii. Ce putei spune despre sensibilitatea valorilor afiate ? Explicai.

[24s] Din nou, napoi de unde am plecat


tii ... o fi frumos afiorul, o fi util minitastatura i ceasurile interne, convertoarele i celul, poate chiar modurile de eficientizare a consumului i memoria special. O fi cu adevrat interesante toate acestea, dar uneori prea mult seriozitate nu face bine la trtcu1. Uneori, dup o lung perioad de efort intelectual sau fizic, cutm un pic de joc. Cutm s ne relaxm neuronii i s lsm lucrurile nvate s se aterne. Acest lucru l facem la toate nivelele fie c suntem tineri sau btrni, fete sau biei, cu toii ne cutm momentul de pauz. Vom face i noi o pauz i ne vom juca, iar pentru a arta c Ale poate fi i distractiv nu numai serioas, o vom folosi pe post de zar electronic (bineneles) pentru a avea cu ce ne juca. Pentru c, nu-i aa? : nimic nu e mai plcut dect un joc creat de noi nine i poate de Ale. Aadar, pentru acest ultim exerciiu, ne vom ntoarce la modulele de baz ale plcuei, ne vom ntoarce la afior i minitastatur i vom uita un pic de restul. Nu vom folosi niciun modul intern n plus, nici mcar un generator de ntreruperi. Vom face asta pentru a v demonstra c orice este posibil atta timp ct exist ideea i bunvoina de a-l duce pn la capt. Partea frumoas este aceea c nu avem neaprat nevoie de lucruri complicate pentru a-l face posibil.
1

sau creier

173

Aadar, fr a v obosi mai mult, s vedem ce ne propunem efectiv : vrem s scrie o secven de cod care s se comporte asemeni unui zar cu 6 fee obinuit. Desigur, valoarea sa va fi redat pe afior innd cont de urmtoarele reguli : valoarea 1 va fi afiat n felul urmtor pe LED-uri : valoarea 2 va avea urmtoarea afiare : valoarea 3 : valoarea 4 : 5: i

6: Pentru a arunca zarul, nu vom arunca plcua ci vom apsa pe butonul D0 pentru a-l agita zarul, iar n urma ridicrii degetului de pe buton, valoarea la care am ajuns se va vedea pe ecran. Aadar, vom folosi doar modulul de intrare/ieire (afior + minitastatur) pentru a face ce neam propus. Pentru afiarea valorii propriu-zise aa cum ne-o cere tiparul de mai sus, vom construi o subrutin. S o numim afiseaza_zar_r18 unde, prin R18 vom transmite subrutinei un numr ntre 0 i 255, iar ea, pe baza acestei valori, va alege zarul ce-l va afia. Pentru asta, intervalul 0,255 va fi mprit n 6 regiuni dup cum urmeaz : pentru R18=0,41 , vom spune i afia valoarea 1 R18=42,84 va alege i afia valoarea 2 pentru zar R18=85,126 pe LED-uri faa cu valoarea 3

Un ultim detaliu nainte de a ncepe codul nostru mult ateptat : ct timp butonul va fi apsat, pentru a construi suspansul valorii finale, pe ecran nu se va afia nimic. Cum vom ataca problema ? ntrebai. Pn acum, dup exemplele prin care am trecut, ar trebui s fie floare la ureche i chiar v sftuiesc s ncercai pe cont propriu o rezolvare. Totui, dac nu o facei din motive de voi tiute, prezentm n continuare o variant. Creionm mai nti paii care vor explica evoluia aplicaiei noastre : 1. Iniializm perifericele (afior i minitastatur) 2. Ateptm ca D0 s fie apsat, iar cnd este apsat 3. curam mai nti LED-urile trimind o valoare ce le foreaz s fie nchise 4. Ct timp butonul este apsat, incrementm continuu R18, dar 5. dup ce butonul nu mai este apsat, apelm subrutina noastr nou afiseaza_zar_r18 i srim la punctul 2 ateptnd o nou aruncare de zar Exist un sentiment de imprevizibil atunci cnd aruncm un zar. Oare ce valoare va iei ? Acest sentiment este greu de meninut pe Attiny-ul nostru i pe orice alt creiera deoarece ele execut instruciuni aa cum le spunem noi s o fac, iar asta nu are nimic imprevizibil. Am putea spune c nu vom reui s obinem niciodat valori imprevizibile cu plcua noastr i c urmrim o cauz pierdut, dar nu este chiar aa. Folosindu-ne de incrementri continuue care se petrec extrem de rapid ntr-o perioad scurt de timp, putem obine acelai efect. Cu alte cuvinte, este foarte greu ca 2 apsri de buton s dureze exact aceai

R18=127,169 R18=170,211 R18=212,255

174

perioad de timp. Nu imposibil, dar extrem de improbabil! Att de improbabil c pn i mainriilor le-ar fi dificil s o fac. Aadar, ncepem codul nostru prin o revizitare a subrutinei noastre de iniializare a modulelor : initializeaza_perif: ldi R16, 0b00010011 ; pornim afiorul i minitastatura out DDRB, R16 ret La ce ne-am propus s realizm nu este de mirare c o descoperim la fel cum am lsat-o atunci cnd discutam prima dat despre butonae. Nimic deosebit aici i continum cu introducerea secvenei principale care mbrac paii descrii mai sus : main: rcall initializeaza_perif executa_vesnic: D0_neapasat: ; stm n aceast subrutin pn cnd simim c D0 este apsat rcall citeste_taste_r17 sbrs R17, 0 rjmp D0_neapasat clr R16 ; tergem ecranul ct timp inem apsat pe D0 pentru a ridica nivelul de suspans rcall afiseaza_r16 D0_apasat: ; incrementm continuu R18 ct timp D0 este apsat inc R18 rcall citeste_taste_r17 sbrc R17, 0 rjmp D0_apasat
; la final, reconstituim i afim valoarea zarului rezultat

rcall afiseaza_zar_r18 rjmp executa_vesnic

Nici aici nu prea avem ce discuta, instruciunile sunt directe, simple i evidente. Ultima bucat de cod introduce subrutina noastr nou afiseaza_zar_r18 pe care o putem construi dup cum urmeaz : afiseaza_zar_r18: push R16
; == Regiune de stabilire a intervalului de apartenen a valorii R18 ==

cpi R18, 42 brlo _zar_val_1 cpi R18, 85 brlo _zar_val_2 cpi R18, 127 brlo _zar_val_3 cpi R18, 170 brlo _zar_val_4

175

cpi R18, 212 brlo _zar_val_5 rjmp _zar_val_6 _zar_val_1: ldi R16, 0b00000001 rjmp _gata_subrut _zar_val_2: ldi R16, 0b00000011 rjmp _gata_subrut _zar_val_3: ldi R16, 0b00000111 rjmp _gata_subrut _zar_val_4: ldi R16, 0b00001111 rjmp _gata_subrut _zar_val_5: ldi R16, 0b00011111 rjmp _gata_subrut _zar_val_6: ldi R16, 0b00111111 _gata_subrut: rcall afiseaza_r16 ; afim valoarea rezultat pop R16 ret Urmrind-o putem uor s identificm cele 2 regiuni importante : 1. de stabilire a intervalului de apartenen a lui R18 dup cum discutarm mai sus i 2. de ncrcare efectiv a valorii zarului n R16 i afiarea ei i zarul nostru este gata. Simplu, dar eficient, nu credei ? La ce este bun un zar dac nu ai la ce s-l foloseti, nu ? n continuare, vom prezenta o serie de jocuri unde am putea utiliza ceea ce tocmai am creat... [Jocul 1] PIG Nu tiu de unde vine numele, dar PIG este un joc cu zaruri att educativ, dar mai ales distractiv.
Aranjamente
; == Regiuni de reconstrucie a valorii zarului ==

Jocul necesit un singur zar i se joac n 2 sau mai muli juctori, iar scopul lui este acela de a ajunge primul la 100 de puncte.

176

Cum se joac

Juctorul care ncepe primul poate fi ales printr-o aruncare de zar. Cel mai mare zar alege primul juctor. Odat ales, participantul ncepe jocul prin a arunca respectivul zar ori de cte ori dorete sau pn obine zarul cu valarea 1. Fiecare zar aruncat i adun valoarea la punctele arunctorului, dar obinerea unui 1 conduce, pe lng pierderea dreptului de a mai arunca odat i la pierderea tuturor punctelor obinute n runda respectiv. Jocul se termin atunci cnd unul din juctori atinge sau depete 100 de puncte.
Puncte tari

Curiozitatea jocului este aceea de a ti cnd s renuni astfel nct punctele obtinute s fie ct mai multe, dar s nu le pierzi prin aruncarea i obinerea unui 1. [Jocul 2] 36 Este de asemenea un joc uor ce se poate juca cu un singur zar i se laud c dezvolt latura matematic a gndirii participanilor.
Aranjamente

Jocul se poate desfura cu 2 sau mai muli juctori utiliznd un singur zar, iar scopul su este acela de a te apropia ct mai mult de valoarea 36, fr a o depi ns.
Cum se joac

Asemeni primului joc, cel ce ncepe poate fi ales de comun acord sau prin aruncarea celui mai mare zar nainte de joc. Odat ales, juctorul are dreptul la 10 aruncri de zar pe care le nsumeaz i urmrete ca valoarea adunat s fie ct mai aproape de 36, dar s nu o depeasc. Participantul poate alege s nu foloseasc toate cele 10 aruncri i s se mulumeasc cu suma sa curent pentru runda respectiv, iar odat depit valoarea de 36, se consider c respectivul concurent a pierdut runda respectiv. Dintre cei ce au sub 36 sau cel 36 de puncte, ctig cel care are valoarea cea mai apropiat de 36 dup care ncepe o nou rund.
Puncte tari

Posibilitatea de a simi cnd s te opreti pentru a nu depi valoarea maxim i totui pentru a ajunge ct mai aproape de ea. Exemplele se ncheie aici prieteni. Avem suficiente jocuri i suficiente probleme rezolvate pentru a vedea i nelege capacitile acestui uimitor circuit ce ni le confer plcua Ale. nainte de a ncheia aceast crulie ns, mai vreau s discutm despre 2 lucruri care, zic eu, v-ar face viaa mai uoar dac Ale va prins n vraja ei i dorii s continuai s nvai aceast uimitoare art a electronicii moderne. Prima i prima dat vom discuta un pic despre limbaj i despre alternative

ntrebri / Exerciii : 1. De ce credei c nu am resetat iniial registrul R18 n aplicaia noastr de mai sus ? 2. n exemplul de mai sus, dei avem subrutina afiseaza_zar_r18 care face ceea ce promite, modul prin care o face, s fim sinceri, nu este cel mai eficient. ncercai s restrngei numrul de instruciuni prezente n subrutin. Orice modificare n aceast direcie este bine venit.

177

3. Modificai aplicaia zarului pentru a include elemente ajuttoare pentru unul din jocurile de mai sus.

O alternativ la ceea ce tim


tii ce m deranjeaz pe mine ? Am parcurs o grmad de explicaii i o mulime de linii de cod i cu ce ne-am ales ? Desigur c plcua face exact ceea ce ne-am propus i ne propunem s facem, dar noi, ca i stpni ai gndirii ei, ce vedem la baza acestui comportament ? Pi, vedem asta :
; == Regiune de definiii de registre ==

SP = 0x3D TIMSK = 0x39 TIFR = 0x38 MCUCR = 0x35 MCUSR = 0x34 TCCR0B = 0x33 TCNT0 = 0x32 TCCR1 = 0x30 OCR1A = 0x2E OCR1C = 0x2D OCR1B = 0x2B OCR0A = 0x29 OCR0B = 0x28 CLKPR = 0x26 WDTCR = 0x21 EEAR = 0x1E EEDR = 0x1D EECR = 0x1C PORTB = 0x18 DDRB = 0x17 PINB = 0x16 ADMUX = 0x07 ADCSRA = 0x06 ADCH = 0x05 ADCL = 0x04 PB4 PB1 PINB2 PB0 = 0x04 = 0x01 = 0x02 = 0x00

; == Regiune de definiii de bii ==

[Acestea sunt toate registrele pe care le-am folosit n exemplele discutate de noi n crulia de fa. La finalul acestei lucrri avei o foaie care sumarizeaz toi aceti regitrii] i asta : intarzie_un_pic: push R27 push R26 push R25

178

ldi R25, 3 _ciclu_intarziere_M: ldi R27, 0xFF ldi R26, 0xFF _ciclu_intarziere: sbiw R26, 1 brne _ciclu_intarziere subi R25, 1 brne _ciclu_intarziere_M pop R25 pop R26 pop R27 ret citeste_taste_r17: cli push R16 cbi PORTB, PB1 cbi PORTB, PB4 nop sbi PORTB, PB4 clr R17 ldi R16, 8 ciclu_citire_taste: lsl R17 sbis PINB, PINB2 ori R17, 0b00000001 cbi PORTB, PB1 nop sbi PORTB, PB1 dec R16 cpi R16, 0 brne ciclu_citire_taste pop R16 sei i uneori asta : .section .text .global main .global __vector_10 .global __vector_11 main: rcall initializeaza_perif ... Nu este de mirare c am decis s nu prezentm programele complete atunci cnd discutam exemplele! Sracii copaci, chiar meritau ei o asemenea soart ? Chiar meritau asemenea

179

cuvinte urte scrise pe hrtia lor ? Evident c nu! i acesta este un alt motiv pentru care multe dintre persoanele interesate de programare abandoneaz: codul acesta este foarte urt! Dei face ceea ce i propune, nu exist nimic la el care s te atrag dect, eventual, o idee ce-i caut naterea i o curiozitate ce trebuie potolit. Putem repara acest lucru pentru c, ai ghicit : avem o alternativ! Avem chiar dou ...

nfrumusearea codului prin includeri externe


Ce nume pompos! Poate suna dificil, dar nu este aa. Includeri externe se refer la posibilitatea de a folosi cod ce se afl prezent n mai multe locaii sau, n cazul nostru, fiiere. S ne gndim un pic : toate exemplele noastre au fost simple i au necesitat, n cel mai ru caz, cteva zeci de linii de instruciuni, dar lucrurile se pot complica extrem de mult. S lum compilatorul prin care transformm liniile de text n instruciuni pe care creieraul le recunoate. Aflai c el are la baz cteva sute de mii bune de astfel de linii de cod. Pi cum poate o persoan care lucreaz la un astfel de proiect s se uite i s neleag o asemenea monstruozitate ? Rspuns: nu poate. i pentru asta programatorii s-au gndit s mpart un proiect n mai multe fiiere. n felul acesta apar o serie de avantaje dintre care amintim : 1. codul scris de ctre programatorul care vrea s-i dezvolte o aplicaie proprie este mult redus, 2. sursa programatorului devine mult mai aerisit stimulnd procesul creativ, iar deplasarea prin ea se face mult mai uor i 3. erorile de dezvoltare a aplicaiei sunt reduse deoarece programatorul nu trebuie s scrie personal subrutinele n cauz i poate chiar s ignore detalii de funcionare ale circuitelor extern. Este suficient s cunoasc modalitatea de apel a subrutinelor (ce valori accept i prin ce regitrii le accept) i totul este rezolvat. i psAle suport aceast facilitate. Putem, de exemplu, s lum subrutinele comune definite de noi n exemplele discutate n crulie i s le punem ntr-un astfel de fiier, iar atunci cnd avem nevoie, doar s le apelm (call-uim) dup necesitate. Mai mult, putem face acelai lucru i cu declaraia de registre! Subrutinele care nu s-au schimbat dealungul exemplelor noastre au fost : Nume afiseaza_r16 intarzie_un_pic Rol Trimite spre afiorul plcuei valoarea ce o gsete la momentul execuiei n registrul general r16. Introduce o intrziere scurt n aplicaie. Nu este influenat de nici un registru general.

citeste_taste_r17 Obine starea butonaelor plcuei i depoziteaz-o n registrul general r17. Ele ar fi ndreptite s apar ntr-un astfel de fiier. Restul subrutinelor folosite, datorit nevoilor particulare de aplicaie, nu pot fi considerate. psAle vine cu acest fiier gata construit. l vei gsi n directorul sursele mele, acolo unde ai instalat aplicaia i el se numete ale.inc. Ca s-l folosii, trebuie s apelai o nou

180

instruciune a limbajului, pe lng .section i .global, intitulat .include. Acum nelegei de unde vine titlul subseciunii! Atunci cnd deschidei o surs nou, ea este automat inclus pentru voi. Pentru a demonstra ct este de uor s scriem cod cu acest nou concept, s urmrim exemplul 6s rescris n aceast idee : .section .text .include ale.inc .global main main: ldi R16, 0b00000011 out DDRB, R16 clr r16 executa_vesnic: rcall afiseaza_r16 inc r16 rcall intarzie_un_pic rjmp executa_vesnic i acesta este TOT codul! Nu mai trebuie s scriem subrutinele pentru funciile afiseaza_r16 i intarzie_un_pic pentru c acestea sunt deja disponibile n fiierul extern ale.inc ncrcat de aplicaia noastr prin acea instruciune .include. Iar dac aceast modalitate nu v satisface, ce a-i zice dac am folosi ceva cu totul NOU? Poate un nou limbaj ? ...

nfrumusearea codului cu ajutorul limbajului C


Credeai c Ale poate fi instruit numai prin limbaj de asamblare ? Exist o mare parte dintre voi care, pe bun drept, li se par dificile aceste instruciuni. Pentru acele persoane, dar i pentru acei ce doresc s mearg mai departe cu plcua, avem o alternativ. Este vorba de un limbaj auxiliar recunoscut de psAle care poart denumirea de limbaj C. Permitei-mi s v dau o arom a ceea ce poate face acest nou limbaj pentru noi. Presupunem c dorim s vedem cum ar putea arta urmtoarea secven de cod : DDRB = 0x17 PORTB = 0x18 PB0 = 0x00 PB1 = 0x01 .section .text .global main main: ldi R16, 0b00000011 out DDRB, R16 ldi R17, 8

181

ciclu_afisare: cbi PORTB, PB1 sbi PORTB, PB0 nop cbi PORTB, PB0 dec R17 cpi R17, 0 brne ciclu_afisare executa_vesnic: rjmp executa_vesnic n C :
/* includem bibilioteca de unde avem acces la toi regitrii creieraului Are un rol asemntor cu instruciunea .include discutat anterior. */

#include <avr/io.h>
/* secvena principal */

int main() { int contor;

/* definim o variabil cu rol de contor folosit in ciclul de tergere a afiajului */

/* iniializm portul B: pinul 1 si 2 vor fi ieiri */

DDRB = 0b00000011;

/* tergem LED-urile trimind 8 secvene de 0 spre el */

for(contor = 0; contor < 8; contor++) { PORTB &= ~(1<<PB1); /* punem pe intrarea de date a lui 74hc164 un 0 logic */ PORTB |= (1<<PB0); /* pulsm linia de ceas a lui 74HC164 pentru a */ PORTB &= ~(1<<PB0); /* ncrca valoarea pinului PB1 pe afiaj */ }
/* ieim i blocm execuia creiearului ntr-un ciclu infinit */

return 1;

} Impresionant, nu gsii ? Nu avem etichete, nu avem declaraii de registre, ciclurile sunt mult mai uor de urmrit i aplicaia mai uoar de neles. Acestea ar fi beneficiile acestui nou limbaj. Desigur c exist i dezavantaje. Unul din acestea ar fi dificultatea de a realiza o analiz de timpi de execuie. Cum tim ct dureaz fiecare instruciune dac nu avem tabel ca cel al intruciunilor de la nceputul cruliei ? La urma urmei, acest limbaj ajunge, ntr-o faz a compilrii sale, s treac prin limbajul de asamblare nainte de a fi mpachetat n octei recunoscui de plcu. Aa funcioneaz toate limbajele. Totui, uneori acest lucru nu conteaz, deci nu putem spune c ntr-adevr este un dezavantaj. Din nefericire, din dorina de a nu mri grosimea cruliei i de a o face neatractiv pentru voi, nu ne vom ocupa de acest limbaj promitor aici. Poate vom gsi resursele i timpul necear s l discutm ntr-o lucrare viitoare. iaa cred c grosimea cruliei a ajuns un pic mai mare dect mi dorisem, dar ce s facem dac au existat attea lucruri interesante de povestit ?

182

Totui, majoritatea exemplelelor prezentate aici i puse la dispoziia dumneavoastr prin intermediul aplicaiei psAle includ i varianta lor n acest limbaj C. Am vrut s facem asta pentru aceia dintre voi crora le place ideea i vor s continue s studieze pe cont propriu acest subiect. Exemplele n C le gsii uor: au denumirea cu c n loc de s. Spre exemplu, dac dorii s vedei codul n C a seciunii [10s] ntrzieri mai bune, cutai pe psAle exemplul cu denumirea [10c] ntrzieri mai bune. Pentru a activa aceast list de exemple consultai indicaiile de folosire ale aplicaiei psAle de la sfrtiul cruliei. Desigur, sursele proprii putei s le scriei n oricare dintre cele 2 limbaje dorii. Sfatul nostru este s alegei unulcunoscut i plcut vou. Pentru cei ce v-ntrebai de ce nu am scris crulia de la bun nceput folosind numai limbajul C, aflai c motivul a fost unul puternic ntemeiat : pur i simplu am considerat c este bine s ncepem cu noiuni mai rudimentare cum sunt cele prezentate de limbajul de asamblare i s ne chinuim un pic s nelegem aceste lucruri la un nivel ct mai apropiat de realitate. Numai aa putem mai apoi s apreciem cu adevrat utilitatea acestui nou limbaj numit C. Gndii-v un pic : dac am fi nceput cu acest limbaj avansat, ai mai fi dori s lucrai n asamblare ? Acum c am bifat i aceast discuie, mai rmne loc de nc una

183

Felicitri! Ai reuit
ai ajuns la final!
Se spune c un drum de 1000 de pai ncepe cu primul, dar voi, dragii mei, ai fcut mult mai mult dect att. Voi ai crescut i-ai neles, iar drumul numai este cel iniial. De ce ? Pentru c ai reuit s parcurgei cunotine ce stau la baza societii moderne. O afirmaie poate ndrznea, dar nu exagerat. Gndii-v cum ar fi lumea noastr dac nu am avea telefoane, dac nu ar exista televizoare, internet, maini electrice, maini auto, aparate de uz casnic i, n general calculatoare ? Desigur, str-strbunicii notri puteau s-i imagineze o astfel de lume pentru c ei triau ntr-o astfel de lume, dar noi noi tremurm cnd se taie curentul electric o or. Am ajuns la un nivel de coexisten om-main nemaintlnit n istoria noastr evolutiv. Nicio alt unealt nu a creat o asemenea legtur cu noi, nici mcar focul, considerat de muli ca fiind primul moment de iluminare a speciei noastre. Tehnologia face parte din noi. De fapt, este att de bine sudat n fibra noastr existenial c muli dintre noi nici nu suntem contieni de existena sa. Dar cine e de condamnat pentru asta ? La urma urmei e greu s-i pui ntrebri despre lucruri care au fost alturi de noi de cnd ne-am nscut. V vine s credei c exist persoane printre noi care nc mai cred c soarele se nvrte n jurul pmntului sau, mai interesant, c pmntul este plat ? Cu toate acestea, aceti oameni sunt fericii, iar scopul lor n via este atins, oricare ar fi acela. Dar mai exist i o alt clas de persoane, fiine asemeni vou care se opresc, se blocheaz pentru un moment i se ntreab : De ce ?. De ce?, ntadevr De ce?. Acetia sunt oamenii, Dumnezeii societii noastre, care construiesc ziua de mine, care mping posibilitile tiinei actuale pe alte lumi. Pentru ei, pentru puinii dintre ei, fericirea nu exist fr adevr, iar adevrul nu exist fr cercetare. Pentru restul, eliberarea adevrului duce evoluia noastr om-main-realitate la un mereu alt nivel. Vreau s cred c tu, dragul meu cititor, nelegi ... Acum, la finalul cruliei, s vedem ce ne-am propus i ce am realizat pentru c nu tot ce neam propus am realiza precum nu tot ce am realizat ne-am i propus. Ceea ce nu este, considerai-o ca i tem de cas. Se poate! Scopul nostru principal a fost nelegerea modului de lucru al acestor mainrii uimitoare numite calculatoare. Pentru asta, am avut o serie de ajutoare crora vreau s le mulumesc : Am avut istoria la-ndemnn :

184

Am avut o maimuic :

i am avut-o pe Ale. Fr istorie nu am fi neles motivul pentru care oamenii au vrut s construiasc aceste mainrii precum i trecutul acestor componente. Istoria e plin de inspiraie, trebuie doar s ne-amintim s n-o uitm. Mulumim istorie! Fr maimuic nu am fi putut ncepe a nelege aceast lume. Mulumim i ie maimuic! Fr Ale, nu am fi avut cum s intrm cu minile i capul pe acest trm i nu am fi avut posibilitatea de a ne vrsa imaginaia pe aceste meleaguri. Fr Ale, aceast crulie ar fi fost una ca oricare alta, dar cu i prin Ale, aceast crticic a devenit, sperm noi, un ndrumtor al creativitii.

Am folosit istoria i maimuica pentru a ne forma nelegerea, de unde, cu ajutorul lui Ale am mers mai departe i am demonstrat lumii i nou c acest domeniu nu este aa de nchis i intimidant pe ct pare. C aceste mainrii nu sunt fcute doar pentru cei cu facultate i c nu numai specialitii i electronitii de prim clas tiu s le foloseasc. Cu Ale am demonstrat c aceste lucruri sunt aici pentru toi, iar posibilitatea de a face o lume mai plcut e o decizie la fel de bun pentru tine, cititorule, precum este i pentru marii cercettori ai vremurilor noastre i laureai ai premiilor Nobel1. Desigur, nu am fcut ui care s se deschid automat cnd trecem prin faa lor, automate de ceai sau programe speciale de maini de splat, dar stai un pic mai par ele aa de greu de vizionat ? Gndii-v pentru un moment cu ceea ce tim am putea face o main de splat care fotografiaz stele, dac dorim. Cine ne poate zice acuma ce mai este posibil i ce nu ? Ce nu poate rezolva o secven de cod bine scris mpreun cu nite componente electrice ?

,dar jocul continu


Pentru cei din gaca lui Ale care vor s fac i alte exerciii cu plcua, avem urmtoarele probleme de antrenament :
un prestigios premiu ce se acord anual persoanelor ce au adus unor domenii ale tiinei precum economie, fizic, etc. contribuii de o foarte mare importan
1

185

Scriei o secven de cod prin care s folosim plcua pentru a juca Ghicii la ce numr m gndesc eu acuma . Regulile jocului sunt simple : un juctor alege un numr de la 1 la 15, iar restul de juctori trebuie s ghiceasc cu cte o propunere pe rnd valoarea respectiv. Dac numrul propus este prea mic, juctorul care a ales numrul spune c este PREA MIC, iar dac este mai mare, juctorul zice c valoarea propus este PREA MARE. Evident, dac valoarea sugerat este corect, atunci propuntorul spune CORECT.

Indiciu : Sugerm ca plcua s fac alegerea n acelai mod prin care am generat valoarea acea imprevizibil de la zar-ul nostru electronic : prin apsarea scurt a unui buton. Plcua va fi cea care mereu se va gndi la numrul secret, iar voi putei s i sugerai o valoare prin apsarea simultan a unor combinaii de taste plus una pentru a ntiina creieraul c numrul prezent pe butoane este cel dorit. S zicem c dorim s-i propunem valoarea 9. Asta se traduce binar prin secvena : 0b00001001. Pentru asta, apsm D0 i D4 pentru a introduce valoarea, iar D7 pentru a face aplicaia s in cont de ea. Creieraul poate rspunde prin una din secvenele: 1. mare dect cea aleas, 2. 3. dac aceeai valoare este mai mic sau dac propunerea este cea corect. Jocul continu pn e descoperit valoarea secret apoi o nou rund poate s nceap. dac, de pild, valoarea introdus este mai

Important : Exerciiul acesta ne arat o posibilitate ce nu am mai discutat-o pn acum : putem trimite lui Ale valori numerice prin minitastatur! inei minte acest lucru cnd creai aplicaiile voastre proprii. Realizarea unei lmpi de veghe prin care intensitatea afiorului s creasc pe msur ce nivelul de lumin din exterior su scade. Lmpile de veghe sunt nite dispozitive folosite n general de copilai crora le este fric de ntuneric. Cele mai simple sunt nite beculee care se bag n priz i lumineaz suficient ncperea pentru a alunga ntunericul. Acest exerciiu propune s realizm o lamp de veghe automat. Realizai o aplicaie care s nregistreze, la intervale alese ct i permite memoria EEPROM, temperatura din jurul plcuei pe o perioad de 24 de ore i apoi vizualizai aceste valori cu psAle. Vrei mai mult? Dup aceste exerciii, putem trece la un alt nivel de aplicaii... n acest sens, exist 2 posibiliti: 1. Dup cum ai vzut, creieraul se poate extrage fizic de pe plcua suport dup ce l-am programat. Pentru asta, trebuie s avem mare grij s nu-i ndoim picioruele care sunt destul de fragile. Astfel, i acum vine un lucru foarte important : putem folosi Attiny-ul i n comanda altor circuite create de noi. S vedem un mic exemplu. Considerm urmtorul cod pe care-l trimitem spre creiera : main: ldi R16, 0b00000001 ; setm pinul PB0 ca i ieire out DDRB, R16 ciclu_inifinit:

186

; trimitem 1 logic pe PB0, ateptm un pic i trimitem 0 ogic pe respectivul pin

sbi PORTB, 0 rcall intarzie_un_pic cbi PORTB, 0 rcall intarzie_un_pic rjmp ciclu_infinit ; apoi repetm operaia la nesfrit

Dup aceasta extragem creieraul de pe plcu i-l montm n urmtorul circuit :

Ce credei c vom observa atunci cnd vom alimenta circuitul? Exact! LED-ul conectat prin rezisten (una de 330 de Ohmi este n regul) la pinul PB0 va ncepe s plpie conform codului nostru. i asta o va face, pe cont propriu, departe de modulele lui Ale! Vrem alt aplicaie sau , n cazul nostru, alt vitez de plpire ? Lum creieraul, l plasm pe plcu, rescriem i trimitem codul apoi scoatem creieraul i-l punem n circuitul nostru i gata nimic mai simplu! Acum putem folosi puterea creieraului nostru (mpreun cu modulele sale interne!) n comanda altor circuite electrice construite, de ce nu ?, chiar de noi! n felul acesta am putea folosi chiar restul de faciliti ale modulelor interne nediscutate de noi pe plcu din lips de echipament electric. Unul din aceste module interne extrem de important a lui Attiny25 este modulul de comunicaii. Prin acesta putem conecta mai multe creierae ntre ele, fcndu-le s comunice ntre ele, adic s schimbe informaii unul cu altul. Ba mai mult: cu ajutorul ctorva componente, putem chiar face un creiera s comunice cu un calculator normal (pentru mai multe detalii vedei circuitul integrat MAX232). Posibilitile sunt nelimitate i doar imaginaia i resursele ne sunt limite ... 2. O alt direcie de folosire a plcuei este acea de programator individual. Cu alte cuvinte, putei folosi plcua pe post de programator pentru alte tipuri de creierae! Prin programator nelegem un circuit prin care putem ncrca aplicaii pe creiera. Aceasta este o facilitate deosebit de interesant dac ajungei la un punct n care nelegei mai bine limitrile lui Attiny25 i avei alte versiuni de creierae care sunt mai performante sau care se potrivesc mai bine cerinelor aplicaiei dumneavoastr. Pentru asta putei utiliza componenta care ine creieraul implicit (se mai numete soclu) pentru a realiza legturile electrice precum i aplicaia avr-gcc pentru a traduce codul n limbajul creieraului dorit i avrdude pentru a trimite rezultatul pe creiera. Ambele aplicaii se instaleaz automat atunci cnd instalai psAle. Pentru a v uura analiza, prezentm n imaginea ce urmeaz, diagrama de semnale ce o putem folosi de pe soclul plcuei :

187

Totui, pentru aceste aplicaii precum i altele propuse de persoane inteligente i interesate asemeni vou, v ateptm cu braele deschise s le discutm n comunitatea online ce ncercm s o construim i pe care o gsii la urmtoarea adres :

www.tuscale.ro V ateptm pentru preri i v mulumim pentru atenie. Spor prieteni, Autorul

188

Extensii de coninut
1) Instruciuni de instalare a aplicaiei psAle
ncepem seria de extensii de coninut printr-o seciune care ne arat cum s instalm pachetul psAle pe calculatorul nostru personal. Toate instruciunile prezente aici se refer la sistemele de operare Windows (cel puin de la versiunea Windows 2000). Dac dorii s instalai aplicaia pe alte sisteme de operare i ntmpinai dificulti, v invitm n comunitate pentru a le discuta i a cuta eventuale soluii. Aadar, s o lum cu nceputul. Prima i prima dat trebuie s introducem CD-ul aplicaiei n calculator. Nu conectai deocamdat plcua! Odat introdus, dac avei Windows7, probabil vei vedea un formular n care vi se va cere dreptul de execuie :

Rspundei simplu cu Yes. Pentru celelalte sisteme de operare probabil nu vei vedea niciun astfel de mesaj. Dac totui v apare ceva legat de drepturi de acces sau de instalare, sau chiar aciuni din partea aplicaiei dumneavoastr de antivirus, putei s le confirmai cu ncredere tiind c aplicaia vine din mediul de dezvoltare tuScale. Mai exist i posibilitatea ca odat introdus, s nu se ntmple nimic. Dac aceasta v este situaia atunci intrai manual n CD-ul aplicaiei din My Computer i, eventual, deschidei manual aplicaia instalator.exe.

Dup aceast etap de confirmri, vei vedea pentru cteva secunde emblema comunitii mpreun cu adresa sa i crezul su. La scurt timp, aceasta va disprea i vom vedea urmtorul formular.

Apoi vei vedea ceea ce vrea s fie licena de distribuie a aplicaiei. V ndemnm s o citii ca pe o lectur uoar, ea nefiind nici greu de neles, nici lung. Cnd suntei gata, apsai butonul De acord.

189

Formularul urmtor v permite s alegei componentele pe care le dorii instalate. Dac aceasta este prima instalare a dumneavoastr a unei aplicaii, atunci lsai-le pe toate bifate. Debifai doar dac nelegei ce facei! n partea stng jos se poate observa spaiul necesar pentru instalare n cazul n care toate opiunile sunt selectate. Acesta este cazul care ocup cea mai mult memorie. Compilatorul WinAvr necesit cel mai mult n aceast instalare (mai mult de 250 MegaOctei).

Urmtorul formular v permite s alegei locaia de instalare a aplicaiei. De cele mai multe ori, nu vei dori s schimbai aceast adres, dar dac vrei, de aici o putei face. Dup ce trecem de acest formular (un click pe butonul Instaleaz), instalarea aplicaiei poate s nceap.

Vom vedea apoi urmtorul mesaj :

Acum este momentul s conectai plcua!


n funcie de sistemul dumneavoastr de operare, s-ar putea s se ntmple mai multe lucruri. Noi prezentm aici doar comportamentul ntlnit la Windows Xp i Windows 7, dar discutm un pic i comportamentul general n alte situaii.

190

Aadar, ambele sisteme de operare vor gsi plcua, dar n mod normal, nu vor putea s gseasc modalitatea prin care s comunice cu ea lipsndu-i, ceea ce se numesc, driverele asociate legturii dintre mediul fizic (componente electronice) i cel virtual (software-ul sau aplicaiile).

Windows 7 va declana n zona de lng ceas urmtorul mesaj :

, iar Windows Xp :

Aciunea corect ce o vom aborda n aceste situaii va fi aceea de a ignora balonul textului din Windows 7. Realiznd acest lucru, cutarea de driver va eua cu urmtoarea imagine :

Nu v facei griji, este un comportament ateptat i normal! Windows Xp, pe de alt parte, va merge mai departe i va deschide un formular propriu :

Pur i simplu dai click pe Cancel. (Este foarte important s nchidei acest formular altfel instalarea driverelor va eua!) Ideea general a acestei etape este s avei plcua conectat la calculator aa cum ne indic i mesajul instalatorului. Indiferent de ce sistem de operare avei, asigurai-v c

191

aceast legtur exist i nchidei orice formular v deschide sistemul de operare ca urmare a acestei conexiuni. Dup ce totul este n regul, putei da click pe Ok de pe mesajul instalatorului. Imediat dup aceea, instalarea va ncepe cu configurarea plcuei. Windows 7 (probabil i Windows Vista) va afia un mesaj asemntor cu urmtorul :

Dai click cu ncredere pe butonul Install this driver software anyway, moment n care formularul se va nchide i driverele se vor instala. n mod normal nu vei gsi astfel de mesaje pe versiuni mai vechi de Windows. Dup drivere urmeaz, n funcie de seleciile proprii, s fie transferate fiierele fizice ale aplicaiei. S-ar putea s dureze un pic aceast etap, dar tii cum se zice: rbdarea este o virtute!

Cu toate acestea, totul este bine cnd se termin cu bine, nu-i aa ? : Ajungnd n acest punct, putei cu ncredere s nchidei formularul i s verificai aplicaia.

Aceast verificare se poate face uor dac ai avut selectat opiunea Creeaz legturi, aciune ce permite ca att pe ecranul dumneavoastr, dar i la regiunea de Start a brii Windows-ului, s apar att iconia de lansare a aplicaiei psAle :

192

ct i alte legturi utile :

Cu acestea fiind spuse, considerm c avem aplicaia psAle instalat cu succes i c putem s o deschidem. De acest aspect ne vom ocupa n seciunea urmtoare ...

2) Instruciuni de folosire a aplicaiei psAle


Prima dat cnd lansai n execuie programul psAle vei vedea un mesaj asemntor celui de mai jos :

Formularul v cere un rspuns asupra modului de realizare a actualizrilor pachetului. Opiunile sunt clare i bine explicate chiar n mesaj aa c nu le mai discutm aici. V sftuim s alegei o actualizare automat pentru a v scuti de a alte click-uri ulterioare. Totui, opiunea este a voastr de luat. Dac dorii o aciune manual, vom vedea ntr-o clip cum se poate realiza aceasta.

Mergnd mai departe, vom vedea formularul principal al aplicaiei :

193

Aici ne sunt prezentate opiunile principale de care dispunem. nainte de a le discuta pe fiecare n parte, precizm c putei da click pe logo-ul prezent, aciune ce va deschide pagina comunitii tuScale. n afar de acest aspect, formularul suport urmtoarele aciuni : 1. Posibilitatea de a lucra la surse proprii att n limbaj cunoscut main (de asamblare : ASM) ct i n limbajul C. Pentru asta, facei click pe Hai la programare ... i pornii de acolo.

2. Capacitatea de a deschide exemplele discutate n crulie prin derularea listei opiunii Cod din crulie .... Odat selectat, vei putea vedea i selecta toate secvenele de cod prezentate. Unele seciuni au chiar mai multe astfel de exemple. Fiecare surs din aceast list este alctuit dintr-un text dispus pe dou coloane : prima coloan, cea din stnga, arat seciunea de carte de unde aparine codul, iar cealalt coloan afieaz o denumire mai prietenoas a exemplului n cauz.

3. Opiunea urmtoare, Viziteaz crulia, v permite navigarea coninutului cruliei, n format electronic, direct de pe calculatorul personal. Vizualizatorul este unul simplu n care navigarea se face fie prin rotia mouse-ului, fie prin butoanele ce sunt situate de-o parte i de alta a paginii sau, de pe tastatur, prin sgeata stng i dreapt respectiv. Desigur c aici discutm despre butoanele din acest bloc al tastaturii :

194

Dac nu v place dimensiunea caracterelor sau a paginii n general avei posibilitatea de a o mri innd apsat tasta Ctrl i acionnd rotia mouseului : n fa mrete imaginea pe cnd n spate o micoreaz. n versiunea actual nu exist opiunea de a sri la o pagin anume, dar exist posibiltiatea de a sri la cuprins printr-un simplu click dat pe pictogramele situate n fiecare col a fiecrei pagini. Odat ajuns la cuprins, putei da click pe o seciune de interes, aciune ce v va transporta direct la informaia pe care o cutai. Vedei voi, vizualizatorul este unul extrem de minimal, dar funcional. Noi nu am urmrit niciodat s facem un navigator comercial de astfel de documente. inei cont de acest aspect atunci cnd ne criticai (ceea ce chiar v invitm s o facei!). Dac totui nu suportai acest formular, putei deschide manual crulia cu un alt vizualizator extern. Ea este depozitat n format PDF i se gsete n directorul de instalare a aplicaiei. O vei gsi, nu avei cum s o ratai! Pentru a deschide vizualizatorul fr a da click pe Viziteaz crulia, nu trebuie dect s apsai combinaia de taste Ctrl + V1, iar efectul este acelai. Am introdus aceast opiune n mai multe regiuni ale aplicaiei pentru cei care se descurc mai repede cu tastatura dect cu deja clasicul oricel (numit i mouse). 4. Un click pe opiunea Ce avem aici? i se va deschide formularul urmtor. El prezint att informaii generale ce in de autor, versiunea curent, licen (click pe imagine pentru a vedea efectul ) i un scurt mesaj de ntmpinare, dar i opiunea de a cere o actualizare manual. Aceast opiune este dat, evident, de butonul Actualizeaz.

Ctrl + V precizeaz c trebuie s apsm simultan (sau deodat/concomitent) att tasta Ctrl ct i butonul V de pe tastatur. Aadar, simbolul + l traducem prin simultan.
1

195

Tot aici sunt prezente urmtoarele scurtturi : Ctrl + R : Declaneaz o actualizare i Esc : Prsete formularul de informaii. Mai ne rmne de discutat doar opiunea Gata, am ieit! la acest formular principal. Ghicii ce face aceasta ? Tasta sa scurt este Ctrl + P. Chiar dac formularul principal este cel pe care-l vedei prima dat cnd pornii aplicaia psAle, mai mult ca sigur c nu vei sta mult pe acesta. Avnd crulia n format fizic (pe hrtie) probabil c nu vei sta mult nici pe vizualizatorul cruliei electronice. Mai mult ca sigur c vei dori s facei lucruri practice. Asta nseamn c vei dori s scriei instruciuni. n continuare vom discuta cel mai important formular al aplicaiei. Este vorba despre formularul de cod. Acesta se poate deschide din formularul principal fie prin opiunea Hai la programare ..., fie prin lista dat de opiunea Cod din crulie .... Exist mici diferene dintre cele dou moduri de construire a formularului. Considernd c ai luat pachetul pentru a nva, s vedem ce se ntmpl dac deschidem un exemplu din crulie. Am ales exemplul Ale, mai ncet! i am fost ntmpinai de urmtorul formular :

196

Putem s mprim ceea ce vedem n 3 regiuni : 1. Exist codul propriu-zis, colorat frumos i cu rnduri numerotate pentru o navigare mai uoar, 2. Exist o regiune de butoane pe care le vom discuta imediat, n dreapta i 3. Exist o bar de stare, sub regiunea de cod, care prezint informaii privind starea conexiunii cu plcua, tipul sursei curente (SM : surs proprie, iar EX : surs din exemplu), denumirea sursei i, dup caz, dac sau nu sursa a suportat modificri care nu sunt nc salvate. Dac aciunea regiunii 1 i 3 este evident, nu acelai lucru l putem spune despre regiunea 2. Aici avem expuse toate opiunile utile ce se pot face n acest fomular. nainte de a vedea care sunt acestea, precizm c aceast seciune poate fi fie ascuns, pentru a mri spaiul de lucru, fie afiat, pentru a putea lucra cu butoanele n sine. Totul se realizeaz printr-un click pe butonul vertical ce desparte regiunea butoanelor de cea de cod. S revenim la butoanele verticale. Le vom lua i explica de sus n jos. Primul buton este ncarc pe Ale. Prin acest buton, dac sursele scrise sunt corecte (nu conin erori gramaticale de exemplu) i plcuta este conectat, atunci codul se traduce automat n limbajul plcuei i apoi este ncrcat pe aceasta. Dac plcua nu este conectat, lucru ce se poate citi din bara de stare, atunci codul nu mai este transmis. Pe de alt parte, dac exist greeli n codul surs scris, atunci ele apar marcate deasupra formularului de cod n felul urmtor :

197

Observai v rog cum indicaiile sunt n limba romn. Mesajele compilatorul sunt n limba englez, dar noi am ncercat s le traducem n limba noastr natal pentru a le putea nelege mai uor. Desigur c nu le avem pe toate traduse, dar avei rbdare, vom ajunge i acolo . Pentru a ajunge la linia cu problema indicat, este suficient s dai click pe numrul liniei din indicaii i cursorul va merge automat acolo. Apoi nu v rmne dect s corectai problema i s rencercai trimiterea. nainte de a ncheia discutia despre acest buton, precizm c tasta scurt asociat lui este : Ctrl + T. Urmtoarele dou butoane, Salveaz lucrul i Deschide cod, permit depozitarea respectiv reluarea unui cod personal scris. n felul acesta, dac lucrm la aplicaii complicate, putem salva, face o pauz i reveni la lucru cu fore proaspete. Aceaste opiuni lucreaz cu fiiere, deci va trebui s lucrai cu denumiri de fiiere. V sftuim, pe ct se poate, alegerea unor nume scurte, dar sugestive pentru aplicaiile voastre. Tastele scurte pentru aceste dou butoane sunt urmtoarele: Ctrl + D pentru a salva n fiier, iar Ctrl + R pentru a relua codul din fiier. Pe lng aceste scurtturi, mai exist i combinaia Ctrl + S care, odat deschis sau salvat un fiier propriu, actualizeaz acest fiier cu noile modificri aduse codului fr a mai aduce n prim-plan dialogul cu locaia de salvarea a fiierului. Aciunea este deosebit de util dac dorim numai salvarea actualizrilor n acelai fiier surs i nu ntr-un fiier surs nou. Urmtoarea opiune, Aciuni EEPROM, declaneaz la rndul su un formular de aciuni speciale ale memoriei EEPROM :

198

Aici avem posibilitatea de a vizualiza i interaciona cu memoria special a microcontrollerului. Valorile sunt exprimate n baza 16 (hexazecimal) i sunt dispuse cte 16 pe linie. Dac dorii s aflai rapid adresa unei anumite celule, nu trebuie dect s mergei cu mouse-ul deasupra respectivei celule, i un mesaj scurt v va informa. Dac dorii s modificai o anumit celul, dai dublu-click i introducei o valoare hexazecimal corect, apoi apsai tasta Enter pentru a fi luat n calcul de ctre aplicaie. Starea curent a memorie ajunge pe microcontroller printr-un click pe butonul Scrie EEPROM (avnd taste scurte : Ctrl + S), iar citite prin butonul Citete EEPROM (Ctrl + C). Formularul EEPROM se nchide prin butonul nchide formular sau prin tasta scurt Esc. La rndul su, formularul de cod se nchide fie printr-un click pe butonul Prsete formular sau prin combinaia de taste Ctrl + P. Dac la momentul nchiderii formularului avei modificri ale codului nesalvate, aplicaia v va ntreaba, printr-un dialog scurt, dac dorii s prsii formularul de cod n aceste condiii. Facem lucrul acesta pentru a evita pierderea sursei printr-o nchidere nedorit a codului. i cam asta este tot ce am avut de spus legat de psAle. Ar mai fi de discutat modalitatea prin care avem acces la exemplele C ale cruliei. Nu este nimic secret, dar v lsm pe voi s v jucai un pic i s aflai. Spunem doar att : exist o combinaie de taste care schimb exemplele ASM n exemple C, iar fiecare buton i prezint, dac mergem cu mouse-ul i stm un pic deasupra sa, informaii att despre aciunea sa, ct i despre eventualele scurtturi folosite.

199

3) Rspunsuri posibile la problemele propuse


Ce tiu calculatoarele s fac ?

1. Una din variantele construirii unui SAU NEGAT const n alturarea a 2 pori : un SAU i
un COMPLEMENT LOGIC n felul urmtor :

Soluia o putem demonstra ca fiind una corect ncercnd toate combinaiile logice posibile la intrare i verificnd ieirea circuitului. Mai nti precizm c o poart de tip SAU NEGAT are caracteristicile INVERSE celei unei pori simple SAU : Bit intrare 1 Bit intrare 2 0 0 1 0 1 0 SAU SAU NEGAT logic logic 0 1 1 1 0 0

1 1 1 0 Observm imediat c acest comportament inversat este exact cel obinut de o poart COMPLEMENT.

2. Circuitul

inverseaz de 2 ori o valoare logic aplicat la intrarea sa astfel nct, la ieire s avem exact semnalul logic prezent la intrare. Poate v ntrebai ce utilitate ar avea un astfel de circuit care nu face dect s repete un semnal logic ntr-o schem electric ? Ei bine, aflai c exist unele caracteristici ce-l fac deosebit de interesant. Amintim aici doar una dintre ele : datorit faptului c circuitele electrice nu sunt perfecte, ieirea sa nu rspunde imediat ca urmare a aplicrii unei valori logice la intrare. Aceast tranziie dureaz timp, iar unele circuite electrice au nevoie de aceast ntrziere. Aadar, o astfel de configuraie nu ar fi aa de inutil pe ct s-ar credea iniial.

[1s] Ale, f nimic!

1. Nu. Putei s scriei instruciuni fie cu litere mari, fie cu litere mici sau chiar combinat : i
cu litere mari i cu litere mici. Compilatorul psAle nu va comenta nimic n acest sens, dimensiunea literelor necontnd. Exist o excepie totui : etichetele. Acestea trebuie invocate cu acelai nume i mrime de caractere folosit atunci cnd ele au fost definite. Cu alte cuvinte, urmtoarea bucat de cod are 2 etichete diferite : eticheta1 i EtiChetA1 : eticheta1 : EtiChetA1 : ...

200

2. Nu, aceast bucat de cod nu va putea fi tradus ntr-un limbaj cunoscut de plcu.
Motivul este unul legat de cum a fost gndit compilatorul : instruciunea .global trebuie s aib ca argument o etichet main, altfel compilarea sursei nu poate avea loc. A doua i a treia ntrebare nu i mai au rspuns n acest context.

[2s] Iniializarea registrelor generale pe Ale

1. S urmrim execuia secvenei de instruciuni : ldi R15, 4 ncarc n registrul general


R15 valoarea 4 aa cum ldi R16, 5 depoziteaz n R16 valoarea 5. Dac considerm c bitul C din SREG este 0 atunci ror R15 va deplasa spre dreapta valoarea registrului R15 cu o poziie, iar rezultatul (2 n acest caz) va rmne n R15. Apoi add R16, R15 face ca R16 s fie ncrcat cu suma dintre vechiul R16 i R15 adic R16=5+ 2=7 .rol R16 va roti registrul R16 o poziie spre stnga cu bitul C din SREG depozitat n noua poziie liber a bitului 0 din R16. Rezultatul cestei operaii este 0b000011011=0b00011010=14 . Ultima operaie, subi R16, 1, scade din aceast valoare 1 rezultnd o valoare final 141=13 n registrul R16.

[3s] Ale ne salut

1. Aa cum reiese din seciune, cei 2 regitrii sunt registrul de direcie DDRB i registrul de
date PORTB. 2. Prin prezena a 2 intrri pe acest circuit, proiectanii si au dorit s permit utilizatorilor s-l foloseasc n ct mai multe aplicaii posibile. 3. O astfel de secven ar putea fi urmtoarea :
; [instruciunile precedente rmn nemodificate] ; trimitem spre ieirea portului B, valoarea ce se afl n registrul R16

out PORTB, R16


; verificm dac bitul cu indice 7 din R17 are valoarea 1 ; dac da, sari peste instruciunea 'rjmp bitul_7_este_0' i trimite pe pinul de date a lui 74HC165 ; valoarea de 1 logic. Dac nu, trimite un 0 logic pe acelai terminal

sbrs R16, 7 rjmp bitul_7_este_0

bitul_7_este_1: sbi PORTB, PB1 rjmp impinge_pb1_pe_afisor bitul_7_este_0: cbi PORTB, PB1 impinge_pb1_pe_afisor:
; trecem linia de tact a creieraului pe 1 pentru ncrca valoarea din PB1 n Q0

sbi PORTB, PB0


; aducem linia de tact la 0 pentru a-i menine starea iniial

cbi PORTB, PB0

executa_vesnic: rjmp executa_vesnic ; bucl infinit

201

4. Da, va funciona. Motivul : imediat dup ce trimitem codul spre plcu, terminalul de ceas
primete valoarea 0 astfel nct este suficient instruciunea sbi PORTB, PB0 pentru a ncrca valoarea bitului PB1 pe afior. Nu acelai lucru se poate spune dac facem invers: pstrm cbi PORTB, PB0, dar eliminm sbi PORTB, PB0. Explicaia rmne aceeai.

[4s] Ale ne salut ... mai frumos i mai complet

1. Subrutinele sunt utile pentru c :


ne permit o reutilizare a secvenei de cod fr a o multiplica i permit o urmrire mai uoar a logicii programului. Desigur c acestea nu sunt toate motivele, dar sunt unele dintre cele mai puternice n sprijinul utilizrii subrutinelor. Ca i contraargument, pot exista cazuri cnd o subrutin scris de altcineva, dar utilizat de noi realizeaz ce ne dorim, dar fie nu n totalitate, fie mai face i ceva ce nu ne dorim. n cazul acesta, n funcie de situaie, se poate merge pe o variant de rescriere a respectivei secvene. Aceste probleme pot fi ns evitate cu o gndire serioas a modului de abordare a problemei nc din fazele iniiale ale creionrii soluiei. 2. La ntlnirea secvenei DDRB = 0x17, traductorul nu o traduce n limbajul plcuei ci asociaz intern cuvntul DDRB cu valoarea numeric 0x17. n acest mod, pe msur ce avanseaz in instruciuni i gsete cuvntul DDRB, acesta va fi nlocuit cu adevrata sa valoare 0x17. 3. Pentru aceast problem putem parcurge invers registrul R16 atunci cnd i trimitem biii spre afior. Astfel, o soluie ar putea fi urmtoarea subrutin : afiseaza_r16_inversat: push R17 push R16 ldi R17, 8 ciclu_afisare:
; inspectm bitul cu index 0 n loc de cel de pe poziia 7 pentru c dorim ; o afiare invers pe LED-urile plcuei

sbrc R16, 0 sbi PORTB, PB1 sbrs R16, 0 cbi PORTB, PB1 sbi PORTB, PB0 nop cbi PORTB, PB0
; n loc s rotim spre stnga, rotim spre dreapta registrul pentru a avea acces la ; urmtorul bit pe poziia 0

lsr R16 dec R17 cpi R17, 0 brne ciclu_afisare pop R16 pop R17 ret

202

4. Pentru asta, este suficient s adunm un 5 la R16 nainte de a trimite efectiv valoarea pe
afior. Practic, vom avea urmtoarea modificare a codului :
; [instruciuni precedente]

push R16
; secven de instruciuni a crei singur scop este acela de a aduna ; la valoarea registrului R16, cifra 5

ldi R17, 5 add R16, R17 ldi R17, 8


; [restul de instruciuni]

5. Nu a fost necesar utilizarea instruciunilor de stiv PUSH/POP atunci cnd am scris


subrutina initializeaza_perif pentru c, operaia realizndu-se o singur dat la nceputul fiecrui program, nu exist necesitatea pstrrii i relurii registrelor folosite intern. Pur i simplu ne bazm pe faptul c prima instruciune a main-ului o rerprezint acea iniializare a perifericelor. Dac nu asta ne dorim, atunci o salvare urmat de o restaurare a valorilor regitrilor folosii n subrutin este de dorit. 6. Evident c se poate tri! Oricum se poate tri, dar dac nu am avea instruciunile PUSH/POP ar trebui s gsim un nlocuitor pentru ele din motivul discutat n seciune. 7. Rspunsul la ambele ntrebri se datoreaz instruciunilor prezente n subrutina de afiare. Nu neaprat tipul lor ct numrul lor. Faptul c fiecare instruciune necesit timp s se execute contribuie la durata de 0 logic respectiv 1 logic ce o vedem pe osciloscop.

[4.1s] O dovad c Ale gndete

1. Da se modific. Este normal s se modifice dac ne gndim un pic. Instruciunea ce


trebuie s o eliminm conform exerciiului este rcall initializeaza_perif. Fr aceast iniializare, modulul intern de intrare/ieiren nu mai este configurat bine, iar comunicarea cu modulele externe nu mai este realizat. 2. S simplificm un pic ecuaia iniial 30(5+ x )=8 . Astfel, aceasta este totuna cu a scrie c 5+ x=308=22 . De aici obinem valoarea lui x : x=225=17 . Acum dac lum invers secvena de pai ce i-am realizat i o trecem n limbaj cunoscut de psAle, vom obine urmtoarea soluie :
; R16 = 30 8 = 22

ldi R16, 30 subi R16, 8


; R16 = 22 5 = 17 = 0b00010001

subi R16, 5

; afim rezultatul

rcall afiseaza_r16

3. Creieraul nu cunoate operaiuni de nmulire sau mprire deci o rezolvare direct a


ecuaiei 5x =20 cu instruciunile mai sus menionate nu este posibil.

203

[5s] Ale, mai ncet!

1. nlocuirea instruciunii 'com' cu instruciunea 'swap' are acelai efect pentru valoarea 0x0F
(valoarea registrului R16). Instruciunea 'com' inverseaz valoarea biilor rezultnd noua valoare a lui R16 : com(0x0F)=com(0b00001111)=0b11110000 . Pe de alt parte, instruciunea 'swap' inverseaz cele 2 jumti ale octetului. Astfel, swap (0x0F)=swap(0b00001111 )=0b11110000 care este unul i acelai rezultat cu

com(0x0F) . Dei n cazul valorii 0x0F cele dou instruciuni se comport lafel, aceasta este doar o coinciden. Cum probabil v putei da seama, de cele mai multe ori rezultatele celor dou instruciuni vor fi diferite. 2. Pentru aceast sarcin, este bine dac ne organizm un pic. Observm c subrutina de ntrziere intarzie_un_pic este alctuit din dou bucle interne date de etichetele _ciclu_intarziere_M i _ciclu_intarziere. Vom face o analiz ncepnd din interiorul codului (ciclul cel mai intern, _ciclu_intarziere) i vom merge spre exterior. Astfel, vom putea obine rezultate mai uor de explicat i urmrit. Prin urmare, dac privim tabelul de instruciuni, fiecare comand din zona etichetei _ciclu_intarziere are urmtoarele ntrzieri :
Instruciune _ciclu_intarziere: sbiw R26, 1 brne _ciclu_intarziere # 0 (nu apare n memoria de program) 2 1 (F) i 2 (A)

Desigur, acest ciclu se repet att timp ct bitul 'Z' din registrul SREG nu este 1. Trecerea la valoarea de 1 a acestui bit se face n momentul n care registrul extins R26:R27 atinge valoarea 0. Cum atinge el acest numr ? : prin scderi succesive cu cte o unitate la fiecare execuie a ciclului, adic prin instruciunea 'sbiw'. Pentru a vedea valoarea iniial a registrului R26:R27, putem observa c ambele primesc numrul 0xFF ceea ce, alipite, creeaz valoarea 0xFFFF sau 65535, n sistem zecimal. Pentru o nelegere mai bun asupra unitilor de timp consumate n acest ciclu, propun s facem un experiment mintal i s considerm c valoarea iniial a lui R26:R27 este un numr mult mai mic. S zicem c iniial R26:R27 ncepe cu valoarea 3. Se pune aceeai ntrebare : ci cicli de ceas de sistem dureaz execuia acestei secvene ?
Instruciune Condiii de intrare n ciclu sbiw R26, 1 brne _ciclu_intarziere sbiw R26, 1 brne _ciclu_intarziere sbiw R26, 1 brne _ciclu_intarziere 3 2 2 1 1 0 0 Valoarea lui R26:R27 dup execuie Valoarea bitului Z dup execuie 0 0 0 0 0 1 1 # --- (nu prezint interes pentru analiz) 2 2 2 2 2 1

Dup cum se poate observa din acest tabel, pentru o valoare iniial a registrului R26:R27 de 3, instruciunile se execut fiecare de 3 ori, iar n afar de ultimul 'brne' toate necesit cte 2 uniti de timp fiecare. Asta nseamn c pentru o valoare iniial oarecare a registrului R26:R27, numrul de uniti de timp necesare execuiei ciclului respectiv este dat

204

de relaia

numr de execuii=( 2+2 )(1)+ 2+ 1


sbiw +brne sbiw +brne ultim

. Bineneles c aceast relaie o

putem rescrie mai frumos: numr de execuii=4(1)+3 .Pentru verificare, dac nlocuim -ul cu valoarea aleas 3, atunci obinem c numr de execuii=4(31)+3 , adic numr de execuii=42+3=11 , ceea ce este n conformitate cu realitatea obinut dac adunm separat i numrul de execuii din tabelul de mai sus. Acestea fiind spuse, nou nu ne mai rmne dect s nlocuim -ul cu valoarea adevrat (65535) de unde obinem rezultatul cutat : numr de execuii=465534+ 3=262139 . Attea impulsuri ale ceasului de baz sunt necesare pentru a executa respectivele instruciuni n condiiile noastre. Gata, am terminat cu ciclul mic. S ne concentrm privirea o treapt mai sus i s analizm ciclul _ciclu_intarziere_M. Conform aceluia tabel de instruciuni, unitile de timp necesare instruciunilor sale sunt urmtoarele: Instruciune _ciclu_intarziere_M: ldi R27, 0xFF ldi R26, 0xFF _ciclu_intarziere: ... subi R25, 1 brne _ciclu_intarziere_M # 0 (nu apare n memoria de program) 1 1 262139 1 1 (F) i 2 (A)

Practic, acest ciclu funcioneaz dup acelai principiu ca cel de mai sus, numai c de data acesta folosete registrul simplu R25 pe post de variabil de control pe care o tot decrementeaz pn cnd atinge valoarea 0. La moment respectiv bucla este rupt i ciclul nu se mai repet. Observai v rog cum am nlocuit ciclul intern cu numrul su efectiv de uniti de timp consumate. Datorit faptului c aceast secvent se va executa cu aceeai valoare de pornire a lui R26:R27, el mereu va consuma aceeai cantitate de timp (dac-mi este permis exprimarea). Aici se vede avantajul unei asemeni analize din interior spre exterior. Dac realizm o analiz asemntoare cu cea de mai sus, dar nlocuim numele variabilei cu m pentru a nu creea confuzie, i precizm c m reprezint valoarea variabilei de control R25, obinem c numrul de uniti de timp necesare acestei buci de cod este (1+1+262139+1+2)( m1)+(1+1+262139+1+1)=262144(m1)+262143 . Cu alte cuvinte, dac m-ul este 3, cum este i cazul nostru, atunci numrul unitilor de timp necesare acestei buci de cod este 262144(31)+ 262143=786431 . Mai departe nu ne mai rmne dect s introducem i restul de instruciuni din subrutin n analiza noastr : Instruciune intarzie_un_pic: push R27 # 0 (nu apare n memoria de program) 1

205

Instruciune push R26 push R25 ldi R25, 3 _ciclu_intarziere_M: ... pop R25 pop R26 pop R27

# 1 1 1 786431 1 1 1

Atunci obinem un numr total de uniti de timp consumate de subrutina intarzie_un_pic de 1+1+1+1+786431+ 1+ 1+ 1=786438 . n timp real, considernd c o unitate de timp are aproximativ 1 s , atunci obinem c ntrzierea introdus de aceast unitate este de aproximativ 7864381 s=786438 s=786.438ms=0.786438s . Pentru a demonstra c ntr-adevr aa stau lucrurile i-n realitate, am realizat o captur de osciloscop pe urmtoarea secven de cod : executa_vesnic: cbi PORTB, PB1 rcall intarzie_un_pic sbi PORTB, PB1 rcall intarzie_un_pic rjmp executa_vesnic Iar rezultatul a fost urmtoarea imagine :

Canalul 1 a fost conectat la PB1 pentru a msura efectiv timpul necesar. Realitatea (stnga jos) a scos la iveal un timp de 762ms . Diferena de aproximativ 25ms dintre acesta i cel calculat se datoreaz faptului c, aa cum am vzut n captura seciunii 3s, timpul real a unei uniti de ceas a sistemului nu este exact 1 s . n cazul nostru observm c ea este clar sub aceast valoare. Ca s nu mai amintim faptul c mai apar erori introduse de aparatul msur (osciloscop). Cu toate acestea, putem afirma cu ncredere c valoarea calculat obinut este cea corect. 3. Pentru a realiza aceat subrutin (s o numim intarzie_500ms) este nevoie s studiem exerciiul precedent. Acolo am vzut, pentru valori fixate, ntrzierea rezultat. Acum va trebui s mergem invers. Va trebui s alegem noi valori pentru ambele variabile de control a

206

celor 2 cicle interne (_ciclu_intarziere i _ciclu_intarziere_M) pentru a obine o ntrziere dorit. Pentru aceasta, haidei s ncepem prin a rescrie ecuaia unitilor de timp necesare prin i m. Dac mai inem minte, foloseam pentru a calcula unitile de timp ale ciclului interior _intarzie_un_pic : 4(1)+3 . Vom introduce aceast relaie, aa cum apare ea, n expresia ciclului mai mare _intarzie_un_pic_M : (1+1+4 x (1)+3+1+2)(m1)+(1+1+4 x (1)+3+1+1) care se restrnge la (8+ 4(1))(m1)+(7+4(1)) . Nu v speriai de rezultat, mai avem un pas i terminm. Mai trebuie doar s adugm secvena nconjurtoare lui _ciclu_intarziere_M i avem rezultatul complet: 1+1+1+1+(8+ 4( 1))(m1)+(7+ 4(1))+1+1+1 care se mai poate restrnge un pic la urmtoarea relaie (8+4(1))(m1)+(7+4(1))+7 . Dup attea calcule, se poate ntreba : ce am obinut noi aici ? Ei bine, am obinut numrul total de uniti de timp ale subrutinei intarzie_un_pic ce se pot obine din valori proprii date variabilelor de control din ciclii _ciclu_intarziere i _ciclu_intarziere_M. Cu alte cuvinte, alegnd valori pentru i m, putem, teoretic, s obinem ntrzieri a cror durat o alegem noi. Pentru =65535 i m=3 vom obine valoarea calculat la exerciiul 2 : 786438 sau 786.438ms pentru o unitate de ceas ideal de 1 s . Pentru a obine ntrzierea cerut, este suficient s alegem valori pentru m i i s calculm rezultatul obinut. Dac =497 i m=251 obinem o soluie bun : 499984 sau aproximativ 499.984ms la o durat a ceasului sistem de 1 s . ntr-adevr, i osciloscopul este de aceeai prere cu noi :

n ncheiere, precizm c valoarea fizic a duratei se poate mbunti dac lum n calcul abaterea de la valoarea ideal a ceasului sistemului. Pentru noi ns, rezultatul este suficient de bun pentru a-l considera corect. 4. Motivul pentru care semnalul de date rmne pe 1 logic dup ncheierea subrutinei afiseaza_r16 este datorat att felului n care este construit aceast subrutin ct i de valoarea 0xF0=0b11110000 trimis spre afior. Ultimul bit al acestei secvene fiind 1, acesta rmne configurat pe 1 i dup ncheierea subrutinei.

207

[5.1s] Unde este stiva ?

1. Pentru a rspunde la aceast ntrebare putem s traducem valoarea binar afiat.


Astfel aflm c stiva microcreieraului poate conine pn la 0b11011101=221 octei. 2. Desigur c putem! Avnd adresa octetului care indic vrful stivei, am putea scrie uor o secven de instruciuni care modific aceast valoare. O soluie ar fi urmtorul cod : ldi R16, 0x8F out SP, R16

[6s] Alte 2 exemple interesante cu LED-uri

1. Pn n acest punct am nvat de prezena a dou tipuri de seciuni :


.text : precizeaz c urmeaz memoria programului i .progmem : precizeaz c valorile ce urmeaz vor fi situate n memoria programului 2. Singura modificare ce trebuie adus la cod const n declararea datelor de la adresa_secventa_de_afisat. Astfel, noul cod devine : .section .progmem adresa_secventa_de_afisat: .byte 0b00000000, 0b10000001, 0b11000011, 0b11100111, 0b11111111 .byte 0b01111110, 0b00111100, 0b00011000 Restul de instruciuni, mai puin valoarea de gard cpi R16, 0b00000001 care devine cpi R16, 0b00011000, rmn nemodificate, iar efectul este cel dorit. 3. Aceast ntrebare este identic cu cea prezent la seciunea 1s. Rspunsul este simplu : cu modificarea adus, exemplul nu va mai funciona! 4. Codul rezultat nu se va putea traduce i, prin urmare, nu va funciona. Dac v uitai n tabelul acela mare de instruciuni vei vedea c instruciunea lpm funcioneaz numai cu registrul extins Z.

[7s] Ale, suntem aici!

1. Fr ntrzierea de dup afiare creieraul va trimite nentrerupt una din cele 2 secvene
(n funcie de starea butonaului D6) spre afior. Acest lucru se traduce vizual prin aprinderea tuturor LED-urilor (vedei modul de funcionare al afiorului pentru o explicaie asupra acestui fenomen). Prin urmare, dac vrem s vedem corect, trebuie s avem o ntrziere dup afiare. 2. O variant de cod ce ar rspunde la aceast problem ar putea fi urmtoarea :
; pulsm linia de ncrcare pentru a depozita starea curent a tastelor

cbi PORTB, PB4 sbi PORTB, PB4


; aplicm impulsuri consecutive pn ajungem la starea butonaului dorit (D3)

cbi PORTB, PB1 sbi PORTB, PB1 cbi PORTB, PB1 sbi PORTB, PB1 cbi PORTB, PB1 sbi PORTB, PB1

208

cbi PORTB, PB1 sbi PORTB, PB1


; verificm starea butonaului D3 i ncrcm tiparul de afiat dup caz

sbic PINB, PINB2 ldi R16, 0b11110000 sbis PINB, PINB2 ldi R16, 0b00001111 rcall afiseaza_r16 rcall intarzie_un_pic

; afim tiparul i ntrzierea obinuit dup care repetm secvena

3. Un rspuns corect ar fi urmtorul cod :


cbi PORTB, PB4 sbi PORTB, PB4
; pulsm linia de ncrcare pentru a depozita starea curent a tastelor

; verificm butonaul D7

sbis PINB, PINB2 rjmp D7_apasat cbi PORTB, PB1 sbi PORTB, PB1 cbi PORTB, PB1 sbi PORTB, PB1 cbi PORTB, PB1 sbi PORTB, PB1 cbi PORTB, PB1 sbi PORTB, PB1 cbi PORTB, PB1 sbi PORTB, PB1 cbi PORTB, PB1 sbi PORTB, PB1 cbi PORTB, PB1 sbi PORTB, PB1 cbi PORTB, PB1 sbi PORTB, PB1
; verificm starea butonaului D0 ; aplicm impulsuri pn ajungem la starea lui D0

sbis PINB, PINB2 rjmp D0_apasat


; ajungnd aici nseamn c nici unul din butoane nu a fost apsat. ; ncrcm tiparul implicit de afiat

ldi R16, 0b00000000 rjmp afiseaza_tiparul

209

D7_apasat: ldi R16, 0b00000001 rjmp afiseaza_tiparul D0_apasat: ldi R16, 0b10000000 afiseaza_tiparul: rcall afiseaza_r16 rcall intarzie_un_pic

[8s] Ale, tot aici suntem ...

1. Codul urmtor este un rspuns corect la aceast problem :


citeste_taste_r17: push R16 cbi PORTB, PB1 cbi PORTB, PB4 nop sbi PORTB, PB4 clr R17 ldi R16, 8 ciclu_citire_taste: lsr R17 sbis PINB, PINB2 ori R17, 0b10000000 cbi PORTB, PB1 nop sbi PORTB, PB1 dec R16 cpi R16, 0 brne ciclu_citire_taste pop R16 ret Liniile marcate cu nuana aceasta de culoare reprezint modificrile aduse la subrutina original. Practic, n loc s rotim registrul la stnga, l rotim la dreapta 'lsr' i adugm bitul de apsat '1' n cealalt parte a sa. 2. Pentru a rezolva aceast cerin este suficient s negm (complementm) biii lui R17 nainte ca subrutina s revin la punctul de unde s-a apelat. Facem aceasta utiliznd instruciunea 'com' :
; instruciunile subrutinei 'citeste_taste_r17'

com R17

pop R16 ret

210

[9s] i dac totul este bine, s continum ...

1. Din cauza modului n care este scris codul, fcnd aici mai ales referire la ordinea de
verificare a butoanelor, apsarea simultan a 2 sau mai multe butonae va conduce la execuia programului celui mai mic buton apsat. Cu alte cuvinte, dac apsm simultan i D0 i D2, aplicaia selectat este cea a lui D0 pentru c el este verificat nainte lui D2. 2. Facem acest lucru prin ncrcarea programului 2 n R18 nainte de a 'executa_vesnic' meniul respectiv rcall initializeaza_perif ldi R18, 2 executa_vesnic:
; [restul de instruciuni]

3. Zis i fcut. O variant corect l reprezint urmtorul cod :


; [instruciuni ale exemplului iniial]

rjmp decrementeaza_3 sbrc R18, 4 rjmp interschimba

; [codul restului de programe]

decrementeaza_3: ldi R19, 3 sub R16, R19 rjmp afiseaza_secventa interschimba: swap R16 afiseaza_secventa:
; [restul de instruciuni ale exemplului]

4. Secvena ce trebuie s o nlocuim are rolul de a verifica R17 dac este egal cu 0. Dac
da, atunci se realizeaz saltul la 'reinoire_nenec'. Dac nu, se execut restul de instruciuni normal. Am putea nlocui instruciunea 'tst R17' cu 'cpi R17, 0' sau 'subi R17, 0'. Comportamentul este acelai.

[10s] ntrzieri mai bune

1. Un factor mai mic conduce la o vitez de numrare mai mare a ceasului. 2. Pentru a rspunde la aceast ntrebare trebuie s observm faptul c R17 este de fapt
valoarea ceasului (TCNT0). Aceast valoare este comparat iniial cu 255, iar dac este egal atunci se incrementeaz numrtorul binar. Dac noi micorm acest 255 la 120 sau orice alt valoare mai mic, atunci evident vom obine o cretere a vitezei de numrare. Motivul este unul simplu : ceasul are nevoie de mai puin timp pentru a ajunge la o valoare mai mic dect la una mai mare. 3. Instruciunea 'ldi R17, 0' va conduce la resetarea lui TCNT0 prin copierea valorii lui R17 n registrul numrtor al ceasului0. Dac nlocuim aceast valoare de reset a lui TCNT0 cu o valoare mai mare, asta nseamn c micorm numrul de incrementri realizate pn la atingerea limitei superioare (n exemplul nostru : 255). Cu programul original, TCNT0 trebuie s numere de la 0 la 255 nainte ca afiorul s se actualizeze pe cnd dac am folosi o alt valoare de resetare, 250 de pild, numrarea ceasului ar trebui s treac prin numai 5 valori

211

nainte s ating respectiva valoare limit. n concluzie, dac modifcm valoarea de pornire a numrtorului ceasului0, viteza de numrare va crete i ea.

[11s] Fr ntreruperi, v rog ...

1. Instruciunea reti se comport asemeni instruciunii ret (revine la punctul n cod de


unde s-a fcut apelul rcall), dar i seteaz bitul I din registrul de stare SREG. Asta face ca sistemul de ntreruperi s se reactiveze. Comportamentul obiinuit ale subrutinelor de tratare a ntreruperilor const n resetarea acestui bit I, iar acest motiv face ca instruciunea s fie folosit n special mpreun cu aceste subrutine. 2. Surprinztor, dar rspunsul este nu. Nu putem folosi __vector_0 n loc de eticheta main cu toate c main-ul este amplasat la adresa de tratare a ntreruperii de reset (indice 0 n tabela de tratare). Se pare c traductorul folosit de psAle nu poate fi convins c cele 2 lucruri nseamn, de fapt, unul i acelai comportament. 3. Cum era de ateptat, un factor mai redus va conduce la o incrementare mai rapid a numrtorului intern TCNT0 i, prin urmare, la generarea mai multor ntreruperi n aceeai unitate de timp.

[12s]Alt ntrerupere, acelai ceas0 ...

1. Considerm un ceas de baz ce ne definete o unitate de timp ca avnd 1 s . Un


factor ales de 1024 va conduce la o incrementare a numrtorului ceasului respectiv o dat la 10241 s=1024 s=1.024ms . Asta nseamn c pentru a determina valoarea lui OCR0A pentru care ntreruperea sa s se declaneze la fiecare 100ms scurse ar trebui s rezolvm ecuaia : 1.024?=100 . De unde obinem c ?=

100 =97.6562 . Noi nu 1.024

putem lucra cu numere fracionare aa c aproximm rezultatul obinut n sus i vom folosi 98 . Cu alte cuvinte, pentru a obine o declanare a ntreruperii de echivalen TCNT0OCR0A la fiecare 100ms , va trebui s alegem valoarea 98 pentru registrul OCR0A. Urmtoarea captur de osciloscop ne demonstreaz c am avut dreptate :

(canalul 1 a fost conectat la pinul de date PB1) Din nou se poate observa o diferen ntre valoarea real i cea calculat. Este mic, dar este prezent. Dac ne deranjeaz, se poate compensa. Cum ? Propun s ne ntoarcem un pic la exemplul 3s. Acolo am surprins adevrata valoare a duratei unitii de timp a sistemului. Dup cum era de ateptat, aceasta nu era exact 1 s

212

ci, n cazul nostru, un pic mai mic : 0.98 s . Dac folosim aceast informaie n exerciiul nostru vom obine faptul c TCNT0 se va incrementa o dat la 10240.98 s=1003.52 s=1.00352ms . Pentru aceast valoare, OCR0A ar trebui s fie configurat la ?=

100 =99.6492 sau aproximativ 100 . Ce s vezi ? Dac folosim 1.000352

aceast nou valoare, osciloscopul ne prezint urmtorul grafic :

Obinem o diferen mai bun, nu credei ? Diferena de 0.2ms este dat att de erorile aparatului de msur ct i de faptul c noi nu am folosit o valoare de 99.6492 ct ne cerea rezultatul, ci una un pic mai mare de 100 . Cu toate acestea, rezultatele sunt incomparabil mai bune. Deocamdat ne-am ocupat de un factor de 1024, dar problema ne cere s vedem dac putem obine aceast perioad i la un factor de 256. Rspunsul se poate da uor dac facem observaia c un factor de 256 va conduce numrtorul s se incrementeze de 4 ori mai repede fa de unul configurat la 1024. Asta nseamn c pentru a obine aceeai durat de timp de declanare, valoarea lui OCR0A va trebui s fie de asemenea de 4 ori mai mare dect cea precedent. S nu uitm c valoarea maxim ce ncape n registrul OCR0A este 255, dar noi trebuie s l configurm la (cazul ideal) 498=392 . Pentru cazul real, valoarea devine i mai mare: 4100=400 ! Prin urmare, pentru un factor de 256, nu exist valoare ce i-o putem da lui OCR0A pentru a obine o declanare a ntreruperii de echivalen TCNT0-OCR0A o dat la 100ms . 2. Orict de logic ar prea modificarea, datorit translatorului, comportamentul nu va fi acelai. Atunci cnd se analizeaz codul scris pentru a putea fi tradus, translatorul caut elemente cheie pe care el le poate nelege. Rescrierea etichetelor adreselor de tratare a ntreruperilor nu reprezint un pas uor de neles pentru translator. n cazul nostru, nlocuirea etichetei __vector_10 cu __vector_A ar duce la eliminarea adresei de salt din tabela de ntreruperi i tratarea ei ca o adres oarecare (cum este afiseaza_r16, de pild).

[12.1s] Atenie la ntreruperi!

1. Toate subrutinele pot fi ntrerupte. Iar subrutinele de tratare a ntreruperilor lucreaz i ele
cu regitrii cu care lucreaz subrutinele ntrerupte. Modul n care acestea afecteaz execuia aplicaiei depinde de utilizarea acestor regitrii. Este bine i corect s ncercm s ne gndim la aceste probleme dinainte pentru a le corecta dac este cazul.

213

[13s] ntreruperi din nou i din nou ...

1. Motivul este unul simplu : pentru c configurm registrul OCR0A la o valoare foarte mic
(1). Asta nseamn c subrutina de tratare se execut de foarte multe ori pe secund, iar afiorul este actualizat de la fel de multe ori. 2. Noi ne-am gndit la urmtoarea variant : executa_vesnic: rcall citeste_taste_r17 tst R17 breq continua_executia
; dac nu s-a apsat nicio tast, realizeaz direct incrementarea

sbrc R17, 0 ; D0 apsat ? : ldi R18, 1 sbrc R17, 1 ; D1 apsat ? : ldi R18, 127 sbrc R17, 2 ; D2 apsat ? : ldi R18, 255 out OCR0A, R18 continua_executia: inc R16 rjmp executa_vesnic

; dac s-au apsat taste, verific care taste s-au apsat i ncarc valoarea de comparare ; direct ntr-un registru normal R18

; actualizeaz valoare de comparare cu valoarea registrului R18

Noua secven executa_vesnic este alctuit din 13 instruciuni pe cnd vechiul ciclu are 18 comenzi. Am obinut, aadar, o economie de 5 instruciuni! 3. Modificrile de cod urmtoare fac acest lucru :
; [alte instruciuni originale, nemodificate]

sbrc R17, 3 ; D3 apsat ? : rjmp D3_apasat ; Da sbrc R17, 4 ; D4 apsat ? : rjmp D4_apasat ; Da sbrc R17, 5 ; D5 apsat ? : rjmp D5_apasat ; Da sbrc R17, 6 ; D6 apsat ? : rjmp D6_apasat ; Da
; [alte instruciuni originale]

D2_apasat: ldi R17, 255 out OCR0A, R17 rjmp continua_executia D3_apasat: ldi R17, 100 out OCR0A, R17 rjmp continua_executia

214

D4_apasat: ldi R17, 200 out OCR0A, R17 rjmp continua_executia D5_apasat: ldi R17, 0b00000000 out TCCR0B, R17 rjmp continua_executia D6_apasat: ldi R17, 0b00000101 out TCCR0B, R17 continua_executia:
; [restul de instruciuni nemodificate]

[14s] Cnd una nu este suficient ...

1. n funcie de valorile alese, este posibil ca o ntrerupere s se declaneze mai repede


dect cealalt. Asta nu constituie nicio problem pentru ntreruperea ntrziat, ea se va executa mai devreme sau mai trziu. Ideea general este aceea c nu conteaz ordinea de executare a subrutinelor. 2. Dac mutm instruciunile indicate n subrutina de tratare a ntreruperii de depire, indiferent dac pstrm sau nu apelul la subrutina de ntrziere, afiorul va indica o singur valoare. Motivul este datorat ceasului0 : s nu uitm c att ntreruperile de echivalen TCNT0-OCR0A i TCNT0-OCR0B, dar i ntreruperea de depire funcioneaz pe acelai numrtor. Asta nseamn c ele nu pot s se ntrerup una pe cealalt atta timp ct ele sunt generate una dup cealalt! Atunci cnd afiarea era realizat n 'main' ns, instruciunile de acolo se executau indiferent dac ceasul0 funciona sau nu. Acest lucru permitea ca ntreruperile de echivalen s poat interveni n secvena principal. 3. n primul rnd, pentru a proteja subrutina afiseaza_r16, trebuie s scriem un pic de cod n ea : afiseaza_r16: cli
; [codul subrutinei nemodificat]

sei ret Dup trimiterea noului cod pe plcu vom observa 2 lucruri : Secvena de LEDuri rmne mai mult sau mai puin aceeai, iar Atunci cnd se modific, nu o mai face pe pri, aa cum se realiza cnd foloseam codul original, ci se aplic tiparul n ntregime. Motivul acestui comportament este datorat interzicerii ntreruperilor de a interveni atunci cnd codul ce se execut se afl n subrutina afiseaza_r16. Astfel, secvena afiat este protejat de eventualele modificri exterioare.

215

[15s] Cnd milisecundele nu sunt suficiente ...

1. Un factor de mprire de 128 va conduce la o perioad a unitii de timp a sistemului de


128 1 s=161 s=16 s . n aceste condiii, dac folosim un ceas cu un factor de 8
512, atunci putem spune c o incrementare a numrtorului are loc o dat la 51216 s=8192 s=8.192ms . Asta nseamn c perioada maxim dup care ceasul0 genereaz o ntrerupere este obinut n condiiile unei ntreruperi de depire adic dup numrarea a 256 de valori. Prin urmare, aceast ntrziere nu poate depi valoarea de 2568.192ms=2097.152ms=2.097152s . n concluzie, cele 5 secunde nu se pot obine n aceste condiii! 2. Pentru rezolvarea acestui exerciiu pornim de la problema precedent. La un factor de mprire de 128 i un factor de ceas de 512, obinem o incrementare a numrtorului o dat la 8.192ms i un interval maxim de ntrerupere de 2.097s . Noi avem nevoie s generm o ntrerupere la fiecare 4s , dublul acestei valori. Dac dublm factorul de ceas(opiune disponibil pentru ceasul0) de la 512 la 1024, atunci obinem o perioad maxim de declanare a ntreruperii generate de acest ceas de 2.097s2=4.194s . Perfect! Pentru faptul ca aceast perioad este mai mare dect cele 4s dorite, va trebui s folosim o ntrerupere de echivalen pentru a obine o valoare mai bun a timpului. ntrebarea ce apare imediat este : ce valoare de comparaie alegem pentru respectiva ntrerupere ? Cu puin matematic ne gsim rspunsul. n condiiile unui factor de mprire de 128 i un factor de ceas de 1024, o incrementare a numrtorului se realizeaz o dat la 102416 s=16384 s=16.384ms . Valoarea de comparare (folosim OCR0A, ca n exemplu) o obinem din urmtoarea relaie :

4000 =244.14 , sau, rotunjit, 244 . 16.384

mpachetm toate observaiile ntr-un cod i obinem urmtoarea secven. Vom folosi butonul D3 pentru a activa aceast perioad :
; [alte instruciuni ale exemplului]

sbrc R17, 2 rjmp D2_apasat sbrc R17, 3 rjmp D3_apasat


; [alte secvene de program]

D2_apasat: ldi R17, 0b10000000 out CLKPR, R17 ldi R17, 0b00001000 out CLKPR, R17 rjmp incrementeaza_r16 D3_apasat:
; aplicm valoarea de comparaie calculat

ldi R17, 244 out OCR0A, R17 ldi R17, 0b10000000 out CLKPR, R17 ldi R17, 0b00000111
; alegem un factor de mprire de 128

216

out CLKPR, R17 incrementeaza_r16:


; [alte instruciuni nemodificate]

[16s] Un ceas mai capabil ...

1. Avnd n vedere faptul c ceasul1 suport un factor de 16384, asta nseamn c la o


baz de timp de 1 s , numrtorul ceasului crete cu o valoare la fiecare 163841 s=16384 s=16.384ms . O ntrerupere de depire se va declana, n acest caz, o dat la 25616.384ms=4194.304ms=4.194s . 2. Pentru acest exerciiu vom folosi un factor de 16384, cel de 8192 nu se poate utiliza (verificai!). Asta conduce la o valoare de comparare de

2.5s 2500ms = =152.587 . 16.384ms 16.384ms

Vom alege valoarea rotund de 153 . Avnd aceste rezultate, putem merge mai departe s le utilizm n codul cerut. Vom reda aici doar subrutina de initializare_perif, restul de cod rmnnd lafel ca cel din exemplu : initializeaza_perif: ldi R16, 0b01000000 out TIMSK, R16
; configurm registrul de comparare

ldi R16, 153 out OCR1A, R16

; setm factorul ceasului pe valoarea maxim (16384)

ldi R16, 0b00001111 out TCCR1, R16 sei ldi R16, 0b00000011 out DDRB, R16 ret

[17s] mpreun facem lucruri frumoase ...

1. Dac mrim baza de timp, mrim i intervalul de declanare a ntreruperilor ceasului.


Asta conduce inclusiv la mrirea intervalului de timp n care afiorul este nchis. Mrirea aceasta face ca ochiul s o sesizeze, iar efectul de iluminare treptat nu se mai poate observa. O alt consecin important a acestei observaii : dac am avea opiunea unui factor fracionar (exemplu :

1 ) aceast plpire ar fi mai greu de sesizat. 2

2. Se poate! Nu este uor, dar se pot contopi cele dou subrutine de tratare a ntreruperii
ntr-una singur gestionat de un unic ceas. Nu vom prezenta codul aici, dar vom puncta gndirea dup care am realizat aceast afirmaie : trebuie s fim contieni c cele 2 subrutine nu fac altceva dect s foloseasc doi regitrii generali pentru a controla afiorul. Dac aceasta este povestea, de ce nu s-ar putea utiliza cei 2 regitrii (sau ceva asemntor, de exemplu: un registru extins pe 16 bii) ntr-o singur ntrerupere pentru a obine un efect asemntor ? Singura problem mare o reprezint aici perioada de declanare a ntreruperii

217

respective. Noi am folosit dou ceasuri pentru a obine perioade diferite de declanare, aa cum ne dicteaz teoria, dar acest lucru nu va mai fi posibil dac vom utiliza un singur ceas. Totui, cu puin ingenioiztate i utiliznd regitrii de 16 bii, acest lucru nu este imposibil! 3. Zis i fcut. Urmtoarele modificri ne ajut s obinem tocmai acest efect :
; [...]

main: clr R20 ; plecm de la o intensitate cresctoare a afiorului


; [...]

__vector_3: ; ceasul1 - TCNT1 - OCR1A push R18


; dac R20 are valoare 0 atunci considerm c realizm secvena de cretere a intensitii afisorului ; dac, n schimb, R20 are valoare 1, rezultatul este contrar: intensitatea afiorului descrete

tst R20 breq _intensitate_crescatoare_v3 _intensitate_descrescatoare_v3: subi R17, 5 tst R17 ; dac valoarea lui R17 a atins limita inferioar a perioadei breq schimba_directia_intensitate ; atunci trecem pe secven cresctoare rjmp incheie_subrutina _intensitate_crescatoare_v3: ldi R18, 5 add R17, R18 cpi R17, 100 ; atenie s modificai aceast valoare altfel efectul va avea un pic de suferit brne incheie_subrutina schimba_directia_intensitate: ldi R18, 1 ; schimbm direcia intensitii afiorului eor R20, R18 incheie_subrutina: pop R18 reti
; [...]

Avnd n vedere c exerciiul nu a fost unul aa de uor, sunt necesare o serie de explicaii. Practic, valoarea ce controleaz intensitatea n orice moment a afiorului este registrul R17. El dicteaz, aa cum am vzut n explicaiile seciunii, raportul de timp pornit/oprit al LEDurilor. n aceast idee, am modificat subrutina de tratare a ntreruperii de echivalen pentru a crete i apoi descrete aceast valoare pentru a obine efectul dorit. Pentru aceasta am folosit registrul general R20 pentru a ne pstra direcia de modificare a registrului R17 astfel : Un 0 prezent precizeaz c secvena curent este cresctoare, iar Un 1 precizeaz contrariul : R17 va descrete imprimnd un comportament de scdere n intensitate a afiorului. n funcie de valoarea lui R20, R17 fie va crete pn va atinge valoarea 100 dup care R20 va trece n cealalt stare, iar R17 va ncepe s descreasc pn va atinge valoarea 0, moment n care R20 se va modifica din nou i secvena aceasta va continua la nesfrit. Un lucru la care ar trebui s fii ateni atunci cnd verificai aceast soluie l constituie valoarea limitei superioare a lui R17. Este vorba de acel '100' din instruciunea cpi R17, 100. n exemplul ce l-am discutat n seciunea prezent noi am folosit o valoare mai mare,

218

'105', pentru a realiza o trecere oarecum mai graioas spre o nou cretere de intensitate a afiorului. Acest lucru nu mai poate fi meninut n acest exerciiu deoarece secvena de descretere a intensitii ce urmeaz imediat n urma evalurii adevrate a acestei instruciuni trebuie s fie continu din punctul de vedere vizual, iar acest lucru este posibil doar dac limita lui R19, din subrutina de tratare a ntreruperii de depire, i cea a lui R17, din subrutina ntreruperii de echivalen, sunt egale. Pentru a vedea ce efect are '105' n soluia noastr, nu v rmne dect s o pstrai n cod i s l ncrcai pe plcu.

[18s] Cinele, cel mai bun prieten al omului i nu numai ...

1. Sunt corecte oricare dou rspunsuri din urmtoarele variante posibile :


Celul nu are un registru numrtor accesibil din exterior pe cnd modulele de ceas au un asemenea registru Celul are funcionalitate precis : are grij ca aplicaia s nu o ia razna i dac o ia, pune la dispoziie mijloace prin care se poate realiza o corecie pe cnd modulele de ceas au utilizri mai generale Modulele de ceas sunt mai flexibile n capacitatea lor de configurare (tipuri de ntreruperi generate, perioada lor de generare, etc.) fa de modulu celului Celul are o instruciune special creat pentru el, wdr, iar modulele normale de ceas nu au o asemenea instruciune 2. Dac nlocuim subrutina cu cea indicat vom observa c afiorul se va bloca la valoarea 0b00000001. Dac urmrim comportamentul celului prezentat n crulie, vom vedea c, eliminnd instruciunile lui de calmare, la urmtoarea declanare a ntreruperii sale, el va reseta creieraul. n condiiile acestea de resetare a creieraului la fiecare a 2-a declanare de ntrerupere, este clar c numrtorul nu va trece niciodat de valoarea 1, valoare pe care i noi o putem observa.

[19s] i pe mine cine m-a resetat ?

1. Bitul BORF din registrul MCUSR se activeaz atunci cnd nivelul tensiunii de alimentare
scade sub o anumit valoare. Circuitul va funciona pn la un anumit punct i cu tensiunea de alimentare sub cea necesar lui, dar nu pentru foarte mult vreme. n aceste condiii, ntreruperea generat de bitul BORF poate fi folosit pentru a salva rapid starea creieraului nainte de pierderea total a energiei. Noi nu putem demonstra aceast capacitate cu ajutorul plcuei curente pentru c nu dispunem de construcia fizic care s ne permit o scdere a nivelului de tensiune ntr-un mod treptat, ntr-un mod care s ne permit execuia n siguran a unui numr final de instruciuni. 2. Zis i fcut : .global __vector_12
; []

__vector_12:
; afim tiparul cerut

ldi R16, 0b10101010 rcall afiseaza_r16


; dezactivm complet celul

ldi R17, 0b00000000 out WDTCR, R17 _ciclu_infinit:

; prindem execuia aplicaiei ntr-un ciclu infinit

219

rjmp _ciclu_infinit reti


; []

initializeaza_perif:
; iniializm celul cu declanare la 2 secunde cu generare de ntrerupere

ldi R16, 0b01000111 out WDTCR, R16


; [...]

[20s] Eco Ale!

1. n condiiile ideale prezentate n seciune, Mod-ul 3 este mai eficient dect Mod-ul 1
0.24 =120 de ori. 0.002

2. Diferena destul de mare obinut ntre valoarea calculat i valoarea real se datoreaz
att erorilor de msurare ale aparatelor de msur ct i a condiiilor n care au fost realizate aceste msurtori respectiv aplicaia care funciona pe creiera la momentul respectiv i chiar temperatura circuitului. 3. Din cauza faptului c n exemplul prezentat folosim Mod-ul cel mai restrictiv suportat de creiera, Mod-ul 3, nsi ceasul sistemului este oprit. Iar cum modulele de ceas (ceasul0 i ceasul1) funcioneaz de pe aceast unitate de timp a sistemului, asta nseamn c ele nu vor funciona n acest Mod de lucru! Prin urmare, orice ntrerupere scris de voi care s utilizeze modulele de ceas nu se va declana dac creieraul este adormit n acest Mod de conservare a energiei.

[21s] Un psAle i o Ale. Ceau Ale!

1. Dac realizm calculele corect, obinem urmtoarele rezultate :


Pentru 1 secund : 1000001s=100000s sau mai bine de 27 de ore, pentru 8 secunde : 1000008s=800000s sau peste 222 de ore, iar pentru 1 minut : 10000060s=6000000s sau peste 1666 de ore!

[22s] Ale, tii cumva ce temperatur este ?

1. La un factor de 64 i o unitate de timp a sistemului de 1 s , o unitate de timp a


modulului CAD consum 641 s=64 s . innd cont c primul rezultat al conversiei l avem dup 25 de astfel de baze de timp, iar n rest rezultate obinem o dat la 13 astfel de baze, soluiile corecte ale exerciiului sunt dup cum urmeaz : Prima conversie se obine dup 2564 s=1600 s=1.6ms , iar restul de conversii vin la fiecare 1364 s=832 s=0.832ms scurse.

2. Este suficient s ne uitm la tabelul acela mare de instruciuni si vom vedea c una din
limitrile instruciunii sbiw o reprezint valoarea ce trebuie sczut din registru. Aceasta nu poate depi domeniul 0,63 . Cum 273 nu intr n acest domeniu, am decis s o mprtim n buci mai uor comestibile. 3. Dac nu am scdea acea valoare de 273 , am avea de fapt temperatura exprimat n grade Kelvin, care reprezint o alt unitate de msur internaional pentru temperatur. Noi suntem obinuii ns cu temperatura exprimat n grade Celsius. Pentru a realiza trecerea

220

dintre cele dou uniti de msur, trebuie s scdem 273 din rezultat. Lucru pe care-l i facem. 4. Dac eliminm respectiva instruciune din cod blocm modulul CAD s mai genereze alte valori de temperatur. Dac mai inei minte, o condiie de utilizare a modulului n generarea continuu de valori a fost s-i citim COMPLET rezultatul su de 10 bii ADCH:ADCL! Dac nu realizm asta, modulul nu poate ti c rezultatul su curent a fost utilizat i nu poate porni o nou achiziie de valori, atunci cnd aceast aciune este cerut. 5. Noul cod pune bitul 5 din registrul ADMUX pe valoarea '1'. Dac urmrim explicaiile acestui registru observm c aceast aciune activeaz autodeclanarea conversiei. Practic, de ndat ce rezultatul a fost citit din registrele ADCH:ADCL se ncepe automat o nou achiziie de valori fr a fi necesar o cerin manual n acest sens.

[23s] Lui Ale nu-i trebuie ochelari

1. Rspunsul este DA, se poate calcula rezistena dac se cunoate tensiunea culeas de
pe ea, iar pentru c aceasta este o seciune de rspunsuri, precizm aici i modul. Nu este mare filozofie, dac urmrim explicaiile divizorului de tensiune din seciunea Ale intr pe scen vom vedea urmtoarea relaie: U rezultat =U alimentare

Rezisten2 . n Rezisten2+ Rezisten1

aceast relaie, noi presupunem cunoscute U alimentare (aproximativ 5V, n cazul nostru),

U rezultat (citit de pe afior) i Rezisten1 (din circuitul plcuei, aproximativ 1.5k =1500 ), iar rezistena foto-elementului este Rezisten2 . n aceste condiii, U rezultat Rezisten2=Rezisten1 . U alimentare U rezultat

2. Pentru a putea citi primii 8 bii din rezultatul CAD-ului, trebuie s ne ndreptm atenia
asupra bitului ADLAR din registrul ADMUX. n exemplul din seciune, acesta are valoarea '1' ceea ce nseamn c registrul afiat ADCH conine biii 9,2 din rezultat. Noi vom avea nevoie de biii cu indicii 7,0 . Pentru aceasta, schimbm ADLAR-ul n '0' i afim registrul ADCL, iar ADCH l citim doar pentru a semnaliza modulului c am preluat rezultatul su complet permind astfel nceperea unei noi conversii. Pentru a ne exprima n cod, prezentm urmtoarele modificri :
; []

__vector_12: in R16, ADCL rcall afiseaza_r16 in R16, ADCH


; []

initializeaza_perif: ldi R16, 0b01001110 out WDTCR, R16 sei ldi R16, 0b00000011 out ADMUX, R16
; [...]

Aplicaia obtinut prezint un nivel mai ridicat de sensibilitate la lumina prezent n jurul plcuei.

221

[24s] Din nou, napoi de unde am plecat ...

1. Acum rspunsul depinde de ce se nelege prin noiunea de resetare. Dac resetarea


nseamn aducerea registrului la valoarea 0, atunci nu am realizat-o, dar dac n schimb considerm c nseamn configurarea registrului la o valoare iniial cunoscut, atunci putem spune c am realizat aceast resetare prin instruciunea cpi R18, 42. Considerm a 2-a definiie ca fiind cea corect. 2. Vom folosi un procedeu de optimizare similar cu cel discutat la exerciiul 2 al seciunii 13s. n acest sens, propunem urmtoarea rezolvare : afiseaza_zar_r18: push R16
; == Regiune de stabilire a intervalului de apartenen a valorii R18 ==

ldi R16, 0b00000001 cpi R18, 42 brbs 0, _gata_subrut ldi R16, 0b00000011 cpi R18, 85 brbs 0, _gata_subrut ldi R16, 0b00000111 cpi R18, 127 brbs 0, _gata_subrut ldi R16, 0b00001111 cpi R18, 170 brbs 0, _gata_subrut ldi R16, 0b00011111 cpi R18, 212 brbs 0, _gata_subrut ldi R16, 0b00111111 _gata_subrut: rcall afiseaza_r16 ; afim valoarea rezultat pop R16 ret Dimensiunea subrutinei originale afiseaza_zar_r18 avea 26 de instruciuni pe cnd noua variant are 20 de instruciuni. Ctigm, aadar, 6 instruciuni! 3. Desigur c modificri pot fi multe. Noi vom prezenta aici doar una dintre acestea. S zicem c alegem s mbuntim jocul 2 numit i '36'. Dac ne amintim bine, scopul jocului este acela de a ajunge, prin aruncri de zar, ct mai aproape de valoarea 36 fr ns a o depi. Dac tot mai avem 2 LED-uri disponibile pe afior (6 dintre ele, LED-urile cu indicii 0,1,2,3,4 i 5, fiind folosite pentru a afia valoarea zarului curent), ce ai spune dac am folosi LED-ul cu indice 7 pentru a semnala atunci cnd valoarea curent a depit acel 36 stabilit din regulile jocului ? Acest lucru ne propunem Practic, att timp ct LED-ul 7 este nchis, juctorul curent are o valoare total a zarurilor aruncate ce nu depete 36, dar atunci cnd aceast valoare este depit aprindem LED-ul 7 pentru a semnaliza acest lucru.

222

Am putea tot aici s folosim LED-ul cu indice 6 pentru a semnaliza faptul c valoarea curent este exact 36, sau c s-au atins cele 10 aruncri regulamentare acordate juctorului. Acestea sunt doar idei de mbuntire. Cum ziceam, modificrile pot fi multe. nainte de a continua ns, trebuie s clarificm ceva : cum va ti plcuta c juctorul care arunc acum zarul este diferit de cel ce a aruncat zarul naintea sa ? Adic de unde va ti ea c numrtorul su intern ar trebui s se reiniializeze pentru c juctorul precedent a decis c valoarea la care a ajuns i este suficient? Haidei s folosim butonaul cu indice 7 pentru aceasta. Dac juctorul curent a decis s se opreasc la valoarea la care a ajuns, atunci juctorul ce-l urmeaz trebuie s apese butonaul cu indice 7 pentru a ncepe o nou contorizare a sumei. Fr alte ntrzieri, modificrile ce se impun n aceste condiii sunt urmtoarele :
; [...]

main: rcall initializeaza_perif clr R20 ; folosim acest registru pentru a contoriza valoarea jocului curent executa_vesnic: _asteptam_buton_recunoscut: rcall citeste_taste_r17 sbrc R17, 0 rjmp D0_apasat sbrc R17, 7 rjmp D7_apasat rjmp _asteptam_buton_recunoscut D0_apasat: clr R16 rcall afiseaza_r16 _D0_inca_apasat: inc R18 rcall citeste_taste_r17 sbrc R17, 0 rjmp _D0_inca_apasat rjmp _interpreteaza_valoarea_obtinuta D7_apasat: ; pentru acest buton, reiniializm registrul contor al jocului clr R20 clr R16 rcall afiseaza_r16 rjmp _asteptam_buton_recunoscut _interpreteaza_valoarea_obtinuta: rcall obtine_valoare_zar_r18_in_r19_si_r16
; adugm valoarea zarului curent la registrul contor

add R20, R19 cpi R20, 36 brlo _valoare_limita_nedepasita

223

ori R16, 0b10000000 _valoare_limita_nedepasita: rcall afiseaza_r16 rjmp executa_vesnic


; [...] ; afim valoarea zarului alturi de LED-ul 7 (cu semnificaia mai sus discutat) n formatul corect

obtine_valoare_zar_r18_in_r19_si_r16:
; subrutina folosete valoarea registrului R18 pentru a ncrca att zarul formatat direct n registrul de afiare ; R16 ct i valoarea sa efectiv pentru a putea fi folosit n logica aprinderii LED-ului cu indice 7 n R19

cpi R18, 42 brlo _zar_val_1 cpi R18, 85 brlo _zar_val_2 cpi R18, 127 brlo _zar_val_3 cpi R18, 170 brlo _zar_val_4 cpi R18, 212 brlo _zar_val_5 rjmp _zar_val_6 _zar_val_1: ldi R16, 0b00000001 ldi R19, 1 rjmp _gata_subrut _zar_val_2: ldi R16, 0b00000011 ldi R19, 2 rjmp _gata_subrut _zar_val_3: ldi R16, 0b00000111 ldi R19, 3 rjmp _gata_subrut _zar_val_4: ldi R16, 0b00001111 ldi R19, 4 rjmp _gata_subrut _zar_val_5: ldi R16, 0b00011111 ldi R19, 5 rjmp _gata_subrut _zar_val_6: ldi R16, 0b00111111 ldi R19, 6 _gata_subrut: ret

224

4) Scurt fi a registrelor de control a lui Attiny25


Adres Nume SREG SP GIMSK GIFR TIMSK TIFR SPMCSR MCUCR MCUSR TCCR0B TCNT0 OSCCAL TCCR1 TCNT1 OCR1A OCR1C GTCCR OCR1B TCCR0A OCR0A OCR0B PLLCSR CLKPR DT1A DT1B DTPS1 DWDR WDTCR PRR EEARH WDIF ----WDIE ----LSM CLKPCE DT1AH3 DT1BH3 ------DT1AH2 DT1BH2 --COM0A1 COM0A0 TSM PWM1B CTC1 PWM1A ---------BODS --FOC0A INT0 INTF0 OCIE1A OCF1A --PUD --FOC0B PCIE PCIF OCIE1B OCF1B RSIG SE ----Bit 7 I Bit 6 T Bit 5 H Bit 4 S Bit 3 V Bit 2 N Bit 1 Z Bit 0 C

0x3F 0x3D 0x3B 0x3A 0x39 0x38 0x37 0x35 0x34 0x33 0x32 0x31 0x30 0x2F 0x2E 0x2D 0x2C 0x2B 0x2A 0x29 0x28 0x27 0x26 0x25 0x24 0x23 0x22 0x21 0x20 0x1F

Conine adresa vrfului stivei ----OCIE0A OCF0A CTPB SM1 --------OCIE0B OCF0B RFLB SM0 WDRF WGM02 ----TOIE1 TOV1 PGWRT BODSE BORF CS02 ----TOIE0 TOV0 PGERS ISC01 EXTRF CS01 --------SPMEN ISC00 PORF CS00

Conine valoarea de numrare a ceasului0 Valoare inut n el calibreaz baza de timp a sistemului COM1A1 COM1A0 CS13 CS12 CS11 CS10

Conine numrtorul ceasului1 Registru de comparare selectabil pentru ceasul1 Alt registru de comparare pentru ceasul1 COM1B1 COM1B0 FOC1B FOC1A PSR1 PSR0

Al 3-lea registru de comparare utilizat de ceasul1 COM0B1 COM0B0 ----WGM01 WGM00

Registru de comparare selectabil pentru ceasul0 Al 2-lea registru de comparare selectabil pentru ceasul0 ----DT1AH1 DT1BH1 ------DT1AH0 DT1BH0 ----CLKPS3 DT1AL3 DT1BL3 --PCKE CLKPS2 DT1AL2 DT1BL2 --PLLE CLKPS1 DT1AL1 DT1BL1 DTPS11 PLOCK CLKPS0 DT1AL0 DT1BL0 DTPS10

Registru special de programare (folosit la inspeciia aplicaiilor) WDP3 ----WDCE ----WDE PRTIM1 --WDP2 PRTIM0 --WDP1 PRUSI --WDP0 PRADC EEAR8

225

Adres

Nume EEARL EEDR EECR PORTB DDRB PINB PCMSK DIDR0 GPIOR2 GPIOR1 GPIOR0 USIBR USIDR USISR USICR ACSR ADMUX ADCSRA ADCH ADCL ADCSRB

Bit 7 EEAR7

Bit 6 EEAR6

Bit 5 EEAR5

Bit 4 EEAR4

Bit 3 EEAR3

Bit 2 EEAR2

Bit 1 EEAR1

Bit 0 EEAR0

0x1E 0x1D 0x1C 0x18 0x17 0x16 0x15 0x14 0x13 0x12 0x11 0x10 0x0F 0x0E 0x0D 0x08 0x07 0x06 0x05 0x04 0x03

Registru intermediar de date ntre memoria EEPROM i aplicaie ------------------------EEPM1 PORTB5 DDB5 PINB5 PCINT5 ADC0D EEPM0 PORTB4 DDB4 PINB4 PCINT4 ADC2D EERIE PORTB3 DDB3 PINB3 PCINT3 ADC3D EEMPE PORTB2 DDB2 PINB2 PCINT2 ADC1D EEPE PORTB1 DDB1 PINB1 PCINT1 AIN1D EERE PORTB0 DDB0 PINB0 PCINT0 AIN0D

Registre generale de intrare/ieire

Registru tampon al comunicaiilor ntre-creierae Registru de date al comunicaiilor ntre-creierae USISIF USISIE ACD REFS1 ADEN USIOIF USIOIE ACBG REFS0 ADSC USIPF USIWM1 ACO ADLAR ADATE USIDC USIWM0 ACI REFS2 ADIF USICNT3 USICS1 ACIE MUX3 ADIE USICNT2 USICS0 --MUX2 ADPS2 USICNT1 USICLK ACIS1 MUX1 ADPS1 USICNT0 USITC ACIS0 MUX0 ADPS0

Registru ce conine partea superioar a unei conversii ADC Conine partea mai puin semnificativ (inferioar) a unei conversii ADC BIN ACME IPR ----ADTS2 ADTS1 ADTS0

226

4) Schema electric condensat a plcuei

227

Você também pode gostar