Programació en C del PIC 18F45K20

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

Exemple PW - Control d'una sortida PWM

En aquest exemple volem controlar la lluminositat d'un dels LED fent servir una sortida PWM. Els LED estan connectats al port D. Les sortides PWM normals estan connectades als ports B o C i, per tant, no ens són útils. En canvi, tres de les sortides del PWM millorat estan connectades al port D; per exemple la sortida P1D comparteix pin amb RD7, el nostre vuitè LED.

Per tal que no puguem veure que el LED s'encén i s'apaga sinó que observem que fa més o menys llum ens cal treballar a una freqüència prou alta. Però tampoc ens interessa una freqüència massa alta ja que llavors l'eficiència energètica és menor. Podem treballar, per exemple a 62,5 Hz que correspon a un període T de 16 ms.

Amb la configuració bàsica del microcontrolador, el rellotge treballa a 1 MHz que dóna una freqüència de 250 kHz al rellotge del programa, amb el que es controla el Timer 2. Per tant ens caldria que el Timer 2 comptés fins a:

4000

Però el Timer 2 és de 8 bits, per tant només pot comptar fins a 256 valors. Per tant, ens cal posar una prescala a Timer 2. Aquesta prescala ha de ser superior a:

15,625

Com el Timer 2 pot tenir prescales de 4 i 16, agafarem aquesta darrera. Així el nombre que ens cal comptar serà:

250

Però atès que el comptador comença a 0, caldrà comptar de 0 a 249 per tenir 250.

En el nostre exemple no ens cal la resolució de 10 bits o sigui que mantindrem DC1B1 i DC1B0 a zero i posarem el percentatge de 250 desitjat al registre CCPR1L.

El nostre exemple començarà encenent el LED amb un valor del 50 % (125, la meitat de 250). Després començarà a augmentar la lluminositat (anirem incrementant el valor) fins al màxim. Al màxim es pararà un moment i començarà a disminuir fins a zero. Es tornarà a aturar un moment i tornarà a augmentar; i així successivament. No podem modificar aleatòriament el valor de CCPR1L ja que el podríem canviar dos o més cops en el mateix període; per això esperem a que el temporitzador acabi després de posar-li el nou valor i així ens assegurem que cada valor es fa servir una vegada. A cada cicle incrementem una unitat, per tant fem 250 iteracions entre 0 i 250. El temporitzador triga 16 ms en fer un cicle i, per tant, aquestes 250 iteracions són 4 segons que és el que es trigarà en passar del mínim al màxim. El programa és el següent:

#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 <xc.h>					// Carrega el fitxer de funcions
unsigned char Llum;  				// Variable de 8 bits sense signe per a la lluminositat
void main (void)
{
	TRISD = 0b01111111;     		// RD7 és de sortida
						// Configuració del Timer 2
	T2CON = 0b00000111;			// Engeguem el temporitzador amb una prescala de 16
	PR2 = 249;				// Comptem de 0 a 249, 250 valors
	CCPR1L = 125;				// Valor inicial del 50 % (250/2)
	CCP1CON = 0b01001100;			// Els quatre bits de la dreta CCP1Mx = 1100 PWM amb P1D actiu
						// Els dos bits de l'esquerra a P1Mx = 01
						// o sigui PWM a P1D (LED7)
						// P1A (RC2) sempre actiu, però no ho fem servir
						// Els altres dos bits (DC1B1 i DC1B0) a zero
	while(1)				// Inici del bucle principal
	{
		do				// En aquest primer cicle, incrementem la lluminositat
		{
			CCPR1L = ++Llum;	// Incrementem Llum i ho posem com a tON
			PIR1bits.TMR2IF = 0;	// Posem a zero el bit que indica que ha acabat Timer 2
						// (Timer 2 = PR2)
			while (PIR1bits.TMR2IF == 0)			// Mentre no acabi Timer 2
				;		// esperem sense fer res
		} while (Llum < 250);		// Quan arribem al màxim, s'acaba el cicle
		_delay(62500);	    		// Retard d'uns 250 ms al màxim per permetre la visualització
		do				// En aquest segon cicle, decrementem la lluminositat
		{
			CCPR1L = --Llum;	// Decrementem Llum i ho posem com a tON
			PIR1bits.TMR2IF = 0;	// Posem a zero el bit que indica que ha acabat Timer 2
						// (Timer 2 = PR2)
			while (PIR1bits.TMR2IF == 0)			// Mentre no acabi Timer 2
				;		// esperem sense fer res
		} while (Llum > 0);		// Quan arribem al mínim, s'acaba el cicle
		_delay(62500);	    		// Retard d'uns 250 ms al mínim 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.