TODOPIC
Microcontroladores PIC => Lenguaje C para microcontroladores PIC => Mensaje iniciado por: jdreyesa 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
-
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?
-
#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.......................
-
Y la variable Result solo puede tomar esos dos valores: 1150 o 1300?
-
no el en el caso cuando toma los valores de voltaje Result va de 0 a 1350
-
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:
/****************************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.
-
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
-
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?
-
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.
-
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?
-
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