/* EJEMPLO 4-7
Autor: Mikel Etxebarria
Orozko-Bizkaia, Septiembre 2010
LA CLAVE. Ejemplo de entretenimiento que emula un control de acceso.
Mediante el teclado el usuario pulsa la tecla D (<-) de apertura, e introduce una clave de
4 dígitos. Si es correcta se activa un led de salida conectado a la línea RA4 durante un segundo,
simulando así la apertura de una puerta. Se dan tres oportunidades para introducir la clave correcta.
En RA5 se conecta un led de salida que simula un piezo eléctrico que emite un beep cada vez
que se pulsa una tecla.
La tecla C (->) permite realizar el cambio de clave pidiendo una nueva y la correspondiente
confirmación.
La pantalla LCD irá presentando los oportunos mensajes.
En la memoria EEPROM de datos disponible en los dispositivos 16F88X quedará registrada, de
forma permanente, aunque modificable, la clave actual. */
#include <16f886.h>
/* Ajusta los valores de las palabras de configuración durante el ensamblado.Los bits no empleados
adquieren el valor por defecto.Estos y otros valores se pueden modificar según las necesidades */
#fuses NOLVP,PUT,NOWDT,EC_IO,NOFCMEN,NOBROWNOUT //Palabra 1 de configuración
#fuses NOWRT,BORV40 //Palabra 2 de configuración
/* Con estas directivas las funciones "input" y "output_bit" no reprograman el pin de la puerta cada vez que
son utilizadas. Si no se indica el modo fast_io se asume por defecto standard_io el cual reprograma el pin
siempre antes de ser utilizadas estas funciones.*/
#use fast_io (B)
#use delay(clock=4000000)
/*Esta directiva graba la clave por defecto (1234) en la 1ª posición de la EEPROM trás el ensamblado. */
#rom 0x2100={0x31,0x32,0x33,0x34}
#include <lcd4bitsPIC16.h> //Incluye rutinas de control de la pantalla LCD
#include <Teclado.h> //Incluir funciones de manejo del teclado
char tecla; //String con dígitos tecleados
char Clave[4]; //String con la clave de 4 dígitos
char Temporal[4]; //String con nº temporal
int intentos=3; //Variable para nº de intentos
/**************************************************************************************
Key_Off: Esta rutina genera un Beep y espera que la tecla recién pulsada se suelte.
Debe usarse justo después de llamar a la rutina Key_Scan */
void Key_Off()
{
int temp;
temp=tecla; //Salva la tecla recién pulsada
output_high(PIN_A5); //Activa señal acústica conectada a RA5
delay_ms(100); //Temporiza 0.1"
output_low(PIN_A5); //Desconecta señal acústica
while (key_Scan()!= 0x00); //Espera se deje de pulsar la tecla
tecla=tecla; //Repone la tecla pulsada
}
/********************************************************************************************
Control: Espera que se tecleen los cuatro dígitos de la clave, los almacena en digito_1 ..
digito_4 y visualiza **** en LCD. La tecla C (->) permite cancelar en cualquier momento */
control()
{
int c;
for(c=0;c<4;c++)
{
do
{Tecla=Key_Scan();}
while (Tecla== 0x00); //Espera que se pulse una tecla
lcd_putc('*'); //Visualiza el *
Key_Off(); //Genera Beep y espera se libere
if(tecla=='C')
return(TRUE); //Retorna TRUE si se pulsa C de cancelar
Temporal[c]=Tecla; //Almacena la tecla en el buffer
}
return(FALSE); //Retorna false si NO se pulsa C de cancelar
}
/********************************************************************************************
Okey: Comprueba si la clave introducida en el buffer Temporal coincide con la de la EEPROM. En caso
afirmativo se devuelve TRUE", de lo contrario FALSE. */
Okey()
{
int c;
for(c=0;c<4;c++)
{
if(Temporal[c]!=Clave[c])
return(FALSE);
}
return(TRUE);
}
/**************************************************************************
EE_Read: Lee el contenido actual de la clave almacenada en la EEPROM y lo
guarda en el buffer Clave */
void EE_Read()
{
int c;
for(c=0;c<4;c++)
Clave[c]=Read_eeprom(c);
}
/**************************************************************************
EE_Write: graba el contenido actual de la clave almacenada en el buffer
Clave, sobre la EEPROM y queda como nueva clave */
void EE_Write()
{
int c;
for(c=0;c<4;c++)
write_eeprom(c,Clave[c]);
}
/************************************************************************************
Función para la apertura o acceso. Se permiten tres intentos */
Apertura()
{
int c;
for(c=0;c<Intentos;c++)
{
lcd_enviar(LCD_COMANDO,LCD_CLEAR); //Borra pantalla
lcd_putc('(');
lcd_enviar(LCD_DATO,0x7E); //Símbolo flecha dch.
printf(lcd_putc,") Cancelar"); //Visualiza "(->) Cancelar"
lcd_gotoxy(1,2); //Posiciona el cursor
printf(lcd_putc,"Clave ? "); //Visualiza "Clave ?"
if(control()==TRUE) //Si hay cancelación retorna
return(TRUE);
if(Okey()==TRUE) //Si es clave correcta ..
{
//Clave correcta
lcd_enviar(LCD_COMANDO,LCD_CLEAR); //Borra pantalla
printf(lcd_putc,"Puede pasar"); //Visualiza "Puede pasar"
output_high(PIN_A4); //Activar salida de apertura
output_high(PIN_A5); //Emite un tono de apertura
delay_ms(2000); //Temporiza 2 "
output_low(PIN_A4); //Desactiva salida de apertura
output_low(PIN_A5); //Tono en OFF
return(TRUE);
}
}
//Clave incorrecta
lcd_enviar(LCD_COMANDO,LCD_CLEAR); //Borra pantalla
printf(lcd_putc,"ACCESO DENEGADO"); //Visualiza "ACCESO DENEGADO"
delay_ms(2000); //Temporiza 2 seg.
}
/**************************************************************************************
Función que permite realizar el cambio de la clave actual */
Cambio()
{
int c;
lcd_enviar(LCD_COMANDO,LCD_CLEAR); //Borra pantalla
lcd_putc('(');
lcd_enviar(LCD_DATO,0x7E); //Símbolo flecha dch.
printf(lcd_putc,") Cancelar"); //Visualiza "(->) Cancelar"
lcd_gotoxy(1,2); //Posiciona el cursor
printf(lcd_putc,"Clave ? "); //Visualiza "Clave ?"
//Primero se pide la clave actual
if(control()==TRUE) //Si hay cancelación retorna
return(TRUE);
if(Okey()==TRUE) //Si es clave correcta ..
//Si la clave es correcta se pide la nueva clave
{
lcd_enviar(LCD_COMANDO,LCD_CLEAR); //Borra pantalla
lcd_putc('(');
lcd_enviar(LCD_DATO,0x7E); //Símbolo flecha dch.
printf(lcd_putc,") Cancelar"); //Visualiza "(->) Cancelar"
lcd_gotoxy(1,2); //Posiciona el cursor
printf(lcd_putc,"Nueva Clave "); //Visualiza "Nueva Clave "
if(control()==TRUE) //Si hay cancelación retorna
return(TRUE);
for(c=0;c<4;c++)
Clave[c]=Temporal[c]; //Se salva la nueva clave
//Se pide teclear la nueva clave para confirmar
lcd_enviar(LCD_COMANDO,LCD_CLEAR); //Borra pantalla
lcd_putc('(');
lcd_enviar(LCD_DATO,0x7E); //Símbolo flecha dch.
printf(lcd_putc,") Cancelar"); //Visualiza "(->) Cancelar"
lcd_gotoxy(1,2); //Posiciona el cursor
printf(lcd_putc,"Confirmar "); //Visualiza "Confirmar "
if(control()==TRUE) //Si hay cancelación ..
{ee_read(); //Se repone la clave original
return(TRUE);
}
if(Okey()==TRUE) //Si se confirma la nueva clave ..
ee_write(); //Se guarda en la eeprom
}
}
/* Programa principal */
main()
{
SETUP_ADC_PORTS(NO_ANALOGS); //Puertas A y B Digitales
output_a(0x00); //Borra salidas
set_tris_a(0x00); //RA0-RA7 salidas
set_tris_b(0x00); //RB0-RB7 salidas
delay_ms(50);
lcd_init(); //Secuencia de inicio del LCD
ee_read(); //Recupera la clave actual de la EEPROM
while(1)
{
//Visualiza Mensajes iniciales
Loop:
lcd_enviar(LCD_COMANDO,LCD_CLEAR); //Borra pantalla
lcd_putc('(');
lcd_enviar(LCD_DATO,0x7F); //Símbolo flecha dch.
printf(lcd_putc,") Apertura"); //Visualiza "(<-) Apertura"
lcd_gotoxy(1,2); //Posiciona el cursor
lcd_putc('(');
lcd_enviar(LCD_DATO,0x7E); //Símbolo flecha izda.
printf(lcd_putc,") Cambio Clave"); //Visualiza "(-> Cambio Clave)"
//Espera que se pulse la de apertura <- (D) o la de cambio de clave -> (C)
No_Tecla:
do
{Tecla=Key_Scan();}
while (Tecla== 0x00); //Espera que se pulse una tecla
Key_off(); //genera beep y espera se libere
if(Tecla=='D')
{Apertura(); //Si se pulsa <- (D), función de apertura
goto Loop;
}
if(Tecla=='C')
{Cambio(); //Si se pulsa -> (C), función de cambio de clave
goto Loop;
}
goto No_Tecla; //Pulsación incorrecta
}
}