Table of Contents

Calculator Aritmetic

Calculator aritmetic cu facilităţi avansate, implementat cu ATmega32.

Introducere

Proiectul ales de mine este un calculator aritmetic cu funcţii avansate. Scopul în sine al proiectului este mai mult unul didactic, deoarece pe piaţă există foarte multe modele compacte de calculatoare de buzunar.

Ideea de la care am plecat este simplă: întotdeauna mi-am dorit să ştiu cum se construieşte un calculator de buzunar.

Deşi nu cred ca ar avea o utilitate reală practică, datorită suprasaturării acestei pieţe, totuşi consider că proiectul este un foarte bun proof of concept şi totodata îl consider a fi extrem de util pentru mine în mod special, prin acumularea de noi cunoştiinte în domenul embedded.

Nu în ultimul rând, să nu uităm totuşi că puterea dispozitivelor de calcul de pe vremea când Neil Armstrong a păşit pentru prima dată pe lună, este comparabilă cu cea a calculatorului construit de mine, astazi! :-D

Descriere generală

Schema bloc a proiectului este:

Schema bloc a proiectului.

Calculatorul are 32 de taste. Ele sunt alocate astfel: Alocare taste calculator.

Am ales microcontrollerul ATmega32 datorită spaţiului mai mare de memorie pus la dispoziţie.

În momentul în care memorăm un număr (Memory Store), LED-ul se aprinde. Iar când eliberăm memoria (Memory Clear), LED-ul se stinge.

Hardware Design

Pe lângă componentele pentru plăcuţa de baza, a mai fost necesar să cumpăr:

Schema electrică a plăcuţei de bază este:

Schema electrică a plăcuţei de bază.

Schema electrică a componentelor din etapa a doua a proiectului este:

Schema electrică a componentelor pentru etapa a doua a proiectului.

Pentru alimentarea ecranului LCD, am legat:

Schema tastaturii 4x4 este:

Schema tastaturii 4x4.

Datorită faptului că pinii 16 (PD2) şi 17 (PD3) ai microcontrollerului sunt legaţi atât la una din tastaturi, cât şi la pinii de date ai mufei USB, pentru o funcţionare corectă, trebuie ca alimentarea în timpul utilizării să se facă exclusiv utilizând un adaptor de curent continuu.

Software Design

Am lucrat în Windows 7 Professional 32bit. Mi-am instalat Cygwin pentru simularea mediului Linux în line de comandă Windows şi WinAVR pentru compilarea bootloaderului şi a programului în sine. Am copiat executabilul avrusbboot.exe in directorul C:\Windows, pentru a îl putea accesa cu uşurinţă din orice alt director. Ca editor, am folosit Editra.

Codul scris de mine este bogat în comentarii, astfel încat să poată fi uşor de înteles. Practic, programul scris de mine simulează existenţa unor regiştrii.

Funcţia main() arată astfel:

int main()
{
  char key;
 
  LCD_init();	
  init();	        //initializari
 
  DDRB |= (1<<PB4); 	//setam portul ledului ca fiind de output
  PORTB &= ~(1<<PB4);   //stingem LEDul
 
  //initializam tastatura 1
  keyportddrD = 0xF0;		//setam PD4 PD5 PD6 PD7 ca fiind de output si PD0 PD1 PD2 PD3 de input
  keyportD = 0x0F; 		//setam rezistenta de pullup pe PD0 PD1 PD2 PD3
 
  //initializam tastatura 2
  keyportddrC = 0xF0;		//setam PC4 PC5 PC6 PC7 ca fiind de output si PC0 PC1 PC2 PC3 de input
  keyportC = 0x0F;		//setam rezistenta de pullup pe PC0 PC1 PC2 PC3
 
  _delay_ms(DEBOUNCETIME);
 
  afiseaza();
 
  while (1)
  {
    key = get_key();
    if (key != FALSE)
    {
      key = translate_key(key);
      proceseaza(key);	         // procesam caracterul
      afiseaza();		 // afisam starea curenta 
    }
  }
  return 0;
}

API tastaturi:

char get_key();  	        //preia codul unei taste
char translate_key(char key); 	//translateaza codul unei taste intr-un caracter de trimis functiei proceseaza.

Prototipurile funcţiilor utilizate de calculator sunt:

//Nota preliminara: o tasta genereaza un caracter ([A-P] sau [a-p]).
 
void proceseaza(char input);          //functia preia un caracter de la tastatura si apeleaza functia de procesare corespunzatoare
void proceseazaCifra(char input);     //functia trateaza caracterele cifre
void proceseazaOperator(char input);  //functia trateaza tastele + - * / si ridicare la putere
void proceseazaEgal();		      //functia trateaza caracterul =
void marcheazaPunct();		      //functia trateaza tasta . (punct zecimal)
void C_CE();			      //functia trateaza caracterul (tasta) C/CE
void fTrigonometrice(char input);     //functia trateaza tastele sinus, cosinus, tangenta, cotangenta, arcsinus, arccosinus, arctangenta
void calculeazaRadical();	      //functia trateaza tasta radical
void schimbaSemn();		      //functia trateaza tasta de schimbare de semn +/-
void memorie(char input);	      //functia trateaza tastele "memory store", "memory read" si "memor clear"
void paranteze(char input);	      //functia trateaza caracterele ( )
 
void init();			      //functia se ocupa cu initializari de variabile
void afiseaza();		      //functia trimite un string catre API-ul ecranului
double calculeaza();		      //functia se ocupa de calculul a ceea ce se afla stocat in cei 3 registrii acum

În implementarea calculatorului, am utilizat variabile globale. Acestea sunt:

#define SIZESTIVA 20
 
//Nota preliminara: Programul simuleaza oarecum lucrul cu registri.
 
double reg[2];		          // Avem doi registrii pt operanzi. Registrul pentru operandul stang si cel pentru operandul drept.
char regOp;			  // Avem un al treilea registru pentru stocarea operatorului.
short int selReg;		  // Acest registru select ne spune cu care din cei 3 registrii de lucru operam la momentul respectiv.
short int stareReg[3];		  // Acest vector ne spune starea de incarcat/descarcat al celor 3 registrii
 
short int vfStiva;	          // Ne indica varful stivei si implicit numarul de elemente din stiva.
double rezStiva[SIZESTIVA];	  // Aici stocam operandul stang (rezultatul calculabil pana in momentul respectiv), adica primul registru de lucru.
char opStiva[SIZESTIVA];	  // Aici stocam operatorul pasului respectiv, adica al treilea registru de lucru.
 
double outputBuffer;		  // Valoarea afisata pe LCD.
short int buff_repr_rez_egal; 	  // Ne indica daca valoarea de pe ecran (deci din outputBuffer) a fost obtinuta in urma apasarii tastei egal.
 
unsigned long int mascaZecimale;  // Masca pentru zecimale: 1, 10, 100, etc.
short int punctActivat;		  // Ne indica daca s-a introdus un punct (tasta punct zecimal) de la tastatura.
 
short int contorInput;		  // Contorizeaza cate caractere au fost introduse, la introducerea unui numar.
 
short int C_CE_contor;		  // Contorizeaza numarul de apasari ale tastei C/CE.
 
double mem = 0;			  // Registru pentru memorare rezultat.
short int stareMem = 0;		  // Indica starea registrului mem.

Rezultate Obţinute

Plăcuţa finală:

Concluzii

În mare, am realizat ceea ce mi-am propus: un calculator aritmetic cu funcţii avansate, complet funcţional.

Pentru o viitoare îmbunătăţire a proiectului, se poate monta o baterie de 9 volti, care să confere portabilitate calculatorului.

Download

Descărcare arhivă zip cu codul sursă.

După ce se descarcă şi se despachetează arhiva zip, pentru compilare se foloseşte comanda make în consolă. Pentru programarea plăcuţei, se selectează din jumper alimentarea de la USB, se introduce cablul USB în plăcuţă, şi în maxim 30 de secunde cât rulează bootloaderul, se dă comanda avrusbboot calculator.hex.

După programare, se scoate cablul USB, se setează din jumper modul de alimentare pe adaptor, se introduce adaptorul şi se aşteaptă cele 30 de secunde până când bootloaderul predă execuţia programului nostru. În acest moment, cifra 0 ar trebui să apară pe ecranul LCD.

Bibliografie/Resurse

Pentru plăcuţa de bază:

Pentru partea a doua a proiectului:

Bootloader USB ATmega32:

Contact Autor

Data: 2 Iunie 2010