Programació en C del PIC 16F690

Referència Trucs Perifèrics   Recursos CITCEA
Tutorial Exemples Projectes   Inici

Exemple RL - Rotació de LED

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:

Rotació de bits

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ó
    }
}

 

 

Llicència de Creative Commons
Aquesta obra d'Oriol Boix està llicenciada sota una llicència no importada Reconeixement-NoComercial-SenseObraDerivada 3.0.