#include <htc.h>
__CONFIG (LVPDIS & WDTDIS);
#include "Def16f87xa.h" // algunas definiciones propias para esta familia de PICs
#define PIC_CLK 20000000 // defino la velocidad de trabajo
#include "delayhd.h" // rutinas de retardo
#define set_tris_b(x) TRISB=x
#define output_b(x) PORTB=x
#define set_tris_a(x) TRISA=x
#define output_a(x) PORTA=x
/************************************************************************************************
Todos esos include y define son para poder trabajar con el pic, estoy usando el compilador HiTech
pero tratando de dejar el codigo lo mas parecido posible a CCS
Hay que adaptar la cabecera y parte del programa para que trabaje correctamente con CCS
Tambien la linea __CONFIG (xxxx) hay que cambiarla por el tipo soportado por CCS
**************************************************************************************************/
unsigned char flag_teclado = 0; // variable para saber si se presiono una tecla
/*****************************************
Rutina de delay de aproximadamente 10mS
para usar como anti-rebote
******************************************/
void AntiRebote (void)
{
unsigned char tiempo;
for (tiempo = 40; tiempo > 0; tiempo--)
{
DelayUs (250);
}
}
/****************************************************************
Esta es la rutina de atencion de interrupcion que permite Hitech
hay que cambiarla y adaptarla al formato de CCS
******************************************************************/
void interrupt isr (void)
{
unsigned char temporal;
temporal = PORTB & 0xF0;
if (temporal != 0) flag_teclado = 1; // si hay tecla pulsada activo el flag
temporal = PORTB; // leo el puerto B para que ya no exista condicion de cambio
RBIF = 0; // borro el flag de cambio de RB. (Adaptar a CCS)
/*
No deshabilito ni vuelvo a habilitar las interrupciones por que
de ello ya se encarga el compilador. Adaptar a CCS si es necesario
*/
}
/************************************************
Esta es la rutina que devuelve la tecla pulsada
Los valores devueltos van de 1 a 16
*************************************************/
unsigned char captura(void)
{
unsigned char lectura;
output_b (0b00000001); // activo la primer fila
lectura = PORTB & 0xF0; // leo el puerto B y hago una and porque solo me interesa el nibble alto
output_b (0x0F); // activo todas las salidas
if (lectura == 0b00010000) return 1;
if (lectura == 0b00100000) return 2;
if (lectura == 0b01000000) return 3;
if (lectura == 0b10000000) return 4;
output_b (0b00000010); // activo la segunda fila
lectura = PORTB & 0xF0; // leo el puerto B y hago una and porque solo me interesa el nibble alto
output_b (0x0F); // activo todas las salidas
if (lectura == 0b00010000) return 5;
if (lectura == 0b00100000) return 6;
if (lectura == 0b01000000) return 7;
if (lectura == 0b10000000) return 8;
output_b (0b00000100); // activo la tercer fila
lectura = PORTB & 0xF0; // leo el puerto B y hago una and porque solo me interesa el nibble alto
output_b (0x0F); // activo todas las salidas
if (lectura == 0b00010000) return 9;
if (lectura == 0b00100000) return 10;
if (lectura == 0b01000000) return 11;
if (lectura == 0b10000000) return 12;
output_b (0b00001000); // activo la cuarta fila
lectura = PORTB & 0xF0; // leo el puerto B y hago una and porque solo me interesa el nibble alto
output_b (0x0F); // activo todas las salidas
if (lectura == 0b00010000) return 13;
if (lectura == 0b00100000) return 14;
if (lectura == 0b01000000) return 15;
if (lectura == 0b10000000) return 16;
return 0;
}
void main (void)
{
unsigned char lectura_temporal;
unsigned char tecla_pulsada;
setup_adc (ADC_OFF);
setup_comparator (NC_NC_NC_NC);
set_tris_a (0); // Puerto A como salida
output_a (0); // todo en 0
set_tris_b (0b11110000); // Nibble alto como entrada, nibble bajo como salida
output_b (0x0F); // Todas las salidas en 1
RBIF = 0; // borro el flag que indica cambio en RB4..RB7
/*
Creo que en CCS se usa clear_interrupt (INT_RB)
*/
enable_interrupt (INT_RB); // habilito interrupcion por cambio
enable_interrupt (GLOBAL); // habilito todas las interrupciones
while (1)
{
if (flag_teclado == 1) // si se presiono alguna tecla...
{
disable_interrupt (INT_RB);
AntiRebote(); // Aca se podria usar alguna funcion de delay de CCS
if (PORTB != 0) // si sigue presionada alguna tecla....
{
tecla_pulsada = captura(); // guardo en una variable la tecla pulsada
output_a (tecla_pulsada); // la muestro en formato binario por el puerto A
}
flag_teclado = 0; // borro para avisar que ya procese la tecla
lectura_temporal = PORTB; // leo el puerto B para que ya no exista condicion de cambio
RBIF = 0; // borro el flag de cambio;
enable_interrupt (INT_RB);
}
}
}