Documente Academic
Documente Profesional
Documente Cultură
Seciuni lucrare:
Modaliti de conectare a unui buton
Modaliti de manipulare software a intrrilor digitale
Exemplu de manipulare software a intrrilor digitale
Exemplu de numrtor pe dou caractere
Exemplu de cronometru cu activare direct a
sistemului de ntreruperi
45
Modaliti
Modaliti de interconectare a unui buton
Butoanele i comutatoarele (butoane
butoane fr revenire) reprezint cele mai simple exemple
de intrri pentru un sistem embedded. Astfel de dispozitive sunt capabile s trag n 0
logic sau 1 logic un pin de intrare de uz general semnaliznd n acest mod sistemului
o comand sau o condiie
ie de intrare.
Imaginea de mai jos prezint schema clasic de conectare a trei butoane la trei pini de
intrare a plcii Arduino (Buton 1 PIN2, Buton 2 PIN3, Buton 3 PIN4) cu comand
pe 0 logic la apsarea unui buton starea pin
pin-ului
ului de intrare va trece din 1 logic n
0 logic.
46
47
Modaliti
Modaliti de manipulare software a intrrilor
Mediul Arduino IDE pune la dispoziia programatorului funcia digitalRead(pin)
care returneaz starea pinului dorit. Pinul citit se poate configura n prealabil ca fiind de
intrare pinMode(pin, INPUT) dar avnd n vedere faptul c dup reset toii pinii
microcontrolerului sunt configurai implicit ca intrri acest lucru nu este obligatoriu dect
n cazul n care pinul respectiv a fost configurat anterior ca ieire.
Plecnd de la schema din seciunea anterioar (cu sau fr debouncing hardware dar
cu rezisten extern de pull-up) se poate testa programul urmtorul program pentru o
exemplificare a funciei digitalRead .
const int buton1 = 2;
const int buton2 = 3;
const int buton3 = 4;
int a1 = 0;
int a2 = 0;
int a3 = 0;
void setup() {
pinMode(buton1, INPUT);
pinMode(buton2, INPUT);
pinMode(buton3, INPUT);
Serial.begin(9600);
}
void loop(){
if (digitalRead(buton1) == LOW) {
a1++;
Serial.print("Butonul 1 s-a apasat butonul de ");
Serial.print(a1,DEC);
Serial.print(" ori.");
Serial.println();
//debouncing software
delay(200);}
if (digitalRead(buton2) == LOW) {
a2++;
Serial.print("Butonul 2 s-a apasat butonul de ");
Serial.print(a2,DEC);
Serial.print(" ori.");
Serial.println();
//debouncing software
delay(200);}
48
if (digitalRead(buton3) == LOW) {
a3++;
Serial.print("Butonul 3 s-a apasat butonul de ");
Serial.print(a3,DEC);
Serial.print(" ori.");
Serial.println();
//debouncing software
delay(200);
}
}
Se observ c citirea celor trei butoane presupune o bucl infinit care verific continuu
starea pinilor la care sunt conectate cele trei butoane i afieaz pe serial numrul de
apsri al fiecrui buton n parte. Se mai observ c programul introduce i un
debouncing software (o mic ntrziere dup declanarea fiecrei apsri de buton)
pentru a nu prinde evenimentul n mod eronat de mai multe ori. Se poate experimenta i
observa efectul nlturrii debouncing-ului software
O alt modalitate de a prinde un eveniment de tip nchidere circuit / apsare buton se
poate face i prin utilizarea ntreruperilor externe. Mediul Arduino IDE pune la dispoziia
programatorului funcia attachInterrupt(ntrerupere, isr_asociat, mod)
care permite manipularea celor dou ntreruperi externe INT0 i INT1 ale
microcontrolerului. Din pcate acestea sunt singurele ntreruperi care sunt accesibile
prin intermediul limbajului de baz al mediului Arduino IDE. Butoanele trebuie s fie
conectate la pinii 2 (INT0) i 3 (INT1) ai plcii Arduino. Parametrii funciei sunt:
ntrerupere - 0 pentru INT0 i 1 pentru INT1, isr_asociat numele unei proceduri care
s trateze apariia ntreruperii i mod specific evenimentul extern la care s se
declaneze ntreruperea LOW (pinul devine 0 logic), FALLING (pinul trece din 1 n
0), RISING (pinul trece din 0 n 1) sau CHANGE (orice tip de tranziie la buton
acest mod va conduce la declanare dubl la fiecare apsare). Funcia pereche
detachInterrupt(ntrerupere) permite dezactivarea ntreruperii activate cu
ajutorul funciei precedente. Pentru testarea celor dou funcii se poate rula programul
urmtor utiliznd aceiai schem electric efectul programului este identic cu cel
precedent.
include <avr/io.h>
const int buton3 = 4;
volatile int a1 = 0;
volatile int a2 = 0;
int a3 = 0;
49
void setup() {
attachInterrupt(0,ISR_b1,FALLING);
attachInterrupt(1,ISR_b2,FALLING);
Serial.begin(9600);
}
void loop(){
if ((PIND & (1<<buton3))==0) {
a3++;
Serial.print("Butonul 3 s-a apasat butonul de ");
Serial.print(a3,DEC);
Serial.print(" ori.");
Serial.println();
//debouncing software
delay(200);
}
}
void ISR_b1() {
a1++;
Serial.print("Butonul 1 s-a apasat de ");
Serial.print(a1,DEC);
Serial.print(" ori.");
Serial.println();
//debouncing software
delay(400);
}
void ISR_b2() {
a2++;
Serial.print("Butonul 2 s-a apasat de ");
Serial.print(a2,DEC);
Serial.print(" ori.");
Serial.println();
//debouncing software
delay(400);
}
Sistemul de ntreruperi este folosit doar pentru butonul 1 (pin2 INT0) i butonul
2 (pin3 INT1) deoarece funcia attachInterrupt nu permite definirea de
ntreruperi externe pe ali pini. Citirea butonului 3 se face n continuare n bucla
infinit principal.
50
51
Serial.print(a1,DEC);
Serial.print(" ori.");
Serial.println();
Serial.print("Butonul 2 s-a apasat de ");
Serial.print(a2,DEC);
Serial.print(" ori.");
Serial.println();
Serial.print("Butonul 3 s-a apasat de ");
Serial.print(a3,DEC);
Serial.print(" ori.");
Serial.println();
delay(1000);
}
ISR(INT0_vect) {
a1++;
_delay_ms(400);
}
ISR(INT1_vect) {
a2++;
_delay_ms(400);
}
ISR(PCINT2_vect) {
a3++;
_delay_ms(1000);
}
52
de buton 3 va fi prins de dou ori, lucru care poate fi evitat prin mrirea temporizrii de
debounce software.
Funciile ISR pentru cele trei ntreruperi trebuie declarate de forma ISR(INT_vect)
unde INT_vect va fi INT0_vect, INT1_vect, PCINT2_vect. [17]
n cazul ISR-urilor reale (nu generate de mediul Arduino) sistemul de ntreruperi este
dezactivat pe durata execuiei ISR-ului (pentru ca un ISR s nu ntrerup un alt ISR).
Pentru a preveni blocarea programului (n ISR) nu trebuie folosite n cadrul unui ISR
funciile puse la dispoziie de mediul Arduino. De exemplu, utilizarea funciei delay n
cadrul unui ISR (pentru debouncing-ul software) va conduce la blocarea programului
deoarece aceast funcie utilizeaz ntreruperea asociat timer-ului 0 apelat ntr-un
context de dezactivare a sistemului de ntreruperi va introduce un delay infinit
ntreruperea asociat timer-ului 0 nu se va declana niciodat. Aceast funcie poate fi
nlocuit cu macro-ul _delay_ms(nr_ms) prezent n biblioteca util/delay.h .
53
54
int
int
int
int
int
int
latchPin1 = 7;
clockPin1 = 8;
dataPin1 = 9;
latchPin2 = 10;
clockPin2 = 11;
dataPin2 = 12;
55
ISR(INT0_vect) {
if (digit1==9) {
if (digit2==9) {
digit1=0;
digit2=0;
}
else {
digit1=0;
digit2++;
}
}
else digit1++;
_delay_ms(400);
}
ISR(INT1_vect) {
if (digit1==0) {
if (digit2==0) {
digit1=9;
digit2=9;
}
else {
digit1=9;
digit2--;
}
}
else digit1--;
_delay_ms(400);}
ISR(PCINT2_vect) {
digit1 = 0;
digit2 = 0;
_delay_ms(400);
}
int
int
int
int
int
int
latchPin1 = 7;
clockPin1 = 8;
dataPin1 = 9;
latchPin2 = 10;
clockPin2 = 11;
dataPin2 = 12;
57
void loop(){
digitalWrite(latchPin1, LOW);
shiftOut(dataPin1, clockPin1, MSBFIRST, numbers[digit1]);
digitalWrite(latchPin1, HIGH);
digitalWrite(latchPin2, LOW);
shiftOut(dataPin2, clockPin2, MSBFIRST, numbers[digit2]);
digitalWrite(latchPin2, HIGH);
delay(1000); }
ISR(TIMER1_OVF_vect) {
if (digit1==9) {
if (digit2==9) {
digit1=0;
digit2=0;
}
else {
digit1=0;
digit2++;
}
}
else digit1++;
}
ISR(INT0_vect) {
_delay_ms(400);
//pornire timer FCPU/256
TCCR1B |= (1 << CS12);
}
ISR(INT1_vect) {
TCCR1B = 0;
_delay_ms(400);}
ISR(PCINT2_vect) {
digit1 = 0;
digit2 = 0;
_delay_ms(400);
}
Activarea ntreruperii de timer overflow pentru timer-ul 1 se face setnd bitul TOIE1 n
registrul TIMSK1. Pentru pornirea i configurarea timer-ului 1 se seteaz biii CS12,
CS11, CS10 din registrul TCCR1B n funcie de modul dorit. Oprirea timer-ului 1 se face
trecnd CS12, CS11, CS10 pe 0. Se recomand ca iniializare TCCR1A = 0 i TCCR1B
58
59