CONFIGURAZIONE DEL MODULO PWM DEL PIC16F877
I registri usati per la configurazione del modulo PWM sono: TRISC, PR2, CCP1CON, CCP2CON, CCPR1L, CCPR2L e T2CON. Tipicamente il modulo PWM viene utilizzato per il controllo dei motori. È dunque molto importante determinare la frequenza e la larghezza dell’impulso in base alla propria applicazione. Alcuni motori richiedono frequenze di impulsi relativamente basse (inferiori ai 5KHz) mentre altri richiedono frequenze più elevate, tipicamente dell’ordine dei 15-20KHz. Il listato 1 mostra come utilizzare il modulo PWM del PIC16F877 con i compilatori CCS.
#include <16f877.h>
#ORG 0x1F00,0x1FFF {} /* Reserve memory for bootloader for the 8k 16F876/7 */
#device PIC16F877 *=16 /* Allow RAM to expand beyond 256 bytes */
#device adc=10 /* Make sure that we are sampling on 10 bits. This directive
is required for compiler version 2.7. */
/* Set the clock speed */
#use delay(clock=20000000)
#fuses HS,NOPROTECT,NOWDT,BROWNOUT,PUT,NOLVP
/* Directive for RS-232 interface */
#use rs232(baud=9600, xmit=PIN_C6, rcv=PIN_C7)
#include “input.c”
#define VARIABLE_PERIOD 1 // If this symbol is defined, let the user select the
// period and prescaler, otherwise,
// if VARIABLE_PERIOD = 0, use fixed values.
main() {
char selection;
byte duty, period;
byte prescale;
// We use serial input to capture PWM parameters to make
// an easy demo.
setup_ccp1(CCP_PWM); // Configure CCP1 as a PWM
setup_ccp2(CCP_PWM); // Configure CCP1 as a PWM
#if VARIABLE_PERIOD // This is default
for ( ; ; ) {
// Select value for the period (100% duty cycle)
printf(“Period (100%% duty cycle): “);
period = gethex();
printf(“\r\n”);
// Set the prescaler
do {
// Select prescaler (t2div)
printf(“\r\nSelect prescaler:\r\n”);
printf(“ 1: Prescaler = 1\r\n”);
printf(“ 2: Prescaler = 4\r\n”);
printf(“ 3: Prescaler = 16\r\n”);
printf(“Selection: “);
selection = getc();
putc(selection);
printf(“\r\n”);
} while((selection < ‘1’) || (selection > ‘3’));
// The cycle time will be (1 / clock) * 4 * t2div * (period + 1)
// In this program, if period is 0x80 (or 128 decimal), with
// a clock of 20000000:
// For the three possible prescaler selections the cycle time is:
// (1/20000000) * 4 * 1 * 128 = 25.6 us or 39 khz
// (1/20000000) * 4 * 4 * 128 = 102.4 us or 9.8 khz
// (1/20000000) * 4 * 16 * 128 = 409.6 us or 2.4 khz
switch(selection) {
case ‘1’:
prescale = 1;
setup_timer_2(T2_DIV_BY_1, period, 1);
break;
case ‘2’:
prescale = 4;
setup_timer_2(T2_DIV_BY_4, period, 1);
break;
case ‘3’:
prescale = 16;
setup_timer_2(T2_DIV_BY_16, period, 1);
break;
}
#else
period = 0x80;
prescale = 4;
setup_timer_2(T2_DIV_BY_4, period, 1);
#endif
printf(“Frequency = %ld kHz\r\n”, 5000 / period / prescale);
while(TRUE) {
printf(“Enter duty cycle: “);
duty = gethex();
printf(“\r\n”);
set_pwm1_duty(duty);
set_pwm2_duty(duty); // This sets the time the pulse is
// high each cycle. If period is 128 (or ‘80’ hex),
// a value of 64 (or ‘40’ hex) will set the duty cycle to 50%, i.e.
// the pulse is high 50% of time.
// WARNING: A value too high or low will
// prevent the output from
// changing. A value too high
// will make the CCPx high at all times.
if (duty == 0x10) { // If ‘10’ is entered for duty, exit loop to be able to
// select other values for period and prescaler
break;
}
}
}
}
| Listato 1 |




Il PWM è una tecnica per controllare il motore, in questi casi la velocità viene regolata variando il tempo del segnale mantenuto ad una certa tensione.