luni, 23 decembrie 2013

LEDURI, BUTOANE SI XC8 (Partea III)


Dupa cum am zis in postarea trecuta voi incerca sa atasez fiecarui buton cate o functie care sa aprinda ledurile conectate la PORTB intr-un anumit mod.

     In postarea de astazi am atsat butoanelor 1,2,3,4 cate o functie astfel:


  1. Butonul 1 : aprinde pe rand cate un led ("shifteaza" la stanga PORTB de la valoarea 1 la 128 ) ;
  2. Butonul 2 : aprinde pe rand cate un led ("shifteaza" la dreapta PORTB de la valoarea 128 la 1 ) ;
  3. Butonul 3 : combina cele doua functii de mai sus ;
  4. Butonul 4 : aprinde doua leduri si shifteaza pe rand la stanga si la drepta PORTB.
     Programul inital se modifca, fiind adaugate pe langa functiile asociate fiecarui buton inca doua functii, sa zicem ceva mai speciale. Sa vedem intai codul modifcat si apoi sa comentam putin aspectele mai interesante.





     In functia main() nu se modifica nimic iar in scan() in loc sa aprindem ledurile direct pe PORTB atsasam fiecarei apsari de buton functia aferenta. Dupa cum am zis in postarea anterioara apasarea unei taste se verifica prin operatia XOR "char button=PORTD^shifter" . Daca rezultatul nu este "0" atunci inseamna ca o tasta a fost apasata. Intre timp, daca utilizatorul este foarte rapid, exista posibilitatea ca PORTD sa revina la valoarea initiala, asa ca este necesara reconstructia valorii PORTD din momentul apsarii tastei.

      Acest lucru se realizeaza prin utilizarea operatorului OR in operatia "char a=button|shifter". Acum ca stim valoarea apelam functia asociata butonului. Aceasata ia ca parametru valoare "a"  adica valoarea lui PORTD din momentul apasarii butonului. De ce? Pentru ca asa cum vom vedea mai departe la inca o apasare a aceluiasi buton functia asociata acestuia isi va opri executia.

     In cele ce urmeaza voi explica doar modul in care functioneaza functia  "keypad1(unsigned char a)".
     Dupa apasarea butonnului 1 programul va incerca sa execute aceasta functie astfel:


  • va apela functia "debounce (a)" care practic va tine programul pe loc atat timp cat butonul 1 continua sa fie apasat.
  • apoi face variabila globala flag egala cu 1. Aceasta variabila este verificata in timpul executiei functiei pentru a ne asigura ca butonul 1 nu a fost apasat din nou, fapt care duce la intreruperea excutiei functiei.
  • PORTB ia valoarea 1 si se apeleaza functia "delay_500_milli(unsigned char a)" .
      Aceasta functie nu face altceva decat sa asigure un delay de 0.5 s si sa setezeze variabiala globala flag 0 daca a fost apasat acelasi buton. Delay-ul este obtinut cu ajutorul TIMER0. Acesta este setat sa asigure un delay de ~ 25 ms pana cand are loc overflow-ul acestuia fapt care va duce ca flagul de intrerupere "INTCONbits.T0IF" sa fie setat 1. Asadar pentru a obtine un delay de 500 de ms sunt necesare 20 de iteratii. Dupa sfaristul fiecarei iteratii, adica dupa 25 ms, se verifica starea PORTD. Daca acesta revine la valoarea din momentul primei apasari a butonului atunci variabiala "flag este setata 1", fapt care va duce la intreruprea executiei  functiei keypad1(a). In acest moment programul se intoarce inapoi in functia scan() si va detecta alte apasari de taste.

     Cam asta ar fi.  Iar in cel mai scurt timp voi incerca sa postez si un filmulet cu executia programului.

Niciun comentariu:

Trimiteți un comentariu