Programació en C del PIC 16F690 amb PICkit 2

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

Exemple LI - Encendre un LED de manera intermitent

Ara volem que el mateix LED estigui encès de manera intermitent. A primer cop d'ull podríem pensar en aquest programa:

#pragma config FOSC = INTRCIO, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, CP = OFF, CPD = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF
#include "pic16f690.h"				// Carrega el fitxer d'adreces i paràmetres del PIC 16F690
void main (void)				// Inici del programa principal
{
	TRISC = 0b11111110; 			// Posa el bit 0 del port C com a sortida
	while (1)				// Mentre el contingut del parèntesi sigui 1
	{					// repetim aquest bucle
		PORTCbits.RC0 = 1;		// Activa el bit 0 del port C i, per tant, encén el LED
		PORTCbits.RC0 = 0;		// Desactiva el bit 0 del port C i, per tant, apaga el LED
	}					// Fi del bucle
}						// Fi del programa

Aquest programa té dues diferències respecte a l'anterior. La primera és que després d'activar el LED (RC0) es torna a desactivar. La segona és que ara es torna a repetir indefinidament el procés d'activació i desactivació i, per això, el bucle while inclou les dues línies (per fer-ho, emprem unes claus que engloben totes les línies que es repeteixen).

Si proveu aquest programa veureu que no fa el que esperàvem. El LED està encès tota l'estona encara que, si ens hi fixem bé, veurem que fa menys llum. Per què passa això?

Les instruccions al microcontrolador s'executen de manera molt ràpida, per això no ens dóna temps de veure-ho. Podem posar un retard després de cada instrucció per aconseguir el que volem. La funció _delay() afegeix un retard del nombre de cicles especificat dins el parèntesi. La funció _delay() està definida al fitxer <xc.h> ; per tant cal carregar-lo.

#pragma config FOSC = INTRCIO, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, CP = OFF, CPD = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF
#include "pic16f690.h"				// Carrega el fitxer d'adreces i paràmetres del PIC 16F690
#include <xc.h>					// Carrega el fitxer de funcions
void main (void)				// Inici del programa principal
{
	TRISC = 0b11111110; 			// Posa el bit 0 del port C com a sortida
	while (1)				// Mentre el contingut del parèntesi sigui 1
	{					// repetim aquest bucle
		PORTCbits.RC0 = 1;		// Activa el bit 0 del port C i, per tant, encén el LED
		_delay(200000);			// Retard de 200 000 cicles
		PORTCbits.RC0 = 0;		// Desactiva el bit 0 del port C i, per tant, apaga el LED
		_delay(200000);			// Retard de 200 000 cicles
	}					// Fi del bucle
}						// Fi del programa

Podeu variar el valor que poseu com a paràmetre de la funció _delay( ) per variar el temps. Per exemple amb 600000 anirà tres cops més lent. Però si proveu amb valors molt més grans us trobareu que el compilador us dóna una errada ja que la funció no admet valors tan grans. En aquest cas, podem repetir la funció diverses vegades.

També podem indicar el temps exacte del retard amb la funció __delay_ms( ), com en el següent exemple:

#pragma config FOSC = INTRCIO, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, CP = OFF, CPD = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF
#include "pic16f690.h"				// Carrega el fitxer d'adreces i paràmetres del PIC 16F690
#include <xc.h>					// Carrega el fitxer de funcions
#define _XTAL_FREQ  4000000			// La freqüència del rellotge és 4 MHz
void main (void)				// Inici del programa principal
{
	TRISC = 0b11111110; 			// Posa el bit 0 del port C com a sortida
	while (1)				// Mentre el contingut del parèntesi sigui 1
	{					// repetim aquest bucle
		PORTCbits.RC0 = 1;		// Activa el bit 0 del port C i, per tant, encén el LED
		__delay_ms(500);		// Retard de 500 ms (mig segon)
		PORTCbits.RC0 = 0;		// Desactiva el bit 0 del port C i, per tant, apaga el LED
		__delay_ms(500);		// Retard de 500 ms (mig segon)
	}					// Fi del bucle
}						// Fi del programa

Ara imaginem-nos que volem que en lloc d'un LED se n'encenguin dos; per exemple el 0 i el 2. El programa podria ser el següent.

#pragma config FOSC = INTRCIO, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, CP = OFF, CPD = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF
#include "pic16f690.h"				// Carrega el fitxer d'adreces i paràmetres del PIC 16F690
#include <xc.h>					// Carrega el fitxer de funcions
#define _XTAL_FREQ  4000000			// La freqüència del rellotge és 4 MHz
void main (void)				// Inici del programa principal
{
	TRISC = 0b11110000; 			// Posa els bit 0 a 3 del port C com a sortida
	while (1)				// Mentre el contingut del parèntesi sigui 1
	{					// repetim aquest bucle
		PORTCbits.RC0 = 1;		// Activa el bit 0 del port C i, per tant, encén el LED
		PORTCbits.RC2 = 1;		// Activa el bit 0 del port C i, per tant, encén el LED
		__delay_ms(500);		// Retard de 500 ms (mig segon)
		PORTCbits.RC0 = 0;		// Desactiva el bit 0 del port C i, per tant, apaga el LED
		PORTCbits.RC2 = 0;		// Desactiva el bit 0 del port C i, per tant, apaga el LED
		__delay_ms(500);		// Retard de 500 ms (mig segon)
	}					// Fi del bucle
}						// Fi del programa

Si ho proveu, veureu que no fa el que ens esperàvem. No s'encenen els LED 0 i 2 sinó només el 2. Si proveu de permutar les dues línies queactuen sobre el PORTC resultarà que només s'encén el LED 0. Per què passa això?

L'activació o desactivació de bits sobre els ports no funciona igual com amb la resta de memòria. Quan hi ha una instrucció bcf o bsf el microcontrolador llegeix l'adreça completa (vuit bits), modifica el bit i torna a escriure l'edreça completa. En el cas dels ports, el que es llegeix no és l'estat de les sortides sinó el de les entrades. Així quan fem la segona instrucció, es llegeix l'estat de les entrades i com l'entrada RC0 està desactivada tenim un zero en aquesta posició, es canvia el bit 2 i s'escriu.

Per solucionar el problema, podem fer les modificacions sobre una variable i després copiar tota la variable sencera sobre el port. Així si en altres punts del programa es modifica també la variable el que s'enviarà serà el contingut complet. A continuació tenim el programa.

#pragma config FOSC = INTRCIO, WDTE = OFF, PWRTE = OFF, MCLRE = OFF, CP = OFF, CPD = OFF, BOREN = OFF, IESO = OFF, FCMEN = OFF
#include "pic16f690.h"				// Carrega el fitxer d'adreces i paràmetres del PIC 16F690
#include <xc.h>					// Carrega el fitxer de funcions
#define _XTAL_FREQ  4000000			// La freqüència del rellotge és 4 MHz
unsigned char Port;  				// Variable de 8 bits sense signe (0 a 255)
void main (void)				// Inici del programa principal
{
	TRISC = 0b11110000; 			// Posa els bit 0 a 3 del port C com a sortida
	Port = 0b00000000;			// Desactiva tots els bits de Port
	PORTC = Port;				// Copia Port al PORTC
	while (1)				// Mentre el contingut del parèntesi sigui 1
	{					// repetim aquest bucle
		Port = Port | 0b00000101;	// Activa els bits 0 i 2 de Port
		PORTC = Port;			// Copia Port al PORTC
		__delay_ms(500);		// Retard de 500 ms (mig segon)
		Port = Port & 0b11111010;	// Desactiva els bits 0 i 2 de Port
		PORTC = Port;			// Copia Port al PORTC
		__delay_ms(500);		// Retard de 500 ms (mig segon)
	}					// Fi del bucle
}						// Fi del programa

En aquest cas, l'activació i desactivació dels bits de la variable Port la fem aplicant-li un emmascarament.

 

 

Licencia de Creative Commons
Esta obra de Oriol Boix está licenciada bajo una licencia no importada Creative Commons Reconocimiento-NoComercial-SinObraDerivada 3.0.