Autor Tema: una pequeña ayuda para resolver un problema con el pic 12f629  (Leído 1989 veces)

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

Desconectado CcBeNiTocC

  • PIC10
  • *
  • Mensajes: 14
una pequeña ayuda para resolver un problema con el pic 12f629
« en: 17 de Junio de 2018, 16:34:11 »
Buen día, me gustaría saber si alguien me ayudaría en la verificación de un código, para poder entender de mejor forma las interrupciones ya que en este momento me encuentro en una encrucijada.
En principio lo que quiero realizar con el pic 12f629 es un programa el cual con solo 1 botón controlar un numero de formas en que 2 led RGB de 1w puedan brillar, el problema que en este momento me limita es el control de un pulso de PWM para así crear una secuencia de colores lenta, y después de oprimir el botón seguir con otra secuencia.
Lo que no entiendo es si con el botón puedo desactivar el PWM por interrupción con el timer 0 y pasar a la siguiente secuencia que sería un color en específico.
Este es el código que por el momento tengo construido y funcional.

#include <12f629.h>
#FUSES INTRC_IO,NOWDT,NOMCLR,BROWNOUT
#use delay(clock=20M)
#use standard_io(a)
#int_timer0

void TIMER_0(int pwm0){       //PWM0
   int cont;                     //Variable de Contador
   if(cont>50)                   //Si cont 50 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_a0);       //Salida PWM0 a nivel alto
   else                          //Caso contrario
      output_low(PIN_a0);        //Salida PWM0 a nivel bajo
   set_timer0(200);              //Seteo de interrupcion
}
void main(){                     //Funcion principal
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1); 
   set_timer0(200);
   enable_interrupts(INT_TIMER0);           
   enable_interrupts(GLOBAL);                       
   while(true){
   int b;
      for(b=0;b<50;b++){
      TIMER_0(b);            //a0 pwm incrementa
      delay_ms(50);
      }
      for(b=50;b>1;b--){
      TIMER_0(b);            //a0 pwm disminuye
      delay_ms(50);
   }                           
}
}

Hasta el momento solo tengo un PWM pero implementare dos más para cada canal RGB.
Espero alguien me pueda ayudar así sea en la comprensión. Gracias
 
 

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:una pequeña ayuda para resolver un problema con el pic 12f629
« Respuesta #1 en: 18 de Junio de 2018, 20:34:40 »
Hola benito, por lo que veo no comprendes como es que funciona una interrupcion. Asi que mejor en ves de complicarnos por ahora sobre como hacer un PWM variable, presiento que es mejor explicar como es que funciona una interrupcion, y como es que debe programarse.


Tu micro, comienza a ejecutar instruccion es en el vector de reset, el vector de reset es el punto de memoria a la que va el micro al momento de producirse un reset, la vuelta de tension, etc.
De alli hace un par de cosas internas para comenzar a manejar el lenguaje C y se llama a la funcion main. Nosotros ponemos un loop infinito alli. Es decir nunca saldria de alli ( por mas que se llame a una funcion volveria al loop infinito) si la ejecucion fuera normal.
Y aqui es donde entra la interrupcion.

Voy a usar una imagen para que se entienda mejor.


La interrupcion ocurre por hardware, y al producirse el micro guarda donde estaba (la instruccion que le tocaba ejecutar) y salta a la posiciion de memoria que maneja las interrupcion, en tu caso pensalo como si fuera la funcion de interrupcion. Ejecuta la funcion esa, y vuelve a donde dejo.
En la imagen podes ver las 2 funciones, el main a la izquierda y la interrupcion a la derecha, cuando se produce la interrupcion el micro guarda la posicion de memoria de la instruccion numero 5 del main. Y se va a ejecutar la interrupcion, cuando sale vuelve donde habia quedado. Y asi continua.

Si uno lo viera "rapidamente" Podria pensar que esas 2 funciones estan ejecutandose de forma "paralela", es decir al mismo tiempo. Pero lo mas importante ahora, es que NUNCA pero NUNCA desde el main, se llama a la funcion de interrupcion como vos estas haciendo, sino que el mismo Timer es quien le avisa al CPU del microcontrolador y este es quien manda a ejecutar esa funcion.

Supongamos que queremos hacer titilar un led con una interrupcion:



Código: C
  1. void TIMER_0(void){
  2.   set_timer0(0);           //Le puse 0 , pero podria ser cualquier numero
  3.   output_toggle(PIN_B0);
  4. }
  5. void main(void){
  6.  
  7.    // Configuracion del timer
  8.    // Activo interrupcion del timer
  9.  
  10.    while(true){
  11.    }                          
  12. }

Como observas, en el main, nuestro micro se pasaria haciendo nada, encerrado en ese while, pero que gracias a la interrupcion sale de alli y ejecuta el toggle, luego vuelve al main.
Pienso que primero deberias comenzar con esto asi.. Luego haces un PWM como lo tenes realizado

Código: C
  1. int cont;                     //Variable de Contador
  2.    int pwm0;
  3.  
  4. #int_timer0
  5. void TIMER_0(void){       //PWM0
  6.    set_timer0(200);              //Seteo de interrupcion
  7.    if(cont>50)                   //Si cont 50 se inicializa
  8.       cont=0;                    //Cont = 0
  9.    else                          //Caso contrario
  10.       cont++;                    //Incrementa en una unidad cont
  11.    if(cont>0&&cont<pwm0)         //Si 0<Cont<PWM0
  12.       output_high(PIN_a0);       //Salida PWM0 a nivel alto
  13.    else                          //Caso contrario
  14.       output_low(PIN_a0);        //Salida PWM0 a nivel bajo
  15. }

Un par de cambios y otros que no hice pero que deberias.
- Usa las llaves { } en los if y else
- el set_timer siempre al comienzo
- la funcion de interrupcion al uno no deber llamarla, no se le puede pasar valores, por lo tanto sus parametros son void.
- El int cont, deberia ser global, sino donde esta declarado apenas termina la funcion TIMER_0 procede a borrarse, y crearse de nuevo cuando entre. Entonces nunca llegaria a 50.
- Declare otra variable global llamada pwm0, en tu main ahora vas a modificar esa variable en ves de "llamar" a la funcion de interrupcion.


Código: C
  1. void main(){                     //Funcion principal
  2.    setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);  
  3.    set_timer0(200);
  4.    enable_interrupts(INT_TIMER0);            
  5.    enable_interrupts(GLOBAL);                      
  6.    while(true){
  7.       int b;
  8.       for(b=0;b<50;b++){
  9.       pwm0 = b;
  10.       delay_ms(50);
  11.       }
  12.       for(b=50;b>1;b--){
  13.       pwm0 = b;
  14.       delay_ms(50);
  15.    }                          
  16. }
  17. }

Desconectado CcBeNiTocC

  • PIC10
  • *
  • Mensajes: 14
Re:una pequeña ayuda para resolver un problema con el pic 12f629
« Respuesta #2 en: 22 de Junio de 2018, 03:29:23 »
Buen día, gracias por la ayuda, implemente todas tus recomendaciones y ahora entiendo mejor las interrupciones pero ahora tengo un pequeño problema el cual no logro comprender, la cosa es que ya tengo configurada la interrupción por RA2_int_12F629 para que al ser pulsado un botón cambien de estado la variable botón y sume 1 al siguiente paso a aplicar y ejecute el siguiente código de líneas deshabilitando el TIMER0 y ejecutando en un while hasta que la variable sume +1 así pasa a la siguiente condición y ejecuta el ejemplo, el problema es que cuando le pido que me saque un sencillo código por A3 (botón=2), no hace nada pero cuando oprimo otra vez y (botón==3) si ejecuta el programa en A1, es algún problema de programación?. Igualmente gracias por la ayuda =)

#include <12f629.h>
#FUSES  HS,NOWDT,NOMCLR,BROWNOUT
#use delay(clock=20M)
#use standard_io(a)

int cont;                     //Variable de Contador
int pwm0;
int boton = 0;
#INT_TIMER0
void timer_0(void){                //PWM0
   set_timer0(200);              //Seteo de interrupcion                   
   if(cont>50) {                  //Si cont 50 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_a0);       //Salida PWM0 a nivel alto
   }
   else  {                        //Caso contrario
      output_low(PIN_a0);        //Salida PWM0 a nivel bajo
   }

}
#int_EXT
void oprimido(void){
       
        disable_interrupts(INT_TIMER0);
        boton++;
           
     }
                   
   
void main(){                     //Funcion principal
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1); 
   set_timer0(200);
   enable_interrupts(INT_TIMER0);
   enable_interrupts(INT_EXT);
   ext_int_edge( H_TO_L );
   enable_interrupts(GLOBAL);
   while(true){
     
       while (boton==1){         
        output_low(pin_a0);       
        output_high(pin_a1);       
        delay_ms(1000);
        output_low(pin_a1);
        delay_ms(1000);
       }
     
   
       while (boton==2){
       
        output_high(pin_a3);            //este es el que no funciona
        delay_ms(1000);
        output_low(pin_a3);
        delay_ms(1000);
               
       }
       while (boton==3){
       
        output_high(pin_a0);
        delay_ms(1000);
        output_low(pin_a0);
        delay_ms(1000);
       
       
       }
     enable_interrupts(INT_TIMER0);
     boton=0;
     
     int b;
      for(b=0;b<50;b++){
      pwm0 = b;             //a0 pwm incrementa
      delay_ms(20);
      }
      for(b=50;b>1;b--) {
      pwm0 = b;             //a0 pwm incrementa
      delay_ms(20);
                 
   }
  }
}

Desconectado KILLERJC

  • Colaborador
  • DsPIC33
  • *****
  • Mensajes: 8242
Re:una pequeña ayuda para resolver un problema con el pic 12f629
« Respuesta #3 en: 22 de Junio de 2018, 09:13:43 »
Citar
el problema es que cuando le pido que me saque un sencillo código por A3

GP3 es unicamente entrada. No posee la capacidad de funcionar como salida.

Una consideracion con tu codigo..
Agregarle un limite a boton cuando lo incrementas, es decir preguntar si es mayor a 3 y hacer lo que corresponde, por ejemplo ponerlo a 0. Acostumbrate a hacerlo en la parte donde lo incrementas, asi podes usar el 0 tambien como indice. Es decir siempre que tenes un indice, sea de array o lo que sea, muy atento a no pasarse.

Desconectado CcBeNiTocC

  • PIC10
  • *
  • Mensajes: 14
Re:una pequeña ayuda para resolver un problema con el pic 12f629
« Respuesta #4 en: 03 de Julio de 2018, 22:10:14 »
Buen día, hasta el momento tenía el proyecto en espera, pero ya me he puesto a tratarlo más y ahora tengo otro problema del cual no sé si tenga solución o ya es limitación del propio pic, el problema nace cuando quiero desactivar o activar una interrupción por medio de una interrupción externa.
Ya que al realizar el proyecto en proteus todo inicia bien, timer0 ejecuta bien el fade del rgb con el pwm programado, pero a la hora de oprimir el botón de interrupción externa el pic deja de funcionar, o en si la simulación deja de funcionar y creo que el error está en el modo de funcionamiento de las interrupciones y algún error en el código que no logro ver.


#include <12f629.h>
#FUSES  INTRC_IO,NOWDT,NOMCLR,BROWNOUT
#use delay(clock=4M)
#use standard_io(a)
int time = 5;
int time1 = 20;
int8 cont,cont1;                     //Variable de Contador
int pwmR,pwmG,pwmB;                  //pwm fade
int pwmR1,pwmG1,pwmB1;               //pwm de eleccion de color
int boton = 0;                       //variable de almacenamiento del boton
int p = 100;                         //100% == 255   

#int_EXT                             //interupccion del boton
void oprimido(void){             
       
        disable_interrupts(INT_TIMER0);                  //desactiva timer0 (pwm fade)
        enable_interrupts(INT_TIMER1);                   //activa timer1 (pwm color estatico) 
        boton++;                                         //se aumenta en 1 el boton
     
     }
#INT_TIMER0
void timer_0(void){                //PWM0
   set_timer0(190);              //Seteo de interrupcion                   
   if(cont>100) {                  //Si cont 100 se inicializa
      cont=0;                    //Cont = 0
   }
   else    {                      //Caso contrario
      cont++;                    //Incrementa en una unidad cont
   }
   if(cont>0&&cont<pwmR) {        //Si 0<Cont<PWM0
      output_high(PIN_a0);       //Salida PWM0 a nivel alto
   }
   else  {                        //Caso contrario
      output_low(PIN_a0);        //Salida PWM0 a nivel bajo
   }
   if(cont>0&&cont<pwmG) {        //Si 0<Cont<PWM0
      output_high(PIN_a1);       //Salida PWM0 a nivel alto
   }
   else  {                        //Caso contrario
      output_low(PIN_a1);        //Salida PWM0 a nivel bajo
   }
   if(cont>0&&cont<pwmB) {        //Si 0<Cont<PWM4
      output_high(PIN_a4);       //Salida PWM4 a nivel alto
   }
   else  {                        //Caso contrario
      output_low(PIN_a4);        //Salida PWM4 a nivel bajo
   }
}
#INT_TIMER1
void TIMER_1(void){       //PWM0 PWM1 PWM2
   set_timer1(65490);              //Seteo de interrupcion                   
 
   if(cont1>100){                   //Si cont 100 se inicializa
      cont1=0;                    //Cont = 0
   }
   else   {                       //Caso contrario
      cont1++;                    //Incrementa en una unidad cont
   }
   if(cont1>0&&cont1<pwmR1) {        //Si 0<Cont<PWMR1
      output_high(PIN_a0);       //Salida PWMR1 a nivel alto
   }
   else  {                        //Caso contrario
      output_low(PIN_a0);        //Salida PWMR1 a nivel bajo
   }
   if(cont1>0&&cont1<pwmG1)  {       //Si 0<Cont<PWMG1
      output_high(PIN_a1);       //Salida PWMG1 a nivel alto
   }
   else   {                       //Caso contrario
      output_low(PIN_a1);        //Salida PWMG1 a nivel bajo
   }
   if(cont1>0&&cont1<pwmB1){         //Si 0<Cont<PWM2
      output_high(PIN_a4);       //Salida PWMB1 a nivel alto
   }
   else   {                       //Caso contrario
      output_low(PIN_a4);        //Salida PWMB1 a nivel bajo
   }
   
}   

                   
   
void main(){                     //Funcion principal
   set_timer0(190);                              //carga time (10ms duty)
   setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);      //seteo timer0
   set_timer1(65490);                            //carga timer1(10ms duty)
   setup_timer_1(t1_INTERNAL|T1_DIV_BY_1);       //Seteo timer1   
   enable_interrupts(INT_TIMER0);                //activacion interupccion timer0
   enable_interrupts(INT_EXT);                   //activamos interupccion externa
   ext_int_edge( H_TO_L );                       //lectura por flanco de subida
   enable_interrupts(GLOBAL);           
   while(true){
     
       while (boton==1){                         //si el boton == 1
     
      pwmR1 = 100;             //naranja
      pwmG1 = 68;
      pwmB1 = 0;
      delay_ms(time1);
       }
       while (boton==2){
       
      pwmR1 = 20;             //morado
      pwmG1 = 0;
      pwmB1 = 100;
      delay_ms(time1);
      }               
 
       while (boton==3){
       
      pwmR1 = 68;             //amarillo
      pwmG1 = 100;
      pwmB1 = 0;
      delay_ms(time1);
       }
     
        if(boton>=4){
         boton=0;
         enable_interrupts(INT_TIMER0);        //activamos fade rgb
         disable_interrupts(INT_TIMER1);       //desactivamos interupccion timer1
        }
           
     int R,G,B;                 //fade rgb del timer0
      for(B=0;B<p;B++){
      pwmR = 100;              //B aumenta, R en alto y G estado bajo
      pwmG = 0;
      pwmB = B;
      delay_ms(time);
      }
      for(R=p;R>1;R--){
      pwmR = R;              //B EN ALTO, R DESMINUYE y G estado bajo
      pwmG = 0;
      pwmB = 100;
      delay_ms(time);
      }     
      for(G=0;G<p;G++) {
      pwmR = 0;             //B EN ALTO, R ESTADO BAJO y G AUMENTA
      pwmG = G;             
      pwmB = 100;
      delay_ms(time);
      }
      for(B=p;B>1;B--){
      pwmR = 0;              //B DISMINUYE, R ESTADO BAJO Y G EN ALTO
      pwmG = 100;
      pwmB = B;
      delay_ms(time);
      }
      for(R=0;R<p;R++) {
      pwmR = R;             //B EN BAJO, G ESTATICO Y R AUMENTA
      pwmG = 100;
      pwmB = 0;
      delay_ms(time);
      }
      for(G=p;G>1;G--){
      pwmR = 100;              //B EN BAJO, R ESTATICO Y G DISMINUYE
      pwmG = G;
      pwmB = 0;
      delay_ms(time);
      }
  }
 }


 

anything