Autor Tema: Libreria para manejar Frecuencia PWM en CCS.  (Leído 8462 veces)

0 Usuarios y 1 Visitante están viendo este tema.

Desconectado bigluis

  • Colaborador
  • PIC24F
  • *****
  • Mensajes: 511
    • Tutoriales de Qt C++
Libreria para manejar Frecuencia PWM en CCS.
« en: 27 de Noviembre de 2010, 14:19:10 »
En muchos casos necesitamos que nuestra señal PWM  tenga una frecuencia específica, el problema consiste en que necesitamos determinar el valor del Prescaler T2DIV y del registro PR2 a partir de la siguiente Fórmula.

$$Tpwm = 4\,Tosc\,\,T2DIV\,\left( {PR2 + 1} \right)

es decir:

$$Fpwm = {{Fosc} \over {4\,T2DIV\,\left( {PR2 + 1} \right)}}

Por ejemplo, queremos que Fpwm=1khz para un PIC16F887 que tiene Fosc=8MHz, y sabemos que este PIC posee 3 prescaler T2DIV=1, 4 y 16, por lo tanto el primer paso será despejar el valor de PR2 de la formula anterior.

$$PR2 = {{Fosc} \over {4\,Fpwm\,T2DIV}} - 1

el segundo paso sera sustituir valores y probar con T2DIV = 1.

$$PR2 = {{8MHz} \over {4\, \times 1kHz \times 1}} - 1 = 1999

Como el valor anterior es mayor al valor máximo de PR2, es decir 255, debemos aumentar el valor de T2DIV.

$$PR2 = {{8MHz} \over {4\, \times 1kHz \times 4}} - 1 = 499

Como aún el valor anterior es mayor al valor máximo de PR2, es decir 255, debemos aumentar el valor de T2DIV.

$$PR2 = {{8MHz} \over {4\, \times 1kHz \times 16}} - 1 = 124

En este caso si podemos darle este valor a PR2.

Muchas veces resulta tedioso estar calculando este valor, por eso he realizado la siguiente librería que realizará esto por nosotros.
Código: [Seleccionar]
/////////////////////////////////////////////////////////////////////////////////
//Autor: Luis Alberto Vargas Tijerino.
//Alias: Bigluis.
//Fecha: 26-Nov-2010.
//Pais:  Nicaragua.
/////////////////////////////////////////////////////////////////////////////////
//                                    PWM_FREQ.C
//    Libreria para ingresar la frecuencia PWM sin necesidad de calcularla.
//
//    Para utilizarla es necesario definir al inicio del programa Fosc
//
//Ejemplo:
//!#define Fosc 8000000
//
//    Luego es posible utilizar la funcion
//          set_pwm_freq(Fpwm)  Esta configurara T2DIV y PR2 para obtener
//                              Fpwm.
/////////////////////////////////////////////////////////////////////////////////

#ifndef Fosc
   #define Fosc 8000000
#endif

#use delay (clock=Fosc)

#if !defined(__PCD__)                                                            //Si no se ha definido un pic de 24 bits
   #define set_pwm_freq(Fpwm)                                                    /*definimos el macro set_pwm_freq(Fpwm) de la siguiente manera
   */(Fosc/(Fpwm*1*4)-1<0xFF)?                                                   /*Si (Fosc/(Fpwm*1*4)-1 es menor a 0xFF
   */    setup_timer_2(T2_DIV_BY_1, (int8)(Fosc/(Fpwm*1*4))-1, 1):               /*el macro set_pwm_freq(Fpwm) sera igual a setup_timer_2(T2_DIV_BY_1, Fosc/(Fpwm*1*4)-1, 1)
   */(Fosc/(Fpwm*4*4)-1<0xFF)?                                                   /*De lo contrario si (Fosc/(Fpwm*4*4)-1 es menor a 0xFF
   */   setup_timer_2(T2_DIV_BY_4, (int8)(Fosc/(Fpwm*4*4))-1, 1):                /*el macro set_pwm_freq(Fpwm) sera igual a setup_timer_2(T2_DIV_BY_4, Fosc/(Fpwm*4*4)-1, 1)
   */(Fosc/(Fpwm*16*4)-1<0xFF)?                                                  /*Si (Fosc/(Fpwm*16*4)-1 es menor a 0xFF
   */    setup_timer_2(T2_DIV_BY_16, (int8)(Fosc/(Fpwm*16*4))-1, 1):             /*el macro set_pwm_freq(Fpwm) sera igual a setup_timer_2(T2_DIV_BY_16, Fosc/(Fpwm*16*4)-1, 1)
   */    setup_timer_2(T2_DIV_BY_16, 0xFF, 1);                                   //De lo contrario el macro set_pwm_freq(Fpwm) sera igual a setup_timer_2(T2_DIV_BY_1, 0xFF, 1)
#else                                                                            //Si no se ha definido un pic de menos de 24 bits
   #define set_pwm_freq(Fpwm)                                                    /*Definimos el macro set_pwm_freq(Fpwm) de la siguiente manera
   */(Fosc/(Fpwm*1*4)-1<0xFFFF)?                                                 /*Si (Fosc/(Fpwm*1*4)-1 es menor a 0xFFFF
   */    setup_timer2(TMR_INTERNAL | TMR_DIV_BY_1, (int16)(Fosc/(Fpwm*1*4))-1):  /*el macro sera igual a setup_timer2(TMR_INTERNAL | TMR_DIV_BY_1, (Fosc/(Fpwm*1*4))-1)
   */(Fosc/(Fpwm*8*4)-1<0xFFFF)?                                                 /*Si (Fosc/(Fpwm*8*4)-1 es menor a 0xFFFF
   */    setup_timer2(TMR_INTERNAL | TMR_DIV_BY_8, (int16)(Fosc/(Fpwm*8*4))-1):  /*el macro sera igual a setup_timer2(TMR_INTERNAL | TMR_DIV_BY_8, (Fosc/(Fpwm*8*4))-1)
   */(Fosc/(Fpwm*64*4)-1<0xFFFF)?                                                /*Si (Fosc/(Fpwm*64*4)-1 es menor a 0xFFFF
   */    setup_timer2(TMR_INTERNAL | TMR_DIV_BY_64, (int16)(Fosc/(Fpwm*64*4))-1):/*el macro sera igual a setup_timer2(TMR_INTERNAL | TMR_DIV_BY_8, (Fosc/(Fpwm*16*4))-1)
   */    setup_timer2(TMR_INTERNAL | TMR_DIV_BY_64, 0xFFFF);                     //De lo contrario el macro sera igual a setup_timer2(TMR_INTERNAL | TMR_DIV_BY_8, 0xFFFF)
#endif

Y a continuación muestro el código de Ejemplo para usar la librería.
Código: [Seleccionar]
///////////////////////////////////////////////////////////////////////////////
//Autor:   Luis Alberto Vargas Tijerino.
//Alias:   Bigluis.
//Pais:    Nicaragua.
//Fecha:   24-Nov-10.
///////////////////////////////////////////////////////////////////////////////
#include <16f887.h>//pic a utilizar

#FUSES NOWDT       //No Watch Dog Timer
#FUSES HS          //High speed Osc (> 4mhz for PCM/PCH) (>10mhz for PCD)
#FUSES NOPUT       //No Power Up Timer
#FUSES MCLR        //Master Clear pin enabled
#FUSES NOPROTECT   //Code not protected from reading
#FUSES NOCPD       //No EE protection
#FUSES NOBROWNOUT  //No brownout reset
#FUSES IESO        //Internal External Switch Over mode enabled
#FUSES FCMEN       //Fail-safe clock monitor enabled
#FUSES NOLVP       //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NODEBUG     //No Debug mode for ICD
#FUSES NOWRT       //Program memory not write protected
#FUSES BORV40      //Brownout reset at 4.0V
#FUSES RESERVED    //Used to set the reserved FUSE bits

#define Fosc 8000000         //Fosc=8Mhz
#include <PWM_FREQ.c>

#include <Puertos.c>

void main(){
   signed int sel_Fpwm=0;
   unsigned int Duty=127;
   TRISB=0XFF;                         //Todos los pines de PORTB seran entradas.
   setup_comparator(NC_NC);            //Desconectamos los comparadores Analogicos
   SETUP_ADC_PORTS(NO_ANALOGS);        //Solo AN0 sera analogico los demas digitales.
   SETUP_ADC(ADC_OFF);                 //Apagamos el ADC
   setup_ccp1(CCP_PWM);                //Configuramos CCP1 en modo PWM simple.
   while(TRUE){                        //Inicio del ciclo Infinito
      while(!PORTB);                   //Espera a que se active un pin del PORTB.
      delay_ms(10);                    //Retardo de 10ms para eliminar rebotes.
      if(RB0)                          //Si se activo RB0
         if(++sel_Fpwm>3)              //preincrementamos sel_Fpwm y si es mayor que 3
            sel_Fpwm=0;                //igualamos sel_Fpwm a 0.
      if(RB1)                          //Si se activo RB1
         if(--sel_Fpwm<0)              //predecrementamos sel_Fpwm y si es menor que 0
            sel_Fpwm=3;                //igualamos sel_Fpwm a 2.
      if(RB2)Duty+=4;                  //Si se activo RB2 incrementamos Duty en 5.
      if(RB3)Duty-=4;                  //Si se activo RB3 decrementamos Duty en 5.
      
      
      set_pwm1_duty(duty);             //El %DT de la senial sera Duty.
      
      switch(sel_Fpwm) {              
         case 0 :                      //Si sel_Fpwm es 0
            set_pwm_freq(500);         //Fpwm sera 500
            break;
         case 1 :                      //Si sel_Fpwm es 1
            set_pwm_freq(1000);        //Fpwm sera 1000
            break;
         case 2 :                      //Si sel_Fpwm es 2
            set_pwm_freq(1500);        //Fpwm sera 1500
            break;
         default:                      //De lo contrario
            set_pwm_freq(2000);        //Fpwm sera 2000
      }
      while(PORTB);                    //Espera a que se desactiven los pines de PORTB
   }
}

La librería "Puertos.c" la pueden encontrar aquí

Y finalmente adjunto los archivos de la simulación y el código.
« Última modificación: 27 de Noviembre de 2010, 14:21:58 por bigluis »
Tutoriales de Qt C++

No es necesario que hagamos Grandes cosas, sino que lo que hagamos sea importante.

SI la NECESIDAD es la MADRE del CONOCIMIENTO, SEGURAMENTE la PEREZA su TÍA.

Cuando el ARTE requiere de PRECISION le llamamos CIENCIA