Variar frecuencia de PWM

Buenas. Quisiera saber si alguien me podría explicar cómo variar la frecuencia en este código, ya que al simularlo no puedo.
El código es de ELECTGPL
Al hacer el calculo de la carga del timer0 a una fosc de 20MHz y un prescaler de 256 para que el tiempo sea 20mS, el valor de la carga del timer me da -135, lo cual está mal.

Cabe destacar que soy algo nuevo con esto del PWM digital.
Este es el código y web de ELECTGPL
http://electgpl.blogspot.com.ar/2014/10/multiple-pwm-sin-ccp.html

PHP:
#include <16F628A.h>             //MCU a utilizar
#FUSES NOWDT, HS, NOMCLR         //Fueses
#use delay(clock=20000000)       //Oscilador Externo
#int_TIMER0                      //LLamado a interrupcion 
void TIMER0_isr(int pwm0,        //Funcion Interrupcion
                int pwm1,        //Variables de link 
                int pwm2){       //PWM0 PWM1 PWM2
   int cont;                     //Variable de Contador
   if(cont>99)                   //Si cont 100 se inicializa
      cont=0;                    //Cont = 0
   else                          //Caso contrario
      cont++;                    //Incrementa en una unidad cont
   if(cont>0&&cont<pwm0)         //Si 0<Cont<PWM0 
      output_high(PIN_B0);       //Salida PWM0 a nivel alto
   else                          //Caso contrario
      output_low(PIN_B0);        //Salida PWM0 a nivel bajo
   if(cont>0&&cont<pwm1)         //Si 0<Cont<PWM1
      output_high(PIN_B1);       //Salida PWM1 a nivel alto
   else                          //Caso contrario
      output_low(PIN_B1);        //Salida PWM1 a nivel bajo
   if(cont>0&&cont<pwm2)         //Si 0<Cont<PWM2
      output_high(PIN_B2);       //Salida PWM2 a nivel alto
   else                          //Caso contrario
      output_low(PIN_B2);        //Salida PWM2 a nivel bajo
   set_timer0(255);              //Seteo de interrupcion 
}
void main(){                     //Funcion principal
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_2);  //Seteo timer0
   enable_interrupts(INT_TIMER0);            //Seteo timer0
   enable_interrupts(GLOBAL);                //Seteo timer0
   while(true){                  //Loop infinito
      TIMER0_isr(10,45,73);      //Se movera a la funcion
   }                             //PWM0=10%, PWM1=45%, PWM2=73%
}
 
Última edición por un moderador:
ahh es tan simple como complicado

el PWM es como sabemos de una frecuencia fija pero lo que varia es el ciclo de trabajo, es decir H y L van a tener diferente ancho en la misma frecuencia.

ahora
digamos que vas a tener un PWM de 20ms que normalmente lo usan para los servos futaba.
debes pensar que 20ms son 50 Hz entonces debes tener una resolucion para tu ciclo de trabajo

digamos que queremos una resolucion de 8 bits son 255 partes entonces debes tener en cuenta que debes dividir todo eso en 255 partes.

creo que eso da como resultado 78us ahora si
podemos construir un ciclo de trabajo.

declaramos timer
{
fijamos a 78us
contador++
si contador >=255
contador=0
}

ya fijamos un perido de 20ms bien facil
ahora falta el ciclo de trabajo

digamos que lo leemos de un potenciometro y prendemos en un led.

hay que leer potenciometro, compararlo con nuestro contador y con un simple if else hacemos PWM

valor= ADC.

si valor>=contador
{
prendemos led
}
esle
{
apagamos led
}

recuerda que todo eso se hace con entero de 8 bit sin signo
ejemplo

unsigned int8 valor;
unsigned int8 contador;

por que si no lo declaras del tipo unsigned tomara valores de -127 a 128. y no del tipo 0 a 255
 
Hola
La variable cont (0-100) te da el duty.
Las interrupciones ocurren cada x uS, y sera el tamaño de cada paso y tendrás 100 pasos
Es decir que el periodo de tu PWM = x * 100 (cambiando el valor de x puedes variar tu frecuencia)

Pero aquí tienes un problema, el predivisor es de 2, es decir que en 2 ciclos mas (según tu valor de carga tmr0=255) entrará nuevamente en una interrupción.
En teoría (según tus datos) las interrupciones deberían ocurrir cada 0.4us pero eso no es posible, ya que dentro de tu interrupción tienes instrucciones que duran mucho mas que eso.
En C no puedes controlar tiempos exactos, y lamento decirlo pero el código no es tan bueno, pero si va a funcionar, aunque control total de tiempos no tendrás.

Ojala me haya explicado. Saludos.
 
Última edición por un moderador:
ahh por que pregunto como funcionaba tal codigo

si es cierto que el 628 tiene pwm a hardware de 10 bits

pero hay veces que hacer pwm a software es util sobre todo si uno quiere varios pwm digo cada quien puede opinar diferente
 
Arriba