Hola!, gracias a la ayuda del compañero
jgpeiro06 he podido simplificar éste código y hacerlo un poquito más elegante, basicamente es un filtro antirebote a través de una interrupción de 20ms del timer1 del pic18f4550, esto es útil cuando tenemos un proceso en el que no podemos quedarnos a esperar 20ms, 40ms ó lo que sea porque hay otras cosas que requieren nuestra atención también, entonces le dejamos el trabajo al timer a que nos recuerde que pasaron 20ms y que la señal es estable y confiable.
Resumiendo, el programa funciona así: Si hay un cambio de estado en el pin de entrada, se manda a contar 20ms a través de la interrupción del timer1, al pasar este lapso de tiempo se verifica que ese cambio se mantuvo, entonces regresa el valor que tiene ese pin, porque dicha señal es considerada estable.
A continuación el código:
#include <18F4550.h>
#fuses HSPLL,NOWDT,NOPROTECT,NOLVP,NODEBUG,USBDIV,PLL5,CPUDIV1,VREGEN,NOPBADEN
#use delay(clock=48000000)
#byte PORTA = 0xF80// Son las direcciones de memoria de los puertos en este PIC
#byte PORTB = 0xF81
#byte PORTC = 0xF82
#byte PORTD = 0xF83
#byte PORTE = 0xF84
#define entrada1 PIN_A0
#define entrada2 PIN_A1
#define salida1 PIN_B0
#define salida2 PIN_B1
#use fast_io(A)
#use fast_io(B)
#use fast_io(C)
#use fast_io(D)
#use fast_io(E)
typedef struct{
long pin;// Es el pin de entrada del LS
int8 contando;// si es 0 indica que no está contando
int8 pasaron_20ms;// Si es 1 significa que pasaron 20ms
int8 estado_actual;// Es el estado actual del pin, sea 0 ó 1
int8 estado_anterior;// Es el estado anterior del pin
} mi_LS;// mi Limit Switch
const long delay_20ms=35535;
mi_LS ls_art_1={entrada1 0 0 0 0};
mi_LS ls_art_2={entrada2 0 0 0 0};
// Prototipos de funciones
short estado(mi_LS *);
// Verifica el estado de un pin con un antirebote de 20ms
// manejado con la interrupción del timer1
#INT_TIMER1
void timer1_isr()
{
if (ls_art_1.contando==1){// mando a contar el ls de la art1??
ls_art_1.pasaron_20ms=1;
}
if (ls_art_2.contando==1){// mando a contar el ls de la art2??
ls_art_2.pasaron_20ms=1;
}
disable_interrupts(INT_TIMER1);// Deshabilitamos
}
void main(void) {
set_tris_a(0b00000011);// A0 y A1 como entradas
set_tris_b(0);// Todo el puerto B como salida
enable_interrupts(GLOBAL); // Deshabilitamos todas las inteerupciones
setup_timer_1(T1_INTERNAL | T1_DIV_BY_8);
// 8*(1/12E6)=666,6667ns= 1 Tick, 20ms/1Tick=30.000Ticks
// 65535-30000=35535, es el valor con el que tengo que cargar
// al timer1 para que ocurra una interrupción a los 20ms
// set_timer1(delay_20ms);// delay_20ms=35535
output_low(salida1);
output_low(salida2);
while (TRUE){
if (estado(&ls_art_1)) output_high(salida1);
else output_low(salida1);
if (estado(&ls_art_2)) output_high(salida2);
else output_low(salida2);
}
}
short estado(mi_LS * ls){
// Verifica el estado de un pin con antirebote mediante la interrupción
// del timer 1, basicamente detecta si hubo un cambio de estado en el pulsador
// si ese cambio de estado se mantiene por 20ms entonces la señal se considera
// estable y por consiguiente la función regresa su valor.
if (ls->contando){// Mandé a contar??
// Efectivamente hemos mandado a contar 20ms
if (ls->pasaron_20ms){// Pasaron 20ms??
// han pasado 20ms
ls->contando=0;// Apago éste indicador porque ya pasaron los 20ms
// y no estamos contando más
ls->estado_actual=input(ls->pin);// Leemos el valor actual del pin
// Verificamos si el cambio se mantiene
if ((ls->estado_actual)!=(ls->estado_anterior)){
// Efectivamente el cambio se mantuvo
ls->estado_anterior=ls->estado_actual;
// Actualizamos el valor del estado anterior del pin, porque la
// señal es estable
}
}
}
else{// No he mandado a contar aún
ls->estado_actual=input(ls->pin);// Leemos el valor actual del pin
// verificamos si hubo un cambio de estado
if ((ls->estado_actual)!=(ls->estado_anterior)){
// Entonces hubo un cambio de estado en el pin
ls->contando=1;// indico que mande a contar
ls->pasaron_20ms=0;// Indico que no han pasado 20ms
set_timer1(delay_20ms);
clear_interrupt(INT_TIMER1);// Para prevenir una interrupción
// indeseada al iniciar el servicio
// de interrupción
enable_interrupts(INT_TIMER1);// Habilito interrupción del timer1
}
}
if (ls->estado_anterior) return(1);
else return(0);
}
Pueden utilizar éste diseño en el
proteus para verificar su funcionamiento.
Saludos.