2.3.
Pinout-ul plăcii de dezvoltare
LCD Displays
Character LCD GPIO Pin
RS PC0
RW PC1
EN PC2
D4 PC3
D5 PC4
D6 PC5
D7 PC6
Backlight PC7
GPIO
Graphical LCD
Pin
CS PB0
RST PB1
A0 PB4
SDA PB5
SCK PB7
Backlight PA7
I2C Sensors & Bus Addresses
I2C GPIO Pin Chip Address
I2C Enable PA6 LSM9DS0 0x1D (XM) 0x6B (G)
SCL PC0 MPL3115A2 0x60
SDA PC1
SD Card
GPIO Pin
CS PA2
MOSI PB5
MISO PB6
SCK PB7
RGB LED
GPIO Pin
Red PD5
Green PD7
Blue PB3
Miscellaneous
GPIO Pin
Temperature Sensor PA0
Ambient Light Sensor PA1
Buttons (BTN1 - 6) PA5
BTN 1 PB2
BTN 2 PD6
Speaker PD4
Pentru a scrie o valoare într-un registru se poate face direct atribuirea unei valori, însă acest mod
nu face codul foarte ușor de înteles. Recomandarea noastră este de a folosi măștile pe biți ((1 <<
x)) sau macro-ul _BV(x). De asemenea recomandăm folosirea numelui pinului în loc de indexul
acestuia, pentru că numele acestora sunt sugestive pentru funcția pe care o îndeplinesc (spre
exemplu, în registrul ADCSRA al convertorului analog-digital, bitul ADEN este bitul de enable).
Numele pinilor, ca și în cazul registrelor, sunt deja definite în avr-libc.
Operație Formă
Scriere bit pe 1 macro |= (1 << bit_index)
Scriere bit pe 0 macro &= ~(1 << bit_index)
Toggle bit macro ^= (1 << bit_index)
Citire bit macro & (1 << bit_index)
Exemplu: Lucrul cu registre
DDRB = 8; // AȘA NU.
DDRB = (1 << 3); // Nici așa, este hardcodat indexul pinului.
DDRB |= (1 << PB3); // AȘA DA.
DDRB |= _BV(PB3); // AȘA DA.
3.3. Registrele de I/O
Pentru acest laborator v-am scutit de căutarea în datasheet, lucru ce poate părea complicat la
început și am sintetizat, pentru voi, ce adrese de memorie (registre) trebuie să modificați pentru
lucrul în acest laborator.
Microntroller-ul ATmega324 oferă 4 porturi I/O a câte 8 pini, iar intern, fiecare port are asociate
trei registre a câte 8 biți prin care utilizatorul poate controla la nivel de pin fluxul datelor: poate
scrie/citi date în/din portul respectiv. Aceste trei registre sunt:
• DDRn - Data Direction Register
o stabilește direcţia pinilor portului
o dacă bitul x are valoarea 0 atunci pinul x este de intrare
o dacă bitul x are valoarea 1 atunci pinul x este de ieșire
• PORTn - Data Register
o stabilește valorile de ieşire ale pinilor sau activează/dezactivează rezistenţele de
pull-up
o dacă bitul x are valoarea 0 atunci
▪ dacă pinul x este de ieșire el va avea valoarea LOW
▪ daca pinul x este de intrare rezistența de pull-up va fi dezactivată
o data bitul x are valoarea 1 atunci
▪ daca pinul x este de ieșire el va avea valoarea HIGH
▪ dacă pinul x este de intrare rezistența de pull-up va fi activată
• PINn - Input Pins Address
o daca pinul este de input, putem citi date de pe portul respectiv
▪ dacă pinul x are valoarea LOW atunci bitul x va avea valoarea 0
▪ dacă pinul x are valoarea HIGH atunci bitul x va avea valoarea 1
o dacă pinul este de output, putem face toggle automat
▪ dacă scriem la bitul x valoarea 1, bitul echivalent din PORTn se va nega
automat (adică facem toggle la starea pinului automat)
n poate să fie A, B, C sau D în funcţie de portul selectat. x poate să fie între 0 și 7.
Descrierea detaliată a porturilor şi registrelor corespunzătoare acestora se găseşte în datasheet-ul
ATmega324, în capitolul I/O Ports.
3.3.1. Exemplu de lucru cu ieșiri
Să presupunem că avem un LED legat la pinul 1 al portului B (numit PORTB1 sau PB1). Pentru a
aprinde sau stinge LED-ul trebuie să urmăm următorii pași:
• Pinul PB1 trebuie configurat ca ieșire
o Bitul 1 (PB1) din registrul DDRB va fi 1
o DDRB |= (1 « PB1);
• Pentru a aprinde LED-ul trebuie ca pinul PB1 să ia valoarea HIGH
o Bitul 1 (PB1) din registrul PORTB va fi 1
o PORTB |= (1 « PB1);
• Pentru a stinge LED-ul trebuie ca pinul PB1 să ia valoarea LOW
o Bitul 1 (PB1) din registrul PORTB va fi 0
o PORTB &= ~(1 « PB1);
3.3.2. Exemple de lucru cu intrări
Să presupunem ca avem un buton legat la pinul 4 al portului D (numit PORTD4 sau PD4), din
cazul b) prezentat anterior. Pentru a determina starea butonului (apăsat sau liber) trebuie să
urmăm următorii pași:
• Pinul PD4 trebuie configurat ca intrare
o Bitul 4 (PD4) din registrul DDRD va fi 0
o DDRD &= ~(1 « PD4);
• Pentru a determina starea de apăsare a butonului trebuie să citim valoarea pinului la care
este atașat. Acesta va fi 1 atunci când butonul este liber și 0 atunci când butonul este
apăsat
o Citim valoarea bitului 4 (PD4) din registrul PIND
o char val = PIND & (1 « PD4);
o
• #include <avr/io.h>
• #include <util/delay.h>
•
• int main() {
• /* Setăm pinul 7 al portului D ca pin de ieșire. */
• DDRD |= (1 << PD7);
•
• while(1) {
• /* Inversăm starea pinului. */
• PORTD ^= (1 << PD7);
• _delay_ms(500);
• }
•
• return 0;
• }