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.