Programando PWM

El ucontrolador posee un susbsistemas para la generación de PWM, llamado Capture/Compare/PWM (CCP). Este requiere que se configuren los módulos TMR2 en conjunto con CPP1 (o CPP2), para ello se deben configurar los registros:  

El procedimiento para la generación de PWM es el siguiente:

La programacion se puede hacer de varios modos, una es tomado los bit individuales de cada registro (de acuerdo al datasheet) e inicializarlos o usar la identificacion que el compilador hace de los bit respectivos, ya que de acuerdo al manual, casi todos ellos tienen un identificador. Por ejemplo en el registro T2CON, el T2CON.2  corresponde al bit TM2ON, T2CON.1 y T2CON.0 corresponden a los bits T2CKPS1 y T2CKPS0 respectivamente.


Se programan los dos PWM con valores fijos

void main()
{

TRISC = 0b10111001;
PR2 = 0xFF; // PERIODO Seteado a 0xFF

T2CON = 0b00000110; // Prescalar de 16 PWM Freq = 1.22kHz -- Clock 20MHz

CCP1CON=0b00001100; //

CCP2CON=0b00001100;

 while(1)
 {

  CCPR1L=50;

  CCPR2L=50;
 // 50 -- 180 us

  // 100 -- 320 us
  // 150 -- 480 us

  // 200 -- 640 us

 }

}

   
   



Programa alternativo de PWM

void int_pwm()
{
 TRISC = 0b10111001;
 PR2 = 0xFF; // PERIODO Seteado a 0xFF

 T2CON = 0b00000110; // Prescalar de 16 PWM Freq = 1.22kHz -- Clock 20MHz
 CCP1CON=0b00001100; //
 CCP2CON=0b00001100;
}


void set_pwm(char pwm1, char pwm2)
{
 CCPR1L=pwm1;
 CCPR2L=pwm2;

}


void main()
{
 Init_pwm(); // Inicializa pwm
 while(1)

 {

   set_pwm(50,50); // Cambia de valor
  }

}


lUna Función más completa puede ser la siguiente

/*
Este código implementa 2 funciones separadas, una para inicializar
y otra para setear los pwm por separado
*/


void init_pwm(char pwm)
{
    TM2ON=1;   // Timer 2 ON
    T2CKPS1=1;  // Pre escalar x 16
    T2CKPS2=0;
    PR2=0xff;
    if(pwm==1)
     {
      TRISC.2=0;   // CCP1 de salida
      CCP1CON.0=0;  // Modo pwm
      CCP1CON.1=0;
      CCP1CON.2=1;
      CCP1CON.3=1;
    }
    if(pwm==2)
    {
      TRISC.1=0; // CCP2 de salida
      CCP2CON.0=0;  // Modo pwm
      CCP2CON.1=0;
      CCP2CON.2=1;
      CCP2CON.3=1;
    }
}


/*
 La varaiable duty es de 16 bit, pero se deben usar 1 bit,
 luego, su valor fluctua entre 0 y 1023
*/

void set_pwm(char pwm, uns16 duty)
{
  if(pwm==1)
  {
    CCP1CON.4=duty.0;
    CCP1CON.5=duty.1;
    duty=duty>>2;
    CCPR1L=duty.low8;
   }
  if(pwm==2)
   {
    CCP2CON.4=duty.0;
    CCP2CON.5=duty.1;
    duty=duty>>2;
    CCPR2L=duty.low8;
   }
}


void main()
{
 while(1)
 {
   init_pwm(1);
   set_pwm(1,512);
 }
}