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:

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:

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

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

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