Programació en C del PIC 18F45K20

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

Exemple ST - Funcions

A l'Exemple VV tenim una part del programa que correspon a la inicialització del conversor i una altra part a la lectura de l'entrada analògica. Anem a posar aquestes parts en dues funcions. La primera funció (la d'inicialització) no tindrà cap paràmetre d'entrada ni cap valor de sortida; per tant formalment serà una funció. La de lectura del conversor no tindrà paràmetres d'entrada i donarà com a sortida el valor llegit.

Podem posar les funcions on vulguem però cal que quan les anem a fer servir estigui clar de quin tipus són; per això les declarem (sense posar-ne el contingut) després de la declaració de variables globals.

#pragma config FOSC = INTIO67, FCMEN = OFF, IESO = OFF				// CONFIG1H
#pragma config PWRT = OFF, BOREN = SBORDIS, BORV = 30				// CONFIG2L
#pragma config WDTEN = OFF, WDTPS = 32768					// CONFIG2H
#pragma config MCLRE = OFF, LPT1OSC = OFF, PBADEN = ON, CCP2MX = PORTC		// CONFIG3H
#pragma config STVREN = ON, LVP = OFF, XINST = OFF				// CONFIG4L
#pragma config CP0 = OFF, CP1 = OFF, CP2 = OFF, CP3 = OFF			// CONFIG5L
#pragma config CPB = OFF, CPD = OFF						// CONFIG5H
#pragma config WRT0 = OFF, WRT1 = OFF, WRT2 = OFF, WRT3 = OFF			// CONFIG6L
#pragma config WRTB = OFF, WRTC = OFF, WRTD = OFF				// CONFIG6H
#pragma config EBTR0 = OFF, EBTR1 = OFF, EBTR2 = OFF, EBTR3 = OFF		// CONFIG7L
#pragma config EBTRB = OFF							// CONFIG7H
#include "p18f45k20.h"				// Carrega el fitxer d'adreces i paràmetres del PIC 18F45K20
#define Polsador PORTBbits.RB0			// Li assigna un nom a l'adreça del polsador
#define FiTimer0 INTCONbits.TMR0IF		// Li assigna un nom al bit que indica el final del Timer 0
unsigned char Valor;  				// Variable de 8 bits sense signe (0 a 255)
bit Premut;					// Estat del polsador
bit Adreta;					// Sentit de gir
						// Definició de les funcions que farem servir 
void IniciAD (void);				// funció d'inicialització del conversor
unsigned char Analogica (void);			// Funció de lectura del conversor
void main (void)
{
						// Inicialització de variables
	Adreta = 0;				// Iniciem girant a l'esquerra
	Premut = 0;				// Suposem el polsador no premut
	Valor = 1;          			// Inicialment posem 1 (activem LED 0)
						// Configuració d'entrades i sortides
	TRISD = 0b00000000;    			// El port D és de sortida
	IniciAD ();				// funció d'inicialització del conversor
	INTCON2bits.RBPU = 0;			// Habilita el control de resistències de pull-up al port B
	WPUBbits.WPUB0 = 1;			// Activa la resistència de pull-up a RB0
	TRISBbits.TRISB0 = 1;      		// RB0 és entrada
						// Configuració del Timer 0
	FiTimer0 = 0;       			// Aquest bit es posarà a 1 quan el temporitzador acabi
						// cal desactivar-lo des del programa
	T0CON = 0b00000001;    		     	// El timer 0 és de 16 bits i compta temps amb pre-escalat de 1/4
	TMR0H = 0;                     		// Fem la precàrrega a zero per començar, primer el registre H
	TMR0L = 0;				// i després el registre L
	T0CONbits.TMR0ON = 1;          		// Fem que Timer 0 comenci a comptar
	while (1)				// Inici del bucle de programa
	{
		LATD = Valor;			// Copiem el valor al port (als LED)
		if (Adreta == 0)
			Valor = (Valor << 1)|(Valor >> 7);		// Desplacem els bits a l'esquerra
		if (Adreta == 1)
			Valor = (Valor >> 1)|(Valor << 7);		// Desplacem els bits a la dreta
		do				// Bucle que repetim mentre esperem que el temporitzador acabi
		{ 				// En el bucle mirem si s'ha premut el polsador i, si és així, 
						// canviem el sentit de gir
			if (Polsador == 1)	// Si el polsador no està premut (1 és no premut)
				Premut = 0;	// Memoritzem l'estat del polsador
			else if (Premut == 0)	// Si el polsador està premut però fa un moment no ho estava
			{ 
				Adreta = ~Adreta;			// Invertim el sentit de gir
				Premut = 1;	// Memoritzem el nou estat del polsador
			}
		} while (FiTimer0 == 0);	// Sortirà del bucle quan el bit es posi a 1
						// és a dir, quan Timer 0 acabi
		FiTimer0 = 0;   	   		// Tornem a posar el bit a zero
		TMR0H = Analogica();		// Cridem a la funció de lectura del conversor i
						// copiem el resultat llegit com a precàrrega del Timer
		TMR0L = 0;			// El TMR0L segueix a 0 però cal escriure-ho per recarregar TMR0H
	}
}
void IniciAD (void)				// funció d'inicialització del conversor
{
	TRISAbits.TRISA0 = 1;			// La pota RA0 és d'entrada
	ANSEL = 0;				// Desactiva totes les entrades analògiques
	ANSELH = 0;	
	ANSELbits.ANS0 = 1;			// I ara activa la del potenciòmetre (AN0)
	ADCON1 = 0;				// Les tensions de referència són les d'alimentació
	ADCON2 = 0b00111000;			// Configuració típica amb justificat per l'esquerra
	ADCON0 = 0b00000001;			// Activa el conversor connectat a AN0
}
unsigned char Analogica (void)			// Funció de lectura del conversor
{
	ADCON0bits.GO_DONE = 1;         	// Posa en marxa el conversor
	while (ADCON0bits.GO_DONE == 1)		// Mentre no acabi
		;    				// ens esperem
	return ADRESH;                    	// Retornem el resultat llegit
}

Les funcions (i altres parts del programa) poden estar en fitxers separats, de manera que estiguin ja preparats i comprovats i només calgui incloure'ls. Això permet reutilitzar fàcilment codi d'un programa a un altre.

Per exemple, les nostres funcions podrien estar en el fitxer analog.h i llavors el nostre fitxer de programa podria ser:

#pragma config FOSC = INTIO67, FCMEN = OFF, IESO = OFF				// CONFIG1H
#pragma config PWRT = OFF, BOREN = SBORDIS, BORV = 30				// CONFIG2L
#pragma config WDTEN = OFF, WDTPS = 32768					// CONFIG2H
#pragma config MCLRE = OFF, LPT1OSC = OFF, PBADEN = ON, CCP2MX = PORTC		// CONFIG3H
#pragma config STVREN = ON, LVP = OFF, XINST = OFF				// CONFIG4L
#pragma config CP0 = OFF, CP1 = OFF, CP2 = OFF, CP3 = OFF			// CONFIG5L
#pragma config CPB = OFF, CPD = OFF						// CONFIG5H
#pragma config WRT0 = OFF, WRT1 = OFF, WRT2 = OFF, WRT3 = OFF			// CONFIG6L
#pragma config WRTB = OFF, WRTC = OFF, WRTD = OFF				// CONFIG6H
#pragma config EBTR0 = OFF, EBTR1 = OFF, EBTR2 = OFF, EBTR3 = OFF		// CONFIG7L
#pragma config EBTRB = OFF							// CONFIG7H
#include "p18f45k20.h"				// Carrega el fitxer d'adreces i paràmetres del PIC 18F45K20
#include "analog.h"				// Carrega el fitxer de funcions del conversor AD
#define Polsador PORTBbits.RB0			// Li assigna un nom a l'adreça del polsador
#define FiTimer0 INTCONbits.TMR0IF		// Li assigna un nom al bit que indica el final del Timer 0
unsigned char Valor;  				// Variable de 8 bits sense signe (0 a 255)
bit Premut;					// Estat del polsador
bit Adreta;					// Sentit de gir
void main (void)
{
						// Inicialització de variables
	Adreta = 0;				// Iniciem girant a l'esquerra
	Premut = 0;				// Suposem el polsador no premut
	Valor = 1;         			// Inicialment posem 1 (activem LED 0)
						// Configuració d'entrades i sortides
	TRISD = 0b00000000;    			// El port D és de sortida
	IniciAD ();				// funció d'inicialització del conversor
	INTCON2bits.RBPU = 0;			// Habilita el control de resistències de pull-up al port B
	WPUBbits.WPUB0 = 1;			// Activa la resistència de pull-up a RB0
	TRISBbits.TRISB0 = 1;      		// RB0 és entrada
						// Configuració del Timer 0
	FiTimer0 = 0;       			// Aquest bit es posarà a 1 quan el temporitzador acabi
						// cal desactivar-lo des del programa
	T0CON = 0b00000001;    		     	// El timer 0 és de 16 bits i compta temps amb pre-escalat de 1/4
	TMR0H = 0;                     		// Fem la precàrrega a zero per començar, primer el registre H
	TMR0L = 0;				// i després el registre L
	T0CONbits.TMR0ON = 1;          		// Fem que Timer 0 comenci a comptar
	while (1)				// Inici del bucle de programa
	{
		LATD = Valor;			// Copiem el valor al port (als LED)
		if (Adreta == 0)
			Valor = (Valor << 1)|(Valor >> 7);		// Desplacem els bits a l'esquerra
		if (Adreta == 1)
			Valor = (Valor >> 1)|(Valor << 7);		// Desplacem els bits a la dreta
		do				// Bucle que repetim mentre esperem que el temporitzador acabi
		{ 				// En el bucle mirem si s'ha premut el polsador i, si és així, 
						// canviem el sentit de gir
			if (Polsador == 1)	// Si el polsador no està premut (1 és no premut)
				Premut = 0;	// Memoritzem l'estat del polsador
			else if (Premut == 0)	// Si el polsador està premut però fa un moment no ho estava
			{ 
				Adreta = ~Adreta;			// Invertim el sentit de gir
				Premut = 1;	// Memoritzem el nou estat del polsador
			}
		} while (FiTimer0 == 0);	// Sortirà del bucle quan el bit es posi a 1
						// és a dir, quan Timer 0 acabi
		FiTimer0 = 0;          		// Tornem a posar el bit a zero
		TMR0H = Analogica();		// Cridem a la funció de lectura del conversor i
						// copiem el resultat llegit com a precàrrega del Timer
		TMR0L = 0;			// El TMR0L segueix a 0 però cal escriure-ho per recarregar TMR0H
	}
}

La instrucció #include "analog.h" llegeix les funcions. Com això es fa abans d'iniciar-se el programa, ja no cal declarar les funcions com fèiem abans.

Per crear el fitxer de funcions, anem al menú lateral i piquem sobre Source Files amb el botó dret. Allà triem New Empty File i s'obrirà una finestra per posar el nom.

El contingut del fitxer analog.h seria:

void IniciAD (void)				// funció d'inicialització del conversor
{
	TRISAbits.TRISA0 = 1;			// La pota RA0 és d'entrada
	ANSEL = 0;				// Desactiva totes les entrades analògiques
	ANSELH = 0;	
	ANSELbits.ANS0 = 1;			// I ara activa la del potenciòmetre (AN0)
	ADCON1 = 0;				// Les tensions de referència són les d'alimentació
	ADCON2 = 0b00111000;			// Configuració típica amb justificat per l'esquerra
	ADCON0 = 0b00000001;			// Activa el conversor connectat a AN0
}
unsigned char Analogica (void)			// Funció de lectura del conversor
{
	ADCON0bits.GO_DONE = 1;          	// Posa en marxa el conversor
	while (ADCON0bits.GO_DONE == 1)		// Mentre no acabi
		;    				// ens esperem
	return ADRESH;         	          	// Retornem el resultat llegit
}

 

 

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