Autor Tema: como encender y apagar un led por medio de una interrupcion???  (Leído 4751 veces)

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

Desconectado jdreyesa

  • PIC10
  • *
  • Mensajes: 11
como encender y apagar un led por medio de una interrupcion???
« en: 04 de Febrero de 2009, 16:14:12 »
hola mi pregunta es como puedo prender un led y apagarlo por medio de una interrupcion esto cuando en un valor tomado del adc(potenciometro) se encienda.... y en otro se apague.

en estos momentos tengo implementado este codigo:

/****************************CODIGO PARA EL RANGO****************************************************/

       if(1150 == Result){      
         LED1_TRIS   = 0;
          LED1_IO = 1;     
          }

      else if(1300 == Result){
         LED1_IO = 0;
      }
/****************************************************************************************************/

en el cual si se me enciende el led pero cuando se apaga el led el programa se queda pegado y lo tengo que resetear........ me dijeron que lo implementara por medio de la interrupcion pero la verdad no se

entonces era para ver si me ayudaban o arreglando este codigo o implementando la interrupcion mi pic que utilizo es un pic24fj128ga010 muchas gracias         
ReyesA

Desconectado arcachofo

  • PIC16
  • ***
  • Mensajes: 126
    • Foro para usuarios Linux.
Re: como encender y apagar un led por medio de una interrupcion???
« Respuesta #1 en: 05 de Febrero de 2009, 02:10:43 »
Hola... quizás tendrías que poner todo el programa... no crees?

esa rutina está dentro de un bucle?...

No sé si dará igual, pero yo diría que sería más correcto escribir: If ( Result==1150)

Si solo es encender o apagar un led según la lectura de adc, porqué hacerlo por interrupciones?

Que tipo de adc lleva ese pic?... osea de cuantos bits?

Desconectado jdreyesa

  • PIC10
  • *
  • Mensajes: 11
Re: como encender y apagar un led por medio de una interrupcion???
« Respuesta #2 en: 05 de Febrero de 2009, 12:50:31 »

#include "system.h"
#include "iomapping.h"
/*****************************************************************************
 *Constantes
 *****************************************************************************/
//ADC channels numbers

#define ADC_DENSIDAD      ADC_DEN_CHAN   //define canal densidad
#define ADC_HIDROGENO        ADC_HID_CHAN   //define canal hidrogeno
#define ADC_VOLTAJE            ADC_VOL_CHAN   //define canal voltaje
#define ADC_TEMPERATURA      ADC_TEM_CHAN   //define canal temperatura
#define ADC_SWITCH_DELAY    600         // Delay after input switching
#define ADC_POS_NUMBER      6         // Number position
#define ADC_POS_MEM         13         // Memory sign position
#define AVCC                1240      // Voltaje de Referencia, mV densidad
#define AVCC1                1300      // Voltaje de Referencia, mV hidrogeno
#define AVCC2                1350      // Voltaje de Referencia, mV voltaje
#define AVCC3                2600      // Voltaje de Referencia, mV temperatura

/*****************************************************************************
 * Arrays: _densidad_str y las demas
 * Overview: datos de variables y sus caracteres.
 *****************************************************************************/
char _densidad_str[16] =     "Den =           ";
char _hidrogeno_str[16] =    "Hid =           ";
char _voltaje_str[16] =      "Vol =           ";
char _temperatura_str[16] =  "Tem =           ";
//char _peligro_str[16] =      " FUERA DE RANGO ";

unsigned char    _uADCState;
unsigned int   _uADCWait;
unsigned int    _uADCDensidad;
unsigned int    _uADCHidrogeno;
unsigned int    _uADCVoltaje;
unsigned int    _uADCTemperatura;       
unsigned char    _uADCFromMemory;   // Switch que toma valor de las variables de la
                                    // EEPROM y no del ADC.

/*****************************************************************************
* Funcion: ADCInit
* Descripcion: Inicializacion ADC y màquina de estados.
******************************************************************************/
void ADCInit(){
   AD1CON1 = 0x80E4;            //Turn on, auto sample start, auto-convert
   AD1CON2 = 0;               //AVdd, AVss, int every conversion, MUXA only
   AD1CON3 = 0x1F05;            //31 Tad auto-sample, Tad = 5*Tcy
   
   AD1CHS = ADC_DENSIDAD;         //Con este canal se empieza la toma de datos

   TRISBbits.TRISB2 = 1;
   TRISBbits.TRISB3 = 1;
   AN_DEN_PIN = 0;               //Disable digital input on AN5
   AN_HID_PIN = 0;   
   AN_VOL_PIN = 0;   
   AN_TEM_PIN = 0;   
   AD1CSSL = 0;               //No scanned inputs
    _uADCWait = ADC_SWITCH_DELAY;
    _uADCState = 1;
    _uADCFromMemory = 0;            //Show current temperature
}

/*****************************************************************************
* Function: ADCProcessEvents
* Preconditions: ADCInit must be called before.
* Overview: Maquina de Estados para la toma de datos de la densidad por el
* potenciometro.
******************************************************************************/
void ADCProcessEvents(){
unsigned long Result;

    switch(_uADCState){

        case 1:                               // TOMA DE DATOS PARA DENSIDAD
         
          while(!AD1CON1bits.DONE);              // Espera que el dato se complete       
         
        Result = (long) ADC1BUF0;   
          Result = (Result*AVCC)/1024;



/***************************CODIGO PARA LECTURA DE DATOS EN LA EEPROM(DENSIDAD)***********************/
        _uADCDensidad -= _uADCDensidad>>4;
         _uADCDensidad += Result;
         Result = _uADCDensidad>>4;
 
       // Leer densidad almacenada en EEPROM 
         _densidad_str[ADC_POS_MEM] = ' ';        
         if(ADCIsFromMemory()){
           Result = ADCLoadDensidad();         
           _densidad_str[ADC_POS_MEM] = 'M';
          }
/****************************************************************************************************/
         
/****************************CODIGO PARA EL RANGO****************************************************/
       if(Result>1000){
               _densidad_str[ADC_POS_MEM] = 'P';     
          }
/****************************************************************************************************/
        ADCShortToString((int)Result, 1, _densidad_str+ADC_POS_NUMBER);
          _densidad_str[ADC_POS_NUMBER+4] = ' ';    // Sweep least significant digit
          AD1CHS = ADC_HIDROGENO;
        _uADCState++;
          break;

        case 3:                               // TOMA DE DATOS PARA HIDROGENO

          while(!AD1CON1bits.DONE);              // Espera que el dato se complete       
         
        Result = (long) ADC1BUF0;   
          Result = (Result*AVCC1)/1024;
      

/***************************CODIGO PARA LECTURA DE DATOS EN LA EEPROM(HIDROGENO)***********************/
        _uADCHidrogeno -= _uADCHidrogeno>>4;
         _uADCHidrogeno += Result;
         Result = _uADCHidrogeno>>4;
 
       // Leer densidad almacenada en EEPROM 
         _hidrogeno_str[ADC_POS_MEM] = ' ';        
         if(ADCIsFromMemory()){
           Result = ADCLoadHidrogeno();         
           _hidrogeno_str[ADC_POS_MEM] = 'M';
          }
/********************************************************************************************/
/****************************CODIGO PARA EL RANGO****************************************************/
       if(Result>1100){
               _hidrogeno_str[ADC_POS_MEM] = 'P';     
          }
/****************************************************************************************************/       
        ADCShortToString((int)Result, 4, _hidrogeno_str+ADC_POS_NUMBER);
          _hidrogeno_str[ADC_POS_NUMBER+4] = ' ';    // Sweep least significant digit
          AD1CHS = ADC_VOLTAJE;                // aqui se cambiaria el canal a tomar
    //      AD1CHS = ADC_DENSIDAD;
          _uADCState++;
        break;

        case 5:                               // TOMA DE DATOS PARA VOLTAJE

          while(!AD1CON1bits.DONE);              // Espera que el dato se complete       
         
        Result = (long) ADC1BUF0;   
          Result = (Result*AVCC2)/1024;

/***************************CODIGO PARA LECTURA DE DATOS EN LA EEPROM(VOLTAJE)***********************/
        _uADCVoltaje -= _uADCVoltaje>>4;
         _uADCVoltaje += Result;
         Result = _uADCVoltaje>>4;
 
       // Leer densidad almacenada en EEPROM 
         _voltaje_str[ADC_POS_MEM] = ' ';        
         if(ADCIsFromMemory()){
           Result = ADCLoadVoltaje();         
           _voltaje_str[ADC_POS_MEM] = 'M';
          }
/********************************************************************************************/
/****************************CODIGO PARA EL RANGO****************************************************/
       if(1150 == Result){      
         LED1_TRIS   = 0;
          LED1_IO = 1;     
          }

      else if(1300 == Result){
         LED1_IO = 0;
      }

      
/****************************************************************************************************/           
        ADCShortToString((int)Result, 3, _voltaje_str+ADC_POS_NUMBER);
          _voltaje_str[ADC_POS_NUMBER+4] = ' ';          // Sweep least significant digit
          AD1CHS = ADC_TEMPERATURA;                // aqui se cambiaria el canal a tomar
          _uADCState++;
        break;
   
        case 7:                               // TOMA DE DATOS PARA TEMPERATURA

          while(!AD1CON1bits.DONE);              // Espera que el dato se complete       
         
        Result = (long) ADC1BUF0;   
          Result = (Result*AVCC3)/1024;

/***************************CODIGO PARA LECTURA DE DATOS EN LA EEPROM(TEMPERATURA)***********************/
        _uADCTemperatura -= _uADCTemperatura>>4;
         _uADCTemperatura += Result;
         Result = _uADCTemperatura>>4;
 
       // Leer densidad almacenada en EEPROM 
         _temperatura_str[ADC_POS_MEM] = ' ';        
         if(ADCIsFromMemory()){
           Result = ADCLoadTemperatura();         
           _temperatura_str[ADC_POS_MEM] = 'M';
          }
/********************************************************************************************/
/****************************CODIGO PARA EL RANGO****************************************************/
       if(Result>2400){
               _temperatura_str[ADC_POS_MEM] = 'P';     
          }
/****************************************************************************************************/         
        ADCShortToString((int)Result, 2, _temperatura_str+ADC_POS_NUMBER);
          _temperatura_str[ADC_POS_NUMBER+4] = ' ';          // Sweep least significant digit
          AD1CHS = ADC_DENSIDAD;                      // aqui se cambiaria el canal a tomar
      //    AD1CHS = ADC_DENSIDAD;
          _uADCState++;
        break;

       case 2:
        case 4:
      case 6:
      case 8:
           
            if(0 == _uADCWait--){               // Tiempo(Delay) entre cambio de canal
                _uADCWait = ADC_SWITCH_DELAY;
                _uADCState++;
            }
            break;
        break;
        default:
           _uADCState = 1;
    }
}

EN ROJO ES DONDE TENGO EL PROBLEMA ESTA ES LA MAQUINITA DE ESTADOS PARA LA TOMA DE DATOS DEL ADC MI PIC ES DE 16 bits me dijeron que lo pudia hacer por interrupciones..........EL PROBLEMA ES CUANDO SE APAGA EL LED YA QUE SE QUEDA PEGADO EL PROGRAMA.......................
ReyesA

Desconectado arcachofo

  • PIC16
  • ***
  • Mensajes: 126
    • Foro para usuarios Linux.
Re: como encender y apagar un led por medio de una interrupcion???
« Respuesta #3 en: 05 de Febrero de 2009, 14:24:49 »
Y la variable Result solo puede tomar esos dos valores: 1150 o 1300?


Desconectado jdreyesa

  • PIC10
  • *
  • Mensajes: 11
Re: como encender y apagar un led por medio de una interrupcion???
« Respuesta #4 en: 05 de Febrero de 2009, 14:52:30 »
no el en el caso cuando toma los valores de voltaje Result va de 0 a 1350
ReyesA

Desconectado arcachofo

  • PIC16
  • ***
  • Mensajes: 126
    • Foro para usuarios Linux.
Re: como encender y apagar un led por medio de una interrupcion???
« Respuesta #5 en: 05 de Febrero de 2009, 16:01:28 »
Bueno, pues yo creo que tendrías que poner que se encienda por encima de un valor y se apague por debajo de ese valor (o de otro), algo como:

Código: [Seleccionar]
/****************************CODIGO PARA EL RANGO****************************************************/

       LED1_TRIS   = 0;

       if (Result > 1000){     
          LED1_IO = 1;     
       }

       if (Result <= 1000){
         LED1_IO = 0;
       }

/****************************************************************************************************/

En vez de 1000 pones el valor que tu necesites.

Pero tal y como lo tienes el led solo se va a encender si Result vale exactamente 1150.

Otra cosa es que el TRIS deberías ponerlo fuera del condicional, ya que quieres que sea salida tanto para encender el led como para apagarlo.
Lo normal sería poner el TRIS al principio de la funcion principal fuera del flujo del programa, a no ser que estés cambiando el pin de entrada a salida.

Saludos.

Desconectado jdreyesa

  • PIC10
  • *
  • Mensajes: 11
Re: como encender y apagar un led por medio de una interrupcion???
« Respuesta #6 en: 05 de Febrero de 2009, 17:05:12 »
NO FUNCIONA AMIGO YA LO PROBE VI QUE EN LOS CASE 2,4,6,8 ME FALTABAN PONER LOS BREAKS PERO TODAVIA SIGUE SIN FUNCIONAR
ReyesA

Desconectado arcachofo

  • PIC16
  • ***
  • Mensajes: 126
    • Foro para usuarios Linux.
Re: como encender y apagar un led por medio de una interrupcion???
« Respuesta #7 en: 06 de Febrero de 2009, 04:57:22 »
Bueno... no sé como vá el flujo del programa, desde donde se llama a la función ADCProcessEvents()? y que es lo que pasa antes?

Es muy grande el programa completo?

Desconectado jdreyesa

  • PIC10
  • *
  • Mensajes: 11
Re: como encender y apagar un led por medio de una interrupcion???
« Respuesta #8 en: 06 de Febrero de 2009, 19:33:41 »
si claro la verdad es muy grande.........cuando lo simule vi que cuando se apaga el LED la señal que tengo en un archivo aparte
IFS0bits.T1IF se pone en uno y a lo que entiendo este es un bit que levanta la bandera q se da una interrupcion talves aqui es donde tengo el problema............y ya el programa en si si es grande.
ReyesA

Desconectado arcachofo

  • PIC16
  • ***
  • Mensajes: 126
    • Foro para usuarios Linux.
Re: como encender y apagar un led por medio de una interrupcion???
« Respuesta #9 en: 07 de Febrero de 2009, 04:05:15 »
Entiendo...

No sé que pic estarás usando, pero ese bit tiene pinta de ser el flag de interrupciones del timer1.

El tema sería saber algo más de como funciona todo el programa; por ejemplo ¿a que correspone LED1_IO?...
Y ¿que es lo que se supone que hace el led y cuando?, es posible que LED1_IO no encienda directamente el led, sino que sea un flag que es leido en la rutina de interrupciones, quizás el timer1 se usa para crear una base de tiempo probocando una interrupción cada cierto tiempo, entonces en la rutina de interrupciones se lee el flag del led... si está a 1 se enciende el led y si está a 0 se apaga, pero esto no tiene demasiado sentido a no ser que hayan más cosas,... por ejemplo que el led no se quede simplemente encendido, sino que parpadee cuando el valor adc sea de un valor determinado o mayor o menor que cierto valor, entonces si tiene sentido porque timer1+interrupciones se usa para crear la base de tiempo que hace parpadear al led y posiblemente otras cosas más...

La pista a seguir podría ser... ¿que es LED1_IO? 
Y por otro lado buscar como se enciende realmente el led... quiero decir, suponiendo que el led esté conectado a (por ejemplo) PORTB.0... donde aparece PORTB.0???...
hay algún: #define lo_que_sea   PORTB.0 ??... o en algún sitio pone POTRB.0=1...

 ... y ...  ¿como es la rutina de interrupciones?



Desconectado jdreyesa

  • PIC10
  • *
  • Mensajes: 11
Re: como encender y apagar un led por medio de una interrupcion???
« Respuesta #10 en: 09 de Febrero de 2009, 21:58:58 »
ya estoy viendo donde tengo el problema y es que en la tarjeta de desarrollo los leds estan o se controlan con el PORTA y hay un boton que se esta controlando con un PORTA entonces al apagar el led....este se pone en tierra que es para el boton la accion de q se pulso por eso mi programa se queda pegado en la rutina del boton.........
la tarjeta de desarrollo es EL EXPLORER 16 DEVELOPMENT BOARD Y EL PIC 24FJ128GA010
ReyesA