- Esquema de connexions:
- Microcontrolador PIC PIC16F877A Codi de seqüència intermitent LED i explicació de treball:
En el nostre tutorial anterior, vam aprendre sobre el parpelleig d’un LED mitjançant microcontrolador PIC i vam construir el mateix circuit a la placa Perf. Després hem utilitzat PICkit 3, ICSP i MPLAB IPE per llençar el programa a la nostra placa Perf. Ara, en aquest tutorial avançarem a utilitzar més pins al microcontrolador PIC. Utilitzarem 7 sortides (LED) i una entrada. Per a aquest tutorial utilitzarem l'antiga placa Perf (que es mostra a continuació) i afegirem pals de Berg per treure els pins necessaris a la segona placa LED. Al final d'aquest tutorial, generarem una seqüència de LEDs parpellejants mitjançant el microcontrolador PIC PIC16F877A i aprendrem a utilitzar diverses entrades i sortides, alguns conceptes bàsics sobre les trucades de bucles i funcions.


La placa LED no és res més que una altra placa perf, sobre la qual soldarem els LED amb una resistència limitadora de corrent (que es mostra a continuació). També afegirem un polsador per iniciar el LED de seqüència que parpelleja.

Esquema de connexions:

Microcontrolador PIC PIC16F877A Codi de seqüència intermitent LED i explicació de treball:
A continuació, es dóna el codi complet (comproveu-ho al final), aquí el recorrerem línia per línia. Aquest codi començarà a encendre els LED de manera seqüencial quan es prem el botó. Per comprendre les seqüències, mireu el vídeo al final del tutorial. Us recomanaria que compareu la sortida que es mostra al vídeo amb el codi següent i que intenteu entendre el programa.
Vegem el codi línia per línia. Les primeres línies serveixen per configurar bits de configuració que s’explicaven al tutorial anterior, de manera que ara els saltaré. La millor manera d’entendre qualsevol programa és començar des de la funció main ( void main () ), així que fem-ho
TRISB0 = 1; // Indiqueu a la MCU que el pin 0 PORTB s'utilitzi com a entrada per al botó. TRISD = 0x00; // Indiqueu a la MCU que tots els pins tinguin sortida PORTD = 0x00; // Inicialitzeu tots els pins a 0
La paraula TRIS s’utilitza per definir si el pin s’utilitza com a entrada / sortida i la paraula PORT s’utilitza per fer un pin High / Low. La línia TRISB0 = 1 farà que el 0è pin de PORT B com a entrada. Aquest serà el nostre polsador. Les línies TRISD = 0x00; PORTD = 0x00; farà que tots els pins del port D com a sortida i assignin un valor inicial de BAIX a aquests pins.
Com que hem dit que s'utilitza B0 com a entrada, connectarem un extrem del polsador al pin B0 i un altre extrem a terra. Aleshores, sempre que premem el botó, el pin es mantindrà a terra tal com es mostra al diagrama de connexió anterior. Però perquè això passi, hem d’utilitzar una resistència de tracció cap amunt perquè el passador es mantingui elevat quan no es prem el botó. Una resistència pull up és una cosa així.

Però la nostra MCU PIC té una resistència interna de pujada feble que es pot activar mitjançant un programari de manera que estalvia moltes molèsties (quan es connectaran més botons).
Què és una resistència feble?
Hi ha dos tipus de resistència de tracció cap amunt, una és la de debilitat i l'altra de la de pujada forta. Les resistències de tracció febles són d’alt valor i permeten que flueixi un corrent feble i les resistències de tracció fortes tenen un valor baix, permetent així fluir un corrent fort. Tots els MCU utilitzen principalment resistències de tracció febles. Per activar-ho al nostre PIC MCU, hem de buscar al nostre full de dades l’ OPTION_REG (registre d’opcions) tal com es mostra a la instantània següent.

Com es mostra, el bit 7 tracta de la feble resistència de tracció cap amunt. S'hauria de fer zero per activar-lo. Això es fa mitjançant OPTION_REG <7> = 0 . Això tracta específicament del bit 7 que deixa els altres bits als seus valors per defecte. Amb això entrem al nostre bucle while, on comprova si es prem el botó utilitzant if (RB0 == 0). Si es compleix la condició, anomenem la nostra funció amb els paràmetres 1, 3, 7 i 15.
sblink (1); // CONVOCAT CRIA FUNCIÓ 1 amb paràmetre 1 sblink (3); // FUNCIÓ DE CONVOCAT 3RIA 3 amb el paràmetre 3 sblink (7); // FUNCIÓ DE CONVOCAT 7RIA 7 amb el paràmetre 7 sblink (15); // FUNCIÓ DE CONVOCAT 4RIA 4 amb el paràmetre 15
Per què fem servir funcions?
Les funcions s’utilitzen per reduir el nombre de línies del nostre codi. Això és el que la majoria de nosaltres hauríem sabut. Però, per què hem de reduir el nombre de línies, especialment quan es tracta de programació MCU? La raó és l’espai limitat a la memòria del nostre programa. Si no optimitzem correctament el codi, és possible que quedem sense espai de memòria. Això serà útil quan escrivim llargues pàgines de codis.
Qualsevol funció tindrà una funció Definició ( sblink (int get) en el nostre cas) i una funció Call ( sblink (1) en el nostre cas). És opcional tenir una declaració de funció, per evitar-la he posat la meva definició de funció abans de cridar la funció a la meva funció principal.
Els paràmetres de funció són el valor que es passarà de la trucada de funció a la definició de funció. En el nostre cas, els valors enters (1, 3, 7, 15) són els paràmetres que es passen de la trucada de funció i la variable "get" obté el valor dels paràmetres a la definició de la funció per processar-los. Una funció pot tenir més d'un paràmetre.
Un cop cridada la funció, s'executaran les línies següents a la definició de la funció.
for (int i = 0; i <= 7 && RB0 == 0; i ++) {PORTD = get << i; // Moure LED Seqüència esquerra __delay_ms (50); } per a (int i = 7; i> = 0 && RB0 == 0; i--) {PORTD = get << i; // Moure LED Seqüència esquerra __delay_ms (50); }
Ara sembla que aquesta línia és estranya: PORTD = get << i . Explicaré què passa realment aquí.
"<<" és un operador de desplaçament a l'esquerra que desplaça tots els bits a la seva posició esquerra. Ara, quan anomenem la funció sblink (int get) amb el paràmetre '1' com a sblink (1), farà que el valor de 'get' sigui 1, que en binari és 0b00000001. Per tant, aquesta línia serà com PORTD = 0b00000001 << i .
El valor de "i" variarà de 0 a 7 ja que hem utilitzat un bucle for per a (int i = 0; i <= 7 && RB0 == 0; i ++). El valor de "i" de 0 a 7 canviarà el resultat de la manera següent:

Com podeu veure, hem encès un LED cada vegada (d'esquerra a dreta) mantenint la resta apagada. El següent 'for loop' per a (int i = 7; i> = 0 && RB0 == 0; i--) , també farà el mateix, però aquesta vegada el LED s'encendrà de dreta a esquerra en una seqüència, ja que vam començar a partir de 7 i vam baixar a 0. Hem utilitzat un retard de 200 ms perquè puguem visualitzar el LED encès i apagat.
Ara, quan passem el valor 3 a la funció sblink (int get) , de manera que s'executarà la funció sblink (3) que fa que el valor de "get" sigui 0b00000011, per tant el resultat a PORTD serà:

Aquesta vegada, doncs, aquesta vegada s’encenen dos LEDs en qualsevol moment mitjançant l’ús de sblink (3). De la mateixa manera, per a sblink (7) i sblink (15), tres i quatre LED s’encenen en una seqüència. Un cop acabat això, farem que tots els LED s’encenguin mitjançant la línia PORTD = 0xFF . Consulteu el vídeo següent per obtenir una demostració completa.
Espero que hàgiu entès el codi i, per tant, que hàgiu après a utilitzar les funcions del bucle 'for' i 'while' per obtenir les sortides desitjades. Ara podeu ajustar el codi per obtenir la vostra seqüència diferent de parpelleig de LED. Seguiu compilant el vostre codi i deixeu-lo a la vostra MCU i gaudiu de la sortida. Podeu utilitzar la secció de comentaris si us quedeu atrapats en algun lloc. També he adjuntat aquí els fitxers de simulació i programa.
Això és tot, ara com ara, al nostre proper tutorial, aprendrem a utilitzar temporitzadors PIC16F877A en lloc d’utilitzar funcions de retard. Podeu consultar tots els tutorials de microcontroladors PIC aquí.
