Referència | Trucs | Perifèrics | Recursos CITCEA | |
Tutorial | Exemples | Projectes | Inici |
Ara volem que els LED s'activin de manera seqüencial. Podríem fer un programa de l'estil dels anteriors on anéssim activant i desactivant els bits un darrera l'altre. Però volem fer un programa més compacte. Hi ha algunes formes de fer-ho.
Una manera és fent servir les instruccions de rotació de bits. Això és el que fa el següent programa:
#pragma config FOSC = INTRCIO, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, CP = OFF #pragma config CPD = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF #include <xc.h> // Carrega el fitxer de funcions necessari per al compilador XC8
unsigned char Valor; // Variable de 8 bits sense signe (0 a 255)
void main (void){ TRISC = 0b00000000; // Posa el port C com a sortida Valor = 1; // Inicialment posem 1 (activem LED 0) while (1) // Bucle infinit { PORTC = Valor; // Copiem el valor al port (als LED) Valor = (Valor << 1) | (Valor >> 7); // Desplacem els bits _delay(200000); // Retard per permetre la visualització } }
El problema és que el programa fa rodar vuit bits i només tenim quatre LED. Per això la meitat del temps els LED es veuen apagats. El que podem fer és que quan toqui encendre el cinquè LED (quan Valor sigui 16) tornem a posar Valor a 1.
#pragma config FOSC = INTRCIO, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, CP = OFF #pragma config CPD = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF #include <xc.h> // Carrega el fitxer de funcions necessari per al compilador XC8
unsigned char Valor; // Variable de 8 bits sense signe (0 a 255)
void main (void){ TRISC = 0b00000000; // Posa el port C com a sortida Valor = 1; // Inicialment posem 1 (activem LED 0) while (1) // Bucle infinit { PORTC = Valor; // Copiem el valor al port (als LED) Valor = (Valor << 1) | (Valor >> 7); // Desplacem els bits if (Valor == 16) // Si ja estem al LED 5, Valor = 1; // tornem al LED 0 _delay(200000); // Retard per permetre la visualització } }
Per girar en sentit contrari només cal permutar el 7 i el 1 i canviar la comparació.
#pragma config FOSC = INTRCIO, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, CP = OFF #pragma config CPD = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF #include <xc.h> // Carrega el fitxer de funcions necessari per al compilador XC8
unsigned char Valor; // Variable de 8 bits sense signe (0 a 255)
void main (void){ TRISC = 0b00000000; // Posa el port C com a sortida Valor = 8; // Inicialment posem 1 (activem LED 0) while (1) // Bucle infinit { PORTC = Valor; // Copiem el valor al port (als LED) Valor = (Valor << 7) | (Valor >> 1); // Desplacem els bits if (Valor == 128) // Ja hem sortit fora, Valor = 8; // tornem al LED 4 _delay(200000); // Retard per permetre la visualització } }
A primer cop d'ull pot semblar estrany aquest 128 a la comparació. El següent gràfic ens ho explica:
Anem a veure una manera alternativa de fer-ho. Igual que en decimal fer desplaçar els números un lloc a l'esquerra implica multiplicar per deu, en binari implica multiplicar per dos. Inicialitzarem una variable amb el valor 1 (LED 0) i a cada repetició l'anirem multiplicant per 2. Quan el valor sigui 8 (LED 3) ja no tornarem a multiplicar per dos ja que sortiríem fora del rang de LED; en aquest cas tornarem a posar un 1.
#pragma config FOSC = INTRCIO, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, CP = OFF #pragma config CPD = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF #include <xc.h> // Carrega el fitxer de funcions necessari per al compilador XC8
unsigned char Valor; // Variable de 8 bits sense signe (0 a 255)
void main (void){ TRISC = 0b00000000; // Posa el port C com a sortida Valor = 1; // Inicialment posem 1 (activem LED 0) while (1) // Bucle infinit { PORTC = Valor; // Copiem el valor al port (als LED) if (Valor == 8) // Si ja estem al LED 3, no podem rodar més Valor = 1; // tornem al LED 0 else // Si no estem al LED 7 Valor = 2*Valor; // Multipliquem per 2 i passem al LED següent _delay(200000); // Retard per permetre la visualització } }
En aquest cas, el gir en sentit contrari s'aconsegueix dividint per dos i permutant l'1 pel 8.
Una tercera forma de fer-ho és tenir una variable que es vagi incrementant del 0 al 3 i fer-la servir de punter per llegir el valor que correspon a una llista. En aquesta llista hi haurà el valor que ccorrespon a cada posició. Aquesta llista és fixa, és a dir que no es modifica durant l'execució del programa. Per això la podem guardar a la memòria de programa.
#pragma config FOSC = INTRCIO, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, CP = OFF #pragma config CPD = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF #include <xc.h> // Carrega el fitxer de funcions necessari per al compilador XC8
unsigned char LED; // Variable de 8 bits sense signe (0 a 255) // Tenim una llista amb els 4 valors que ja definim // i que es guarda a la posició 0x180 de la memòria de programa const char Llista[4] @ 0x180 = {0x01, 0x02, 0x04, 0x08};
void main (void){ TRISC = 0b00000000; // Posa el port C com a sortida LED = 0; // Inicialment activem LED 0 while (1) // Bucle infinit { PORTC = Llista[LED]; // Busquem a la llista el valor que enviem al port LED++; // Incrementem la variable if (LED == 4) // Si hem arribat a 8 (ens hem passat) LED = 0; // Tornem a zero _delay(200000); // Retard per permetre la visualització } }
Aquesta obra d'Oriol Boix està llicenciada sota una llicència no importada Reconeixement-NoComercial-SenseObraDerivada 3.0.