Proiectul consta in crearea unui dispozitiv ce va fi conectat intre tastatura si calculator prin intrari PS2. Acesta, in functie de combinatia de taste ce se apasa poate la alegere:
La placuta de baza de programare voi adauga o intrare PS2 tata si una mama pentru a putea fi conectat intre tastatura si calculator. De asemeni, conectez si un socket SD pentru a putea scrie si citi de pe card. Toate acestea vor fi controlate de controlerul ATMega16. Componente folosite:
Code Text
Diagrama generala:
Interfaţa cu tastatura este directă. Ceasul se leaga direct la INT0 (PD2) şi rutina de tratare a acestei întreruperi citeşte data de pe pinul 3 al portului D (PD3). Datele vor ieşi pe portul C. Eşantioanele sunt codificate pe 6 biţi pentru a permite mai multe taste apăsate simultan (maxim 3). Prin apăsarea a mai mult de o tastă se trimite la portul C suma eşantioanelor.
Diagrama de semnal:
Semnificatiile pinilor din mufa PS2:
Numerotarea pinilor pe cardul SD:
Iar semnificatiile lor sunt:
Pentru a initializa cardul setez ceasul de control SPI la 400kHz - necesar pentru compatibilitate cu majoritatea cardurilor SD si MMC. Apoi resetez cu comanda CMD0 activand inputul CS la nivelul L. Pentru comanda CMD0 byte-ul de CRC si argumentul zero are valoarea 0x95. Dupa bitul de asteptare din nivelul L, protocolul de handshake este terminat si asteapta in continuare comenzi. Dintre comenzile cele mai folosite si folositoare sunt si:
Interfatarea cu cardul SD se bazeaza pe o suita de functii definite care se ocupa cu initializarea sa precum si scrierea si citirea de pe card. De exemplu pentru functia de initializare:
void ini_SD(void) { char i; PORTB |= _BV(CS); //disable CS for(i=0; i < 10; i++) SPI_sendchar(0xFF); // Send 10 * 8 = 80 clock pulses 400 kHz PORTB &= ~(_BV(CS)); //enable CS for(i=0; i < 2; i++) SPI_sendchar(0xFF); // Send 2 * 8 = 16 clock pulses 400 kHz Command(0x40,0,0,0x95); // reset idle_no: if (Command(0x41,0,0,0xFF) !=0) goto idle_no; //idle = L? SPCR &= ~(_BV(SPR0)); //fosc/4 }
Care se foloseste de wrappere pentru a simplifica codul:
SPI_sendchar este facuta analog cu functiile facute la laborator pentru trimiterea unui caracter:
char SPI_sendchar(char chr) { char receivedchar = 0; SPDR = chr; while(!(SPSR & (1<<SPIF))); receivedchar = SPDR; return (receivedchar); }
Functia de setare a comenzii se face prin trimiterea mai multor caractere consecutive:
char Command(char cmd, uint16_t ArgH, uint16_t ArgL, char crc ) { SPI_sendchar(0xFF); SPI_sendchar(cmd); SPI_sendchar((uint8_t)(ArgH >> 8)); SPI_sendchar((uint8_t)ArgH); SPI_sendchar((uint8_t)(ArgL >> 8)); SPI_sendchar((uint8_t)ArgL); SPI_sendchar(crc); SPI_sendchar(0xFF); return SPI_sendchar(0xFF); // Returns the last byte received }
Nu am ajuns atat de departe.