Configurazione del modulo PWM del PIC16F877

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
Scarica subito una copia gratis

Una risposta

  1. Avatar photo Maurizio 23 Luglio 2016

Scrivi un commento

Seguici anche sul tuo Social Network preferito!

Send this to a friend