Pwm por software

Hola, estoy tratando de mejorar este ejercicio pwm por software y no consigo otra manera, que se puede mejorar para que no me de una advertencia el compilador?

C:
[CODE]#include <16f883.h>

#use delay(internal = 4MHz)

 //#use pwm(output=pin_c0, timer=1, frequency=1kHz, duty=30)

int i;



#int_timer0

void pwm_duty(int pwm0)

{

   int cont;

   if(cont>16)

      cont=0;

   else

      cont++;

    if(cont>0&&cont<pwm0)

      output_high(PIN_C0);

   else

      output_low(PIN_C0);



}





void main()

{

   setup_adc(ADC_CLOCK_INTERNAL); 

   setup_adc_ports(ALL_ANALOG);

   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);

   set_timer0(0);

   enable_interrupts(INT_TIMER0);

   enable_interrupts(GLOBAL);

 

 

   setup_ccp1(CCP_PWM);

   setup_timer_2(T2_DIV_BY_4,249,1);   // 1000 Hz. @ 4 MHz.

 

            

   while (true)

   {

  

 

  for(i=0;i<16;i++){

  pwm_duty(i);

  delay_ms(100);

 

  }

 

   for(i=16;i>0;i--){

  pwm_duty(i);

  delay_ms(100);

 

   }

 

   }

}
[/ICODE][/CODE]
 
Tal vez deshabilitando las interrupciones que has habilitado pero no tienes una subrutina que las maneje.

De todas formas el PIC16F883 tiene PWM por hardware, no veo por que inventar la pólvora cuando ya esta "todo echo" (hay que configurarlo pero lo difícil ya está).
 
Voy a buscar como hacerlo, gracias 🙂
No es para la escuela, es para aprender más!!!
include <16F883.h>
#device adc=8
#FUSES NOWDT
#FUSES INTRC_IO
#FUSES NOPUT
#FUSES NOMCLR
#FUSES NOPROTECT
#FUSES NOCPD
#FUSES NOBROWNOUT
#FUSES IESO
#FUSES FCMEN
#FUSES NOLVP
#FUSES NODEBUG
#FUSES NOWRT
#FUSES BORV40
#use delay(int=8000000)
void main()
{
setup_adc_ports(sAN0|VSS_VDD);
setup_adc(ADC_CLOCK_DIV_2);
int8 tOFF, tON;
while(1){
set_adc_channel(0);
tOFF = read_adc();
tON = 255 - tOFF;
delay_us(tOFF);
output_low(PIN_C0);
delay_us(tON);
output_high(PIN_C0);
}
}
 
Última edición:
Es que hay que tomar una interrupción como un evento, no para ponerse a hacer cosas en su void.
Para eso tienes un loop donde puedes cachar todo, siempre y cuando no tengas retardos.
Lo más conveniente es usar banderas y actuar cuando alguna de ellas se active por x interrupción.
Que viéndolo desde el tipo registro, ya tiene su bit que lo es, pero en PIC C de CCS hay que declararlos.
Cuando se da la interrupción solo activas una bandera y dentro del loop te enteras, la desactivas y haces lo que tengas que hacer.
Y obviamente, tampoco es necesario que hagas todo esto en el loop, es mejor crear sub procedimientos.
En verdad que estudiando lenguaje ensamblador se aprende mucho sobre cómo se debe programar.
 
Alejándome un poco del hard (no se bien sus limitaciones y las formas que tiene el CSS), yo usaría contadores y lo resolvería directamente desde la rutina de interrupción, ej:

C:
/*
    - Objetivo: Generar una señal PWM a partir de un timer y su rutina de irq.
    - Características de la Señal a generar: Período 10mS (100 Hz) con un duty al 45%.  
    - Resolución del Duty: 1%, para conseguirlo será necesario generar una irq c/100uS (10mS/100)
*/

...    // Llamado a las librerías necesarias

...    // Declaraciones necesarias
#define DUTY_REF (uint8_t)45    //Duty o Ton de referencia, nunca puede ser mayor o igual a 100


...                    //Definición de variables globales necesarias
uint8_t contador;    //Variable global


...                    //Declaración de funciones necesarias
void irq_timer(void)
{
    contador++;

    if(contador<DUTY_REF)
        puertoX=1;    //Seteo el puerto en estado alto => Ton  
    else if(contador<100)
        puertoX=0;    //Seteo el puerto en estado bajo => Toff  
    else
    {
        contador=0;    //Reseteo el contado a 0  
        puertoX=1;    //Seteo el puerto en estado alto => Ton      
    }

    ...//Algún posible registro o flag que deba restearse
}

void main(void)
{
    ... //Inicialización de variables
    contador=0;    //Al ser global, se inicializa en 0, pero nunca está de más esta inicialización en caso de alguna modificación futura
   
    ... //Inicialización necesaria
    inicializar_timer();//Llamo a una función que inicializa el timer para generar una irq c/100uS

    ...    //Operaciones necesarias
   
    while(1)    //Bucle principal
    {
        ...//Operaciones necesarias, entre ellas podría ser un sleep si el uC lo permite.
    }
}

En caso de ser necesario una frecuencia mayor y que por limitaciones del hard o del propio proyecto no se quiera tener una interrupción en tan corto tiempo (por ej. c/10uS), se podría resignar la resolución del Duty y en vez de trabajar con una resolución del 1%, subirlo al 10%; de esta forma tu contador sería hasta 10 en vez de hasta 100.
 
Atrás
Arriba