Cuprins:

Tutorial AVR Assembler 7: 12 Pași
Tutorial AVR Assembler 7: 12 Pași

Video: Tutorial AVR Assembler 7: 12 Pași

Video: Tutorial AVR Assembler 7: 12 Pași
Video: Getting Started with Atmel Studio 7 - Episode 12 - AVR® MCU Simulator Debugging 2024, Iulie
Anonim
Tutorial AVR Assembler 7
Tutorial AVR Assembler 7

Bine ați venit la Tutorialul 7!

Astăzi vom arăta mai întâi cum să curățăm o tastatură și apoi vom arăta cum să folosim porturile de intrare analogice pentru a comunica cu tastatura. Vom face acest lucru folosind întreruperi și un singur fir ca intrare. Vom conecta tastatura astfel încât fiecare apăsare de tastă să trimită o tensiune unică la intrarea analogică, ceea ce ne va permite să distingem prin tensiunea ce tastă a fost apăsată. Apoi vom afișa numărul apăsat pe analizorul nostru de registre pentru a arăta că totul se întâmplă așa cum ar trebui. Există o serie de capcane pe care le puteți executa atunci când utilizați convertorul analogic la digital (ADC) în ATmega328p și așa vom face luați lucrurile în câteva etape pe drum pentru a încerca și aflați cum să le evitați. Vom vedea, de asemenea, de ce utilizarea convertorului analogic digital nu este cea mai bună modalitate de a controla o tastatură, chiar dacă folosește mai puține porturi pe microcontrolerul dvs. În acest tutorial veți avea nevoie de:

  1. o tastatură. Puteți cumpăra una sau puteți face ceea ce am făcut și scăpați una.
  2. 2 anteturi de sex feminin pentru tastatură (dacă o eliminați)
  3. conectarea firelor
  4. o placă de măsurare
  5. 4 1 rezistențe Kohm
  6. 1 rezistor de 15 Kohm
  7. 1 rezistor de 3,3 Kohm
  8. 1 rezistor de 180 ohmi
  9. 1 680 ohm rezistor
  10. un multimetru digital
  11. analizorul dvs. din Tutorialul 5

Este posibil să doriți să ignorați primii pași dacă aveți deja o tastatură și nu aveți nevoie să o eliminați.

Iată un link către colecția completă a tutorialelor mele de asamblare AVR:

Pasul 1: Scavenge o tastatură 1

Scavenge o tastatură 1
Scavenge o tastatură 1
Scavenge o tastatură 1
Scavenge o tastatură 1
Scavenge o tastatură 1
Scavenge o tastatură 1
Scavenge o tastatură 1
Scavenge o tastatură 1

Cu mult timp în urmă, când chiar bunicii tăi erau simpli copii, oamenii obișnuiau să folosească aceste dispozitive cu aspect ciudat, care aveau cabluri lungi conectate la perete, pentru a comunica între ele. Erau numiți „telefoane” și erau de obicei lucruri ieftine din plastic care scoteau un sunet enervant atunci când cineva vă chema (nu că tonurile de apel „Justin Bieber” de astăzi nu sunt la fel de enervante). În orice caz, aceste dispozitive aveau pe ele tastaturi care erau foarte simplu cablate și astfel sunt ușor de scavenge și au 2 taste suplimentare pe ele („reapelare” și „bliț”) de pe tastaturile pe care le puteți cumpăra, pe care poate doriți să le refaceți ca „taste cu săgeți”, „taste pentru meniu” sau altceva. Deci, vom începe prin a elimina o tastatură de pe un telefon vechi. Mai întâi luați telefonul (folosesc unul GE așa cum se arată în imagini) și desprindeți-l pentru a dezvălui cablajul. Apoi luați o dalta și scoateți butoanele de plastic care țin tastatura și scoateți tastatura.

Pasul 2: Scavenge o tastatură 2

Scavenge o tastatură 2
Scavenge o tastatură 2
Scavenge o tastatură 2
Scavenge o tastatură 2
Scavenge o tastatură 2
Scavenge o tastatură 2

Acum luați un ferăstrău din PVC și tăiați plasticul din jurul găurilor de chei și apoi tăiați-l în jurul marginii pentru a obține adâncimea corectă lăsând o tastatură subțire.

Apoi, puneți din nou tastatura folosind piciorușele care rămân după ce le-ați tăiat vârfurile în ultimul pas și folosiți un fier de lipit pentru a introduce pur și simplu fierul fierbinte în fiecare gaură a cuiului, care va topi plasticul și îl va întinde peste partea de jos a tastaturii formând noi „butoane” care vor menține tastatura în poziție ca înainte.

Îmi place să scutur cele trei difuzoare și poate celelalte lucruri, cum ar fi comutatoarele și ce-nu, care sunt pe tablă. Cu toate acestea, de data aceasta nu am de gând să scuturăm întreruperile și altele, pentru că avem alte obiective în acest moment. De asemenea, există un IC liniar TA31002 acolo, care este o sonerie telefonică. Fișa tehnică este ușor de găsit și descărcat online, oferind detaliile și caracteristicile. Așa că am de gând să-l las lipit pe tablă pentru moment și apoi să mă joc cu el mai târziu. Aș vrea să-l conectez la un osciloscop și să văd ce semnale interesante pot scoate din el. Poate chiar să faci din ea un sunet. Cine știe.

Oricum, după ce ați terminat distrugerea telefonului și eliminarea pieselor, vom termina de realizat tastatura noastră.

Pasul 3: Scavenge o tastatură 3

Scavenge o tastatură 3
Scavenge o tastatură 3
Scavenge o tastatură 3
Scavenge o tastatură 3
Scavenge o tastatură 3
Scavenge o tastatură 3

Utilizați o fitilă de dezlipire și scoateți cablurile panglică din partea de jos a tastaturii, asigurându-vă că găurile din placa de circuit sunt libere și apoi atașați două anteturi feminine pe placa unde sunt găurile. Probabil va trebui să tăiați antetele, astfel încât să fie anteturi cu 4 pini.

Acum că anteturile sunt atașate, puteți să le conectați la o placă de măsurare, să luați un multimetru și să testați tastele lipind multimetrul de pinii aleatori și măsurând rezistența. Acest lucru vă va permite să mapați tastele. Este dificil să vezi cum sunt conectate tastele la ieșiri uitându-te la circuit, dar dacă folosești un multimetru îl poți conecta la oricare doi pini și apoi apasă butoanele până când vezi un număr pe ecran în loc de un circuit deschis. Acesta va fi indicatorul pentru acea cheie.

Hartați toate tastele la pinii de ieșire în acest fel.

Pasul 4: conectați tastatura

Conectați tastatura
Conectați tastatura
Conectați tastatura
Conectați tastatura

Acum urmați schema de cablare și conectați tastatura la panoul dvs. de calcul.

Cum va funcționa acest lucru este că vom pune 5V în partea stângă, iar partea dreaptă merge în GND. Primul pin din dreapta din diagramă intră în primul pin analogic al microcontrolerului Atmega328p. Când nu există butoane apăsate, semnalul va fi 0V, iar când fiecare dintre butoanele diferite este apăsat, intrarea în portul analog va varia între 0V și 5V cu o cantitate diferită, în funcție de tasta care a fost apăsată. Am ales valorile rezistenței astfel încât fiecare cale să conțină o rezistență diferită de restul. Portul analogic al microcontrolerului preia un semnal analogic și îl împarte în 1024 canale diferite între 0V și 5V. Aceasta înseamnă că fiecare canal are o lățime de 5V / 1024 = 0,005 V / canal = 5 mV / canal. Deci portul analogic poate distinge tensiunile de intrare atâta timp cât acestea diferă cu mai mult de 5 mV. În cazul nostru, am ales valorile rezistenței, astfel încât orice două apăsări de taste să trimită un semnal de tensiune care diferă mai mult decât acesta, astfel încât microcontrolerul să poată decide cu ușurință ce tastă a fost apăsată. Marea problemă este că întregul sistem este foarte zgomotos, așa că va trebui să alegem o gamă de tensiuni pe care să le mapăm la fiecare apăsare de buton - dar vom ajunge la asta puțin mai târziu.

Observați că putem controla o tastatură cu 14 butoane folosind doar o singură linie de intrare către controler. Acesta este unul dintre aspectele utile ale intrărilor analogice.

Acum, prima noastră încercare de a controla tastatura va fi să apăsăm tastele să provoace o întrerupere, subrutina de întrerupere va citi portul de intrare analogic și va decide ce tastă a fost apăsată, iar apoi va afișa acel număr în subrutina noastră de analizor de registre care va afișa valoare cheie în binar pe cele 8 LED-uri pe care le-am configurat în Tutorialul 5.

Pasul 5: conectați tastatura la analizorul dvs

Conectați tastatura la analizorul dvs
Conectați tastatura la analizorul dvs
Conectați tastatura la analizorul dvs
Conectați tastatura la analizorul dvs

Imaginile arată cum dorim să conectăm tastatura la microcontroler, astfel încât să putem vedea ieșirea pe afișajul analizorului nostru. În esență, conectăm pur și simplu ieșirea de la tastatură la pinul 0 PortC, care se numește și ADC0 pe ATmega328P.

Cu toate acestea, există câteva lucruri suplimentare. De asemenea, vom conecta un buton la PD2. Adică luați un fir de la șina de 5V la un buton și de cealaltă parte a butonului la PD2 și, în cele din urmă, dorim să deconectăm pinul AREF de la șina noastră de 5V și, în schimb, să-l lăsăm deconectat. Am putea introduce un condensator de decuplare de 0,1 microfarad dacă dorim. Acesta este un condensator ceramic cu un 104 scris pe el. Primele două cifre sunt numărul, iar ultima cifră este puterea lui 10, îl înmulțim cu pentru a obține un răspuns în picofarade (pico înseamnă 10 ^ -12), deci 104 înseamnă 10 x 10 ^ 4 picofarade, care este același cu 100 nanofarade (nano înseamnă 10 ^ -9), care este același cu 0,1 microfarade (micro înseamnă 10 ^ -6). Oricum, tot ce face este să stabilim pinul AREF atunci când îl putem folosi ca pin de referință.

De asemenea, dorim un rezistor de 1 Mohm între PD2 și sol. Vom seta PD2 ca pin de ieșire la 0V și vom declanșa pe o margine pozitivă la acel pin. Vrem ca marginea să dispară imediat când eliberăm butonul, așa că vom introduce acest rezistor de „tragere în jos”.

Motivul pentru care dorim butonul este că dorim să declanșăm convertorul nostru analog-digital de pe pinul INT0 de pe cip, care este și PD2. În cele din urmă, am dori ca apăsarea tastei să declanșeze ADC și să furnizeze, de asemenea, intrarea pentru a fi convertită fără a avea un buton separat, dar din cauza modului în care funcționează sincronizarea, vom începe prin a avea un buton separat pentru a declanșa ADC și odată ce am călcat toate erorile și suntem încrezători că totul funcționează corect, apoi vom aborda problemele de zgomot și sincronizare care vin cu declanșarea de la aceeași apăsare pe buton pe care dorim să o citim.

Deci, deocamdată, modul în care funcționează este că vom ține apăsată o tastă, apoi vom apăsa butonul pentru a declanșa ADC, apoi vom da drumul și, sperăm, valoarea binară a butonului pe care l-am apăsat va apărea pe analizor.

Deci, să scriem un cod care să realizeze acest lucru.

Pasul 6: Ce comutatoare de comutare ar trebui să setăm?

Ce comutatoare de comutare ar trebui să setăm?
Ce comutatoare de comutare ar trebui să setăm?

Să ne gândim mai întâi la modul în care vom codifica acest lucru, astfel încât controlerul să poată citi intrarea de pe tastatură și să o transforme într-o valoare numerică corespunzătoare butonului care a fost apăsat. Vom folosi Convertorul analogic la digital (ADC) care este încorporat în Atmega328p. Vom folosi AREF ca tensiune de referință, iar ieșirea tastaturii va fi conectată la PortC0 sau PC0. Rețineți că acest pin se mai numește ADC0 pentru convertorul analog-digital 0. Ar putea fi o idee bună să citiți secțiunea 12.4 despre întreruperi pentru ATmega328P și, de asemenea, capitolul 24 despre convertorul analog-digital înainte de a obține a început sau cel puțin au acele secțiuni pregătite pentru referință. Pentru a configura microcontrolerul astfel încât să știe ce să facă cu un semnal analogic de intrare și cum să interacționeze cu programul nostru, trebuie mai întâi să setăm câteva dintre diversele ADC biți de registru asociați. Acestea sunt în esență echivalente cu vechile comutatoare de comutare de pe primele computere. Fie apăsați sau opriți întrerupătorul, fie chiar mai în spate, veți conecta cabluri între o priză și alta, astfel încât electronii care ajung la furculița de pe drum să găsească o poartă închisă și alta deschisă, forțând-o pe o cale diferită în labirintul circuitelor și efectuând astfel o sarcină logică diferită. Atunci când codificăm în limbaj de asamblare, avem un acces strâns la aceste funcții ale microcontrolerului, care este unul dintre lucrurile atractive despre realizarea acestuia în primul rând. Este mai mult „hands on” și se întâmplă mult mai puțin „în spatele scenei”. Deci, nu vă gândiți la setarea acestor registre ca la o sarcină plictisitoare. Acesta este ceea ce face ca limbajul de asamblare să fie interesant! Câștigăm o relație foarte personală cu funcționarea interioară și logica cipului și îl facem să facă exact ceea ce dorim - nici mai mult, nici mai puțin. Fără cicluri de ceas irosite. Deci, iată o listă a comutatoarelor pe care trebuie să le setăm:

  1. Opriți bitul ADC de reducere a puterii, PRADC, care este bitul 0 al registrului PRR, deoarece dacă acest bit este activat, acesta va închide ADC-ul. Registrul de reducere a puterii este în esență un mod de a opri diverse lucruri care folosesc energia atunci când nu aveți nevoie de ele. Deoarece utilizăm ADC, vrem să ne asigurăm că nu este dezactivat în acest fel. (Vezi PRADC la pagina 46)
  2. Selectați canalul de intrare analogic pentru a fi ADC0 dezactivând MUX3 … 0 în registrul ADC Multiplexer Selection (ADMUX) (Vezi tabelul 24-4 pagina 249) acestea sunt deja dezactivate în mod implicit, deci nu este nevoie să facem acest lucru. Cu toate acestea, îl includ, deoarece dacă folosiți vreodată un alt port decât ADC0, va trebui să comutați aceste comutatoare în consecință. Diverse combinații de MUX3, MUX2, MUX1, MUX0 vă permit să utilizați oricare dintre porturile analogice ca intrare și le puteți schimba din mers dacă doriți să priviți o grămadă de semnale analogice diferite simultan.
  3. Opriți biții REFS0 și REFS1 în registrul ADMUX, astfel încât să folosim AREF ca tensiune de referință mai degrabă decât ca referință internă (Vezi pagina 248).
  4. Porniți bitul ADLAR în ADMUX, astfel încât rezultatul să fie „ajustat la stânga”, vom discuta despre această alegere în pasul următor.
  5. Setați bitul ADC0D în Registrul de intrare digitală a intrării (DIDR0) pentru a opri intrarea digitală la PC0. Folosim acel port pentru intrarea analogică, deci ar putea dezactiva și intrarea digitală pentru acesta.
  6. Setați ISC0 și ISC1 în Registrul de control al întreruperii externe A (EICRA) pentru a indica faptul că dorim să declanșăm pe marginea ascendentă a unui semnal de tensiune la pinul INT0 (PD2), vezi pagina 71.
  7. Ștergeți biții INT0 și INT1 în Registrul de mască de întrerupere externă (EIMSK) pentru a indica faptul că nu folosim întreruperi pe acest pin. Dacă ar fi să activăm întreruperile pe acest pin, am avea nevoie de un handler de întrerupere la adresa 0x0002, dar în schimb îl configurăm astfel încât un semnal pe acest pin să declanșeze conversia ADC, a cărei finalizare este gestionată de întreruperea completă a conversiei ADC la adresa 0x002A. Vezi pagina 72.
  8. Setați bitul ADC Enable (ADEN) (bit 7) în controlul ADC și registrul de stare A (ADCSRA) pentru a activa ADC. Vezi pagina 249.
  9. Am putea începe o singură conversie setând bitul de conversie ADC start (ADSC) de fiecare dată când am vrut să citim semnalul analogic, totuși, deocamdată am prefera să fie citit automat ori de câte ori cineva apasă butonul, așa că în loc vom activa ADC Autotrigger Enable (ADATE) bit în registrul ADCSRA, astfel încât declanșarea să se facă automat.
  10. De asemenea, setăm biții ADPS2..0 (biții AD Prescalar) la 111, astfel încât ceasul ADC să fie ceasul CPU împărțit la un factor de 128.
  11. Vom selecta sursa declanșării ADC pentru a fi PD2, care se mai numește și INT0 (Cerere de întrerupere externă 0). Facem acest lucru comutând diferiții biți în registrul ADCSRB (vezi Tabelul 24-6 la pagina 251). Vedem lângă tabel că vrem ADTS0 dezactivat, ADTS1 activat și ADTS2 dezactivat, astfel încât ADC să declanșeze acel pin. Rețineți dacă am dori să prelevăm în mod continuu portul analog, ca și cum am citi un semnal analog continuu (cum ar fi eșantionarea sunetului sau ceva de genul), l-am seta la modul Free Running. Metoda pe care o folosim pentru setarea declanșării pe PD2 declanșează o citire ADC a portului analog PC0 fără a provoca o întrerupere. Întreruperea va apărea la finalizarea conversiei.
  12. Activați bitul ADC Interrupt Enable (ADIE) în registrul ADCSRA astfel încât, atunci când conversia analogică la digitală este finalizată, va genera o întrerupere pentru care putem scrie un handler de întrerupere și pune la.org 0x002A.
  13. Setați bitul I în SREG pentru a activa întreruperile.

Exercițiul 1: asigurați-vă că ați citit secțiunile relevante din foaia de date pentru fiecare dintre setările de mai sus, astfel încât să înțelegeți ce se întâmplă și ce s-ar întâmpla dacă le-am schimba în setări alternative.

Pasul 7: Scrieți gestionarul de întrerupere

În ultimul pas am văzut că l-am configurat astfel încât o margine ascendentă detectată pe PD2 să declanșeze o conversie analogică în digitală pe PC0 și când această conversie este finalizată va arunca o întrerupere ADC Conversion Complete. Acum vrem să facem ceva cu această întrerupere. Dacă examinați Tabelul 12-6 la pagina 65, veți vedea o listă cu posibilele întreruperi. Am văzut deja întreruperea RESET la adresa 0x0000 și întreruperea Timer / Counter0 Overflow la adresa 0x0020 în tutoriale anterioare. Acum vrem să ne uităm la întreruperea ADC, pe care o vedem lângă tabel, la adresa 0x002A. Deci, la începutul codului nostru de limbaj de asamblare, vom avea nevoie de o linie care spune:

.org 0x002Arjmp ADC_int

care va trece la gestionarul nostru de întreruperi etichetat ADC_int ori de câte ori ADC a finalizat o conversie. Deci, cum ar trebui să scriem gestionarul nostru de întrerupere? Modul în care funcționează ADC este efectuând următorul calcul:

ADC = Vin x 1024 / Vref

Deci, să vedem ce se întâmplă dacă apăs butonul „reapelare” de pe tastatură. În acest caz, tensiunea de pe PC0 se va schimba la o anumită valoare, să spunem 1,52V și, din moment ce Vref este la 5V, vom avea:

ADC = (1,52V) x 1024 / 5V = 311,296

și așa ar apărea ca 311. Dacă am vrea să convertim acest lucru înapoi la o tensiune, am inversa calculul. Cu toate acestea, nu va trebui să facem acest lucru, deoarece nu suntem interesați de tensiunile reale doar pentru a distinge între ele. Când se termină conversia, rezultatul este stocat într-un număr de 10 biți plasat în registrele ADCH și ADCL și am făcut ca acesta să fie „ajustat la stânga”, ceea ce înseamnă că cei 10 biți încep de la bitul 7 al ADCH și merg la bitul 6 din ADCL (există 16 biți în total în aceste două registre și folosim doar 10 dintre ele, adică 1024 canale). Am putea avea rezultatul „ajustat la dreapta” dacă dorim, ștergând bitul ADLAR din registrul ADMUX. Motivul pentru care alegem ajustat la stânga este că semnalele noastre sunt suficient de departe pentru ca ultimele două cifre ale numărului canalului să nu fie relevante și sunt probabil doar zgomot, așa că vom distinge apăsările de tastă folosind doar cele 8 cifre superioare, cu alte cuvinte, va trebui să ne uităm doar la ADCH pentru a afla ce buton a fost apăsat. Înregistrați-vă, convertiți acel număr într-o valoare a tastaturii, apoi trimiteți acea valoare către LED-urile noastre de analizor de registre, astfel încât să putem verifica dacă apăsarea unui „9”, va face ca LED-urile corespunzătoare „00001001” să se aprindă. deși trebuie să vedem mai întâi ce apare în ADCH atunci când apăsăm diferitele butoane. Deci, hai să scriem doar un simplu handler de întrerupere care trimite doar conținutul ADCH pe afișajul analizorului. Iată de ce avem nevoie:

ADC_int: lds analyzer, ADCH; încărcați valoarea ADCH în analizorul nostrubi EIFR, 0; ștergeți semnalizatorul de întrerupere extern, astfel încât să fie gata să meargă din nou

Până acum, ar trebui să puteți copia doar codul din analizorul nostru din tutorialul 5 și să adăugați această întrerupere și setările de comutare și să o rulați. Exercițiul 2: Scrieți codul și rulați-l. Verificați dacă afișați ADCH pe afișajul analizorului. Încercați să apăsați de mai multe ori aceeași apăsare de tastă. Obțineți întotdeauna aceeași valoare în ADCH?

Pasul 8: Hartați valorile apăsării tastelor

Hartați valorile apăsării tastelor
Hartați valorile apăsării tastelor

Ceea ce trebuie să facem acum este să convertim valorile din ADCH în numere corespunzătoare tastei care a fost apăsată. Facem acest lucru scriind conținutul ADCH pentru fiecare apăsare de tastă și apoi transformând-o într-un număr zecimal așa cum am făcut în imagine. În rutina noastră de gestionare a întreruperilor, vom lua în considerare o gamă întreagă de valori ca fiind corespunzătoare fiecărei apăsări de taste, astfel încât ADC să mapeze orice din acea gamă la o anumită apăsare de tastă.

Exercițiul 3: Faceți acest mapare și apoi scrieți din nou rutina de întrerupere ADC.

Iată ce am primit pentru al meu (probabil că al tău va fi diferit). Observați că l-am configurat cu o serie de valori pentru fiecare apăsare de tastă.

ADC_int:; Analizor handlerclr de întrerupere externă; pregătiți-vă pentru noul număr de butoane H, ADCH; Actualizări ADC când se citește ADCH butonul clccpi H, 240brlo PC + 3; dacă ADCH este mai mare, atunci este un analizor 1ldi, 1; deci analizor de sarcină cu 1rjmp return; și returnează butonul clccpi H, 230; dacă ADCH este mai mare atunci un analizor 2brlo PC + 3ldi, 2rjmp return clccpi buttonH, 217brlo PC + 3ldi analyzer, 3rjmp return clccpi buttonH, 203brlo PC + 3ldi analyzer, 4rjmp return clccpi buttonH, 187brlo PC + 3ldi analyzer, 5rjmp return clccpi buttonH, Analizor 155brlo PC + 3ldi, 6rjmp return clccpi buttonH, 127brlo analizor PC + 3ldi, 255; vom seta blițul ca toate butoanele de returnare onrjmp clccpi H, analizor 115brlo PC + 3ldi, butonul de returnare clrpi 7rjmp H, 94brlo PC + analizor 3ldi, 8rjmp butonul de returnare clccpiH, analizor 62brlo PC + 3ldi, 0b11110000; asterisc este jumătatea superioară a butonului clccpi return Hr, 28brlo PC + 3ldi analizor, 0rjmp return clccpi buttonH, 17brlo PC + 3ldi analizor, 0b00001111; semnul hash este jumătatea inferioară onrjmp return clccpi buttonH, 5brlo PC + 3ldi analyzer, 0b11000011; reapelarea este top 2 bottom 2rjmp return ldi analyzer, 0b11011011; altfel a apărut o eroare return: reti

Pasul 9: Cod și videoclip pentru versiunea 1

Am atașat codul meu pentru această primă versiune a driverului tastaturii. În aceasta trebuie să apăsați tasta și apoi să apăsați butonul pentru a determina ADC să citească intrarea de pe tastatură. Ceea ce am prefera este să nu avem niciun buton, dar în schimb semnalul pentru a face conversia provine de la apăsarea tastelor în sine. Exercițiul 3: Asamblați și încărcați acest cod și încercați-l. Este posibil să fie necesar să modificați diferitele praguri de conversie pentru a corespunde tensiunilor de apăsare a tastelor, deoarece acestea diferă probabil de ale mele. Ce se întâmplă dacă încercați să utilizați o intrare de la tastatură atât pentru ADC0, cât și pentru pinul de întrerupere extern în loc de printr-un buton? Voi atașa, de asemenea, un videoclip cu funcționarea acestei prime versiuni a driverului nostru de apăsare a tastelor. Veți observa că în codul meu există o secțiune de inițializare a indicatorului Stack. Există diferite registre pe care este posibil să vrem să le împingem și să le scoatem din stivă atunci când manipulăm variabile și ce-nu și există, de asemenea, registre pe care am putea dori să le salvăm și să le restaurăm ulterior. De exemplu, SREG este un registru care nu este păstrat între întreruperi, astfel încât diferitele semnalizatoare care sunt setate și șterse ca urmare a operațiilor pot fi modificate dacă o întrerupere apare în mijlocul a ceva. Deci, este mai bine dacă apăsați SREG pe stivă la începutul unui handler de întrerupere și apoi îl scoateți din nou la sfârșitul handlerului de întrerupere. L-am plasat în cod pentru a arăta cum este inițializat și pentru a anticipa cum vom avea nevoie de el mai târziu, dar deoarece nu ne pasă ce se întâmplă cu SREG în timpul întreruperilor din codul nostru, nu am folosit stiva pentru acest lucru. că am folosit operația shift pentru a seta diferiți biți în registre la inițializare. De exemplu, în linie:

ldi temp, (1 <> sts EICRA, temp

Comanda „<<” din prima linie de cod de mai sus este o operație de schimbare. Prinde în esență numărul binar 1, care este 0b00000001 și îl deplasează la stânga cu numărul ISC01. Aceasta este poziția bitului numit ISC01 în registrul EICRA. Deoarece ISC01 este bitul 1, numărul 1 este deplasat în poziția 1 din stânga pentru a deveni 0b00000010. În mod similar, al doilea, ISC00, este bitul 0 al EICRA și deci deplasarea numărului 1 este zero poziții spre stânga. Dacă priviți, aruncați o altă privire asupra fișierului m328Pdef.inc pe care l-ați descărcat în primul tutorial și de când utilizați evrr, veți vedea că este doar o listă lungă de instrucțiuni ".equ". Veți găsi că ISC01 este egal cu 1. Asamblatorul înlocuiește fiecare instanță a acestuia cu 1 înainte de a începe chiar să asambleze ceva. Ele sunt doar nume pentru biți de registru pentru a ne ajuta pe oameni să citim și să scriem cod. Acum, linia verticală dintre cele două operații de schimbare de mai sus este o operație logică „sau”. Iată ecuația:

0b00000010 | 0b00000001 = 0b00000011

și asta încărcăm (folosind „ldi”) în temp. Motivul pentru care oamenii folosesc această metodă pentru a încărca valori într-un registru este că permite utilizării numelui bitului în loc de doar un număr, ceea ce face ca codul să fie mult mai ușor de citit. Există, de asemenea, alte două tehnici pe care le-am folosit. Folosim instrucțiunile „ori” și „andi”. Acestea ne permit să SETăm și CLEAR biți, fără a schimba niciunul din ceilalți biți dintr-un registru. De exemplu, când am folosit

ori temp, (1

această temperatură "sau" cu 0b00000001 care pune un 1 în bitul zero și lasă toate celelalte neschimbate. Tot atunci când am scris

andi temp, 0b11111110

acest lucru schimbă bitul zero de temperatură la 0 și lasă toate celelalte neschimbate.

Exercițiul 4: ar trebui să parcurgeți codul și să vă asigurați că înțelegeți fiecare linie. S-ar putea să vă fie interesant să găsiți metode mai bune pentru a face lucruri și să scrieți un program mai bun. Există o sută de modalități de codificare a lucrurilor și sunt destul de încrezător că puteți găsi o modalitate mult mai bună decât a mea. S-ar putea să găsiți și erori și omisiuni (Doamne ferește!). În acest caz, aș dori cu siguranță să aud despre ele pentru a putea fi remediate.

Bine, acum să vedem dacă putem scăpa de acel buton de prisos …

Pasul 10: Cod pentru versiunea 2

Cea mai simplă modalitate de a scăpa de buton este doar să îl eliminați complet, să uitați de intrarea în PB2 și să comutați ADC la „Free Running Mode”.

Cu alte cuvinte, pur și simplu schimbați registrul ADCSRB astfel încât ADTS2, ADTS1 și ADTS0 să fie toate zero.

Apoi setați bitul ADSC în ADCSRA la 1, care va începe prima conversie.

Acum încărcați-l pe microcontroler și veți găsi că numărul corect apare pe afișaj în timp ce apăsați butonul și numai în timp ce apăsați butonul. Acest lucru se datorează faptului că ADC eșantionează continuu portul ADC0 și afișează valoarea. Când scoateți degetul de pe buton, „butonul sărit” va face ca câteva valori aleatorii să apară foarte repede și apoi se va regăsi la intrarea 0V. În codul nostru avem acest 0V care apare ca 0b11011011 (deoarece apăsarea tastei „0” utilizează deja valoarea de afișare 0b00000000)

Aceasta nu este soluția pe care o dorim din două motive. Mai întâi nu vrem să ținem apăsat butonul. Vrem să îl apăsăm o dată și să afișăm numărul (sau să fie folosit într-un cod nou într-un tutorial ulterior). În al doilea rând, nu vrem să probăm continuu ADC0. Vrem să facă o singură lectură, să o convertească și apoi să adoarmă până când o nouă apăsare de tastă declanșează o nouă conversie. Modul de rulare liber este cel mai bun dacă singurul lucru pe care doriți să-l facă microcontrolerul este să citiți continuu unele intrări analogice - de exemplu, dacă doriți să afișați temperaturi în timp real sau altele.

Deci, să găsim încă o soluție …

Pasul 11: Cum scăpăm de buton? Versiunea 3

Cum scăpăm de buton? Versiunea 3
Cum scăpăm de buton? Versiunea 3

Există numeroase modalități prin care am putea proceda. Mai întâi am putea adăuga hardware pentru a scăpa de buton. De exemplu, putem încerca să punem un tranzistor în circuit la linia de ieșire a apăsării tastei, astfel încât să ia un mic flux de curent de la ieșire și să trimită un impuls de 5V la pinul de întrerupere PD2.

Cu toate acestea, cel puțin probabil ar fi prea zgomotos și, în cel mai rău caz, nu ar permite suficient timp pentru o citire exactă a apăsării tastei, deoarece ieșirea de tensiune a tastaturii nu ar avea timp să se stabilizeze înainte de captarea citirii ADC.

Deci, am prefera să venim cu o soluție software. Ce ne-ar plăcea să facem este să adăugăm o întrerupere pe pinul PD2 și să scriem un handler de întrerupere pentru acesta, care apelează o singură citire a pinului tastaturii. Cu alte cuvinte, scăpăm de întreruperea de declanșare automată de la ADC și adăugăm o întrerupere externă care apelează ADC în interiorul său. În acest fel, semnalul pentru citirea ADC vine după ce semnalul PD2 a apărut deja și acest lucru ar putea oferi lucrurilor suficient timp pentru a stabiliza o tensiune precisă înainte ca pinul PC0 să fie citit și convertit. Am avea în continuare o întrerupere de finalizare ADC care transmite rezultatul pe afișajul analizorului la sfârșit.

Are sens? Ei bine, să o facem …

Aruncați o privire la noul cod atașat.

Vedeți următoarele modificări:

  1. Am adăugat un rjmp la adresa.org 0x0002 pentru a gestiona întreruperea externă INT0
  2. Am schimbat registrul EIMSK pentru a indica că dorim să întrerupem pe pinul INT0
  3. Am schimbat pinul ADATE din registrul ADCSRA pentru a dezactiva declanșarea automată
  4. Am scăpat de setările ADCSRB, deoarece acestea sunt irelevante atunci când ADATE este dezactivat
  5. Nu mai trebuie să resetăm semnalizatorul de declanșare extern, deoarece rutina de întrerupere INT0 face acest lucru automat când se finalizează - anterior nu aveam o rutină de întrerupere, doar am declanșat ADC-ul unui semnal la acel pin, așa că a trebuit să curățați steagul cu mâna.

Acum, în gestionarul de întreruperi, numim pur și simplu o singură conversie din ADC.

Exercițiul 5: Rulați această versiune și vedeți ce se întâmplă.

Pasul 12: Cod și videoclip pentru versiunea de lucru

Așa cum am văzut în ultima versiune, întreruperea butonului nu funcționează foarte bine, deoarece întreruperea este declanșată pe o margine ascendentă la pinul PD2 și apoi gestionarul de întrerupere apelează conversia ADC. Cu toate acestea, ADC obține apoi tensiunea citită înainte de a se stabiliza și astfel citește prostii.

Avem nevoie să introducem o întârziere între întreruperea de pe PD2 și citirea ADC pe PC0. Vom face acest lucru adăugând un temporizator / contor, o întrerupere a depășirii contorului și o rutină de întârziere. Din fericire știm deja cum să facem acest lucru din Tutorialul 3! Deci, vom copia și lipi codul relevant de acolo.

Am dat codul rezultat și un videoclip care îl arată în funcțiune.

Veți observa că citirile nu sunt la fel de exacte pe cât s-ar spera. Acest lucru este probabil din cauza mai multor surse:

  1. atingem de la ieșirea de tensiune a tastaturii pentru a declanșa pe PD2, care afectează citirea în PC0.
  2. nu știm cu adevărat cât timp să întârziem după declanșare pentru a obține cea mai bună lectură.
  3. durează câteva cicluri pentru ca conversia ADC să se finalizeze, ceea ce înseamnă că nu putem declanșa rapid tastatura.
  4. probabil există zgomot în tastatura însăși.
  5. etc …

Deci, deși am reușit să punem tastatura în funcțiune, și acum am putea să o folosim în aplicații folosind valorile apăsării tastelor în alt mod în loc să le trimitem doar pe afișajul analizorului, nu este foarte precisă și este foarte enervant. De aceea, cred că cel mai bun mod de a conecta tastaturile este pur și simplu să lipiți fiecare ieșire de la tastatură într-un alt port și să decideți ce tastă este apăsată prin care porturi văd o tensiune. Este ușor, foarte rapid și foarte precis.

De fapt, există doar două motive pentru care cineva ar dori să conducă o tastatură așa cum am făcut aici:

  1. Folosește doar 2 pini pe microcontrolerul nostru în loc de 8.
  2. Este un proiect minunat de a arăta diferite aspecte ale ADC pe microcontroler, care este diferit de lucrurile standard pe care le puteți găsi acolo, cum ar fi citirile de temperatură, potențiometrele de rotație, etc. mai degrabă decât să ruleze gratuit modul de înghițire a procesorului.

Oricum, iată câteva ultime exerciții pentru dvs.:

Exercițiul 6: Rescrieți tratamentul de întrerupere complet al conversiei ADC pentru a utiliza un tabel de căutare. Adică Pentru a testa valoarea analogică cu primul element din tabel și dacă este mai mare, se întoarce de la întrerupere, dacă nu este, crește Z la următorul element din tabel și se ramifică din nou la test. Acest lucru va scurta codul și va curăța rutina de întrerupere și va face să arate mai frumos. (Voi oferi o posibilă soluție ca pas următor) Exercițiul 7: conectați tastatura la 8 pini de pe microcontroler și scrieți driverul simplu pentru acesta și experimentați cât de frumos este. Vă puteți gândi la câteva moduri de a face ca metoda noastră să funcționeze mai bine?

Asta este totul pentru acest tutorial. Am atașat versiunea finală cu indicii. Pe măsură ce ne apropiem de obiectivul nostru final, vom folosi încă o dată tastatura în Tutorialul 9 pentru a arăta cum să controlăm șapte afișaje de segmente cu acesta (și să construim ceva interesant care să utilizeze tastele suplimentare de pe tastatura telefonului) și apoi vom treceți la controlul lucrurilor cu apăsarea pe buton (deoarece această metodă se potrivește mai bine cu produsul final pe care îl construim cu aceste tutoriale) și vom purta doar tastatura.

Ne vedem data viitoare!

Recomandat: