#INCLUDE <12F1840.h>
// Declaración para trabajar con punteros a constantes.
#device PASS_STRINGS=IN_RAM
#FUSES INTRC_IO // Oscilador interno.
#FUSES WDT // Utilizamos el perro guardián.
#FUSES PUT // Habilita el power uP timer.
#FUSES NOMCLR // Utilizamos el pin MCLR como E/S.
#FUSES NOPROTECT // No proteje el código del microcontrolador -- DE MOMENTO.
#FUSES NOCPD // No proteje el área de la memoria EEPROM.
#FUSES NOBROWNOUT // No hay reset por bajo voltaje.
#FUSES NOCLKOUT // Utiliza los pines de clk como E/S.
#FUSES NOIESO
#FUSES FCMEN // Monitor de falla de clock.
#FUSES NOWRT // No hay protección de registros especiales.
#FUSES PLL_SW // Utiliza el PLL para generar el clock del micro = 32Mhz.
#FUSES STVREN // Si la pila se llena, generará un reset.
#FUSES NODEBUG // No utilizaremos código de debug.
#FUSES NOLVP // No utilizaremos programación a bajo voltaje.
#USE delay (Clock = 16000000,RESTART_WDT) // Reloj = 16Mhz.
// Se define etiquetas de pines de pines //
#use fast_io(A) // Asignación rápida de los pines del puerto A
#locate Puerto_A = 0xf92 // Defino el puerto A con una etiqueta.
#bit Pgm_Cod = Puerto_A.4 // A4 como entrada del pulsador para programar los códigos
#bit Led_Cod_OK = Puerto_A.0 // A0 como salida de indicación de código grabado correctamente
#bit Led_Cod_Error = Puerto_A.1 // A1 como salida de indicación de código erroneo
#bit Config = Puerto_A.5 // A5 como entrada del pulsador de configuración
#bit Dato_entrada = Puerto_A.2 // A2 como entrada de datos del control remoto
// Defino un registro de estado con sus bits respectivos
int Estado = 0; // Registro de Estado ==> BITS: 7 6 5 4 3 2 1 0
// | | | | | | | |_ Bien : Se recibio un código correcto
// | | | | | | |___ Mal : Se recibio un código incorrecto
// | | | | | |_____ Comienzo : Determina cuando comienza un código
// | | | | |_______ Fin : Determina cuando termina un código
// | | | |_________ Estado_inicial : Se pone el estado en el que se comienza a analizar el código
// | | |___________ Escaneo_tiempo : Indica que se encuentra en la parte de analisis de tiempos
// | |_____________ Nuevo_Codigo : Hay disponible un nuevo codigo
// |_______________ Abrir_Cerrar : Al abrir el portón se pone en 1, cuando se cierra se pone en 0
#bit Bien = Estado.0 // Si recibe un codigo correcto, Bien = 1
#bit Mal = Estado.1 // Si recibe un codigo incorrecto, Mal = 1
#bit Comienzo = Estado.2 // Si comienza un código, Comienzo = 1
#bit Fin = Estado.3 // Si termina un código, Fin = 1
#bit Estado_inicial = Estado.4 // Se pone el valor con el que se empieza a leer el código para ver el momento de cambio
#bit Escaneo_tiempo = Estado.5 // Si se está evaluando los tiempo del código, Escaneo_tiempo = 1
#bit Nuevo_Codigo = Estado.6 // Si hay un nuevo codigo medido, Nuevo_Codigo = 1
#bit Abrir_Cerrar = Estado.7 // Si se esta abriendo el portón, Abrir_Cerrar = 1
// Definición de variables
long Tiempo,Tiempo_Max,Tiempo_Min,Reset;
int i,Contador,Contador_Unos,Codigo[3],Salto,aux,Contador_Codigo,Auxiliar[3];
// Declaro las funciones utilizadas
void Inicializacion_dispositivo (); // Rutina de inicialicación del dispositivo
void Demora_ms(long tiempo_ms); // Rutina para hacer demoras en milisegundos
void Tiempo_Bajo (); // Rutina para analizar el tiempo de los pulsos en bajo
void Tiempo_Alto (); // Rutina para analizar el tiempo de los pulsos en bajo
void Decodificacion_cero (); // Rutina donde registra un cero de la decodificación
void Decodificacion_uno (); // Rutina donde registra un uno de la decodificación
void Decodificacion_Codigo (); // Rutina que realiza el proceso de decodificación del código
//!void Borrar_Eeprom (); // Rutina que borra el contenido de la memoria eeprom interna
void Registro_codigos (); // Rutina para registrar los tiempos del código
void Guardar_Codigo_Eeprom (); // Rutina para guardar el código en la eeprom interna
void Leer_codigo (); // Rutina para leer los códigos de entrada
void Configurar (); // Rutina que permite realizar la configuracion del funcionamiento
//!void Funcionamiento (); // Rutina de funcionamiento acorde a como fue configurado
// Interrupción del timer 0
#int_timer0
void Reset_temp (void)
{
Reset++;
}
// Programa principal
void main()
{
Inicializacion_dispositivo(); // Inicializo el dispositivo
Led_Cod_Error = 1; // Prendo el led de error al iniciar
Demora_ms (500); // Espero 500 mseg
Led_Cod_Error = 0; // Apago el led de error
Demora_ms (500); // Espero 500 mseg
Salto = read_eeprom (125); // Cargo el valor del ultimo salto realizado en la memoria eeprom
for (;;) // Buecle infinito
{
if (Pgm_Cod == true) // Si se presiona el pulsador entro a la rutina Registro_codigos
Registro_codigos (); // Llamo la rutina Registro_codigo
if (Config == true) // Si se presiona el pulsador entro a la rutina Configurar
Configurar (); // Llamo la rutina Configurar
Leer_codigo (); // Llamo la rutina Leer_codigo
}
}
void Demora_ms(long tiempo_ms) // Rutina para generar demoras en ms sin agregar mas codigo
{
while (--tiempo_ms) // Bucle de tiempo en mseg
delay_ms(1); // Retardo de 1 mseg
}
void Inicializacion_dispositivo(void)
{
setup_oscillator(OSC_16MHZ); // Configura el oscilador interno.
setup_adc_ports(NO_ANALOGS|VSS_VDD); // Todos los pines son E/S digital.
setup_adc(ADC_OFF); // Apaga el conversor A/D.
setup_dac(DAC_OFF); // Apaga el DAC.
setup_spi(SPI_SS_DISABLED); // Desactiva el puerto SPI.
setup_ccp1(CCP_OFF); // Módulo de captura desactivado.
setup_comparator(NC_NC); // Módulo de comparación desactivado.
set_tris_a (0b111100);
output_a (0);
setup_timer_1 (T1_INTERNAL | T1_DIV_BY_4); // Seteo el timer 1 para funcionar a 1 useg
setup_timer_0 (T0_DIV_256);
enable_interrupts (GLOBAL);
}
void Registro_codigos (void)
{
while (Pgm_Cod == true); // Se queda esperando hasta soltar el pulsador
Reset= 0;
clear_interrupt (INT_TIMER0);
enable_interrupts (INT_TIMER0);
while ((Bien == 0)&(Reset<611))
{
Contador_Codigo = 0;
Mal = 0;
Nuevo_Codigo = 0;
for (i=0;i<3;i++) // Borro el contenido de los 3 bytes de Auxiliar
Auxiliar[i] = 0;
do
{
for (i=0;i<3;i++) // Borro el contenido de los 3 bytes de Codigo
Codigo[i] = 0;
Contador = 25; // Para un bucle que analiza 25 ceros del código
Contador_Unos = 0; // Contador de unos del código para determinar el tipo de codificación
Tiempo_Max = 0; // Seteo el valor de tiempo máximo en el mínimo valor
Tiempo_Min = 0xFFFF; // Seteo el valor de tiempo mínimo en el máximo valor
while (Contador!=0) // Sale del bucle cuando Contador = 0
{
Tiempo_Bajo (); // Llamo a la rutina Tiempo_Bajo
if (Tiempo_Max<Tiempo) // Pregunto si el valor de Tiempo es mayor que Tiempo_Max
Tiempo_Max = Tiempo; // Reemplazo el valor de Tiempo_Max por Tiempo si Tiempo_Max < Tiempo
Contador--; // Decremento el valor del Contador
}
Contador = 25; // Para un bucle que analiza 25 ceros del código
while (((Tiempo_Max-(Tiempo_Max/16))>Tiempo)&(Contador!=0)) // Me quedo hasta que encuentro el espacio entre tramas o hata que contador sea cero
{
Tiempo_Bajo (); // Llamo a la rutina Tiempo_Bajo
Contador--;
}
Decodificacion_Codigo (); // Llamo a la rutina Decodificacion_Codigo
if (Nuevo_Codigo == 0)
{
for (i=0;i<3;i++)
Auxiliar[i]=Codigo[i];
if ((Codigo[0]==0)&(Codigo[1]==0)&(Codigo[2]==0))
Mal = 1;
}
if ((Mal == 0)&(Nuevo_Codigo == 1))
{
if (Auxiliar[0] == Codigo[0])
{
if (Auxiliar[1] == Codigo[1])
{
if (Auxiliar[2] == Codigo[2])
Bien = 1;
else
{
Mal = 1;
Bien = 0;
}
}
else
{
Mal = 1;
Bien = 0;
}
}
else
{
Mal = 1;
Bien = 0;
}
}
Contador_Codigo++;
Nuevo_Codigo = 1;
}while ((Mal == 0)&(Contador_Codigo < 4));
}
disable_interrupts (INT_TIMER0);
if (Bien == 1)
{
Guardar_Codigo_Eeprom(); // Llamo a la rutnia Guardar_Codigo_Eeprom
Led_Cod_OK = 1; // Prendo el led de OK para indicar que el código se copio correctamente
Demora_ms (1000); // Espero 1 seg
Led_Cod_OK = 0; // Apago el led de OK
}
else
{
Led_Cod_Error = 1; // Prendo el led de OK para indicar que el código se copio correctamente
Demora_ms (1000); // Espero 1 seg
Led_Cod_Error = 0; // Apago el led de OK
}
Bien = 0;
Mal = 0;
}
void Tiempo_Bajo (void)
{
while(Dato_entrada == 1); // Está en alto y espera que baje
set_timer1(0); // Pone a cero el Timer 1
while(Dato_entrada == 0); // Se mantiene en el pulso bajo hasta que cambie
Tiempo = get_timer1(); // Leo el tiempo del pulso bajo
}
void Tiempo_Alto (void)
{
while(Dato_entrada == 0); // Está en alto y espera que baje
set_timer1(0); // Pone a cero el Timer 1
while(Dato_entrada == 1); // Se mantiene en el pulso bajo hasta que cambie
Tiempo = get_timer1(); // Leo el tiempo del pulso bajo
}
void Decodificacion_cero (void)
{
shift_left(Codigo,3,0); // Roto hacia la izquierda un 0
}
void Decodificacion_uno (void)
{
shift_left(Codigo,3,1); // Roto hacia la izquierda un 1
}
void Guardar_Codigo_Eeprom (void)
{
if (Salto>120) // Verifico cuando Salto llega al máximo permitido
Salto = 0; // Lo reseteo a cero
for (i=0;i<3;i++) // Guardo el Codigo en la eeprom de acuerdo al valor de Salto
{
aux = Codigo[i];
write_eeprom(i+Salto,aux);
}
if (make16(read_eeprom(126),read_eeprom(127))>Tiempo_Max) // Veo si el valor de Tiempo_Max guardado es mayor que el último tiempo máximo guardo y lo reemplazo
{
write_eeprom(126,make8(Tiempo_Max,1)); // Guardo parte alta de Tiempo_Max en la posición 126
write_eeprom(127,make8(Tiempo_Max,0)); // Guardo parte baja de Tiempo_Max en la posición 127
}
Salto+=3; // Si Salto no llego al máximo lo incremento en 3
write_eeprom(125,Salto); // Guardo el valor de Salto en la eeprom en la posición 125
}
void Leer_codigo (void)
{
for (i=0;i<3;i++) // Borro el contenido de los 3 bytes de Codigo
Codigo[i] = 0;
Contador = 25; // Para un bucle que analiza 25 ceros del código
Contador_Unos = 0; // Contador de unos del código para determinar el tipo de codificación
Tiempo_Min = 0xFFFF; // Seteo el valor de tiempo mínimo en el máximo valor
Tiempo_Max = make16(read_eeprom(126),read_eeprom(127)); // Leo el valor de Tiempo_Max
Tiempo_Bajo (); // Llamo a la rutina Tiempo_Bajo
if ((Tiempo_Max-(Tiempo_Max/16))<Tiempo) // Decodifico si el tiempo leido es mayor que Tiempo_Max-(Tiempo_Max/16)
{
Decodificacion_Codigo (); // Llamo a la rutina Decodificacion_Codigo
if (Mal == 0)
{
for (i=0;i<120;i+=3)
{
if (Bien == 0)
{
if (read_eeprom(1+i) == Codigo[1])
{
if (read_eeprom(2+i) == Codigo[2])
{
if (read_eeprom(0+i) == Codigo[0])
{
Bien = 1;
Mal = 0;
}
else
Mal = 1;
}
else
Mal = 1;
}
else
Mal = 1;
}
}
}
if (Bien == 1)
{
output_toggle(PIN_A0);
Demora_ms(500);
}
Bien = 0;
Mal = 0;
}
}
void Configurar (void)
{
while (Config == true); // Me quedo hasta soltar el pulsador Config
Demora_ms(20); // Espero 20 mseg
for (i=0;i<128;i++) // Bucle para borrar la eeprom
{
write_eeprom(i,0xFF); // Escribo FF en toda la eeprom
}
Led_Cod_OK = 1; // Prendo el led OK
Led_Cod_Error = 1; // Prendo el led error
Demora_ms (333); // Espero 333 mseg
Led_Cod_OK = 0; // Apago el led OK
Led_Cod_Error = 0; // Apago el led error
Demora_ms (333); // Espero 333 mseg
Led_Cod_OK = 1; // Prendo el led OK
Led_Cod_Error = 1; // Prendo el led error
Demora_ms (333); // Espero 333 mseg
Led_Cod_OK = 0; // Apago el led OK
Led_Cod_Error = 0; // Apago el led error
Demora_ms (333); // Espero 333 mseg
Led_Cod_OK = 1; // Prendo el led OK
Led_Cod_Error = 1; // Prendo el led error
Demora_ms (333); // Espero 333 mseg
Led_Cod_OK = 0; // Apago el led OK
Led_Cod_Error = 0; // Apago el led error
}
void Decodificacion_Codigo (void)
{
do
{
Contador_Unos++; // Incremento el contador de unos
Tiempo_Bajo(); // Llamo a la rutina Tiempo_Bajo
if (Tiempo_Min>Tiempo) // Pregunto si el valor de Tiempo es menor que Tiempo_Min
Tiempo_Min = Tiempo; // Reemplazo el valor de Tiempo_Min por Tiempo si Tiempo_Min > Tiempo
}while(((Tiempo_Max-(Tiempo_Max/16))>Tiempo)&(Contador_Unos<26)); // Repito el bucle hasta encontrar el espacio entre tramas o hasta exceder el maximo de Contador_Unos
if (Contador_Unos == 25) // Si el contador de unos es igual a 25 entonces el código tiene sincronismo
Contador_Unos--; // Decremento en uno el contador de unos
if (Contador_Unos == 13) // Si el contador de unos es igual a 13 realizo la rutina de decodificación HT12/MM53200/UM3750/UM86409
{
Contador_Unos--; // Decremento el contador de unos
do
{
Tiempo_Bajo(); // LLamo a la rutina Tiempo_Bajo
if ((Tiempo_Min+(Tiempo_Min/2))>Tiempo) // Prgunto si el tiempo alto es menor que Tiempo_Min+(Tiempo_Min/2) para decodificar como cero
Decodificacion_cero(); // Llamo a la rutina Decodificacion_cero
else // Si no decodifico como uno
Decodificacion_uno(); // Llamo a la rutina Decodificacion_uno
Contador_Unos--; // Decremento el contador de unos
}while(Contador_Unos != 0); // Termino el bucle si el contador de unos es 0
}
else // Sino realizo la rutina de decodificación HT6026/PT2262/EV1527
{
if ((Contador_Unos==24)|(Contador_Unos==18))
{
do
{
Tiempo_Alto(); // LLamo a la rutina Tiempo_Alto
if ((Tiempo_Min+(Tiempo_Min/2))>Tiempo) // Prgunto si el tiempo alto es menor que Tiempo_Min+(Tiempo_Min/2) para decodificar como cero
Decodificacion_cero(); // Llamo a la rutina Decodificacion_cero
else // Si no decodifico como uno
Decodificacion_uno(); // Llamo a la rutina Decodificacion_uno
Contador_Unos--; // Decremento el contador de unos
}while(Contador_Unos != 0); // Termino el bucle si el contador de unos es 0
}
else
Mal = 1;
}
}