¡¡Hola, señores!!
No sé si acierto posteando esto aqui, si no fuese así, ruego a algún moderador que lo cambie...
Este es mi segundo proyecto, y ya me está trayendo quebraderos de cabeza... Posteo aquí mi problema a ver si algún alma caritativa puede echarme un cable (nunca mejor dicho).
Lo que siempre he pretendido es empezar de 0, y consultar la menor cantidad de código y soluciones "ya hechas" en Internet, porque creo que es la mejor forma de aprender.
Buscando proyectos para empezar en este mundillo, encontré el teclado matricial. Leí el desarrollo y la metodología básicos, y me puse a diseñar.
Os pego código y esquema, y luego os cuento lo que me pasa:
// Programa para el manejo de un teclado matricial
// Librerías que utilizo
#include <16F84A.h>
// Fusibles
#fuses HS,NOWDT,NOPUT,NOPROTECT
// Frecuencia del cristal
#use delay(clock=8000000)
#use fast_io(A)
#use fast_io(B)
/// asignamos a variable port_b el espacio memoria 0x06 que es la dir de port_b
#byte PuertoA=0x05
#byte PuertoB=0x06
int Fila; //Definimos los valores globales de fila y columna
int Columna;
int Rebote;
void Reseteo()
{
Fila=0; //Inicializamos los valores de fila y columna a 0
Columna=0;
Rebote=0; //No hay rebotes de momento
}
int Decodifica(int VarFil, int VarCol)
{
int VarTemp; //Definimos una variable temporal donde guardar el resultado
switch(VarFil)
{
case 4:
switch(VarCol)
{
case 1: VarTemp=0b1111; break;
case 2: VarTemp=0b0000; break;
case 3: VarTemp=0b1110; break;
case 4: VarTemp=0b1101; break;
}
break;
case 3:
switch(VarCol)
{
case 1: VarTemp=0b0001; break;
case 2: VarTemp=0b0010; break;
case 3: VarTemp=0b0011; break;
case 4: VarTemp=0b1100; break;
}
break;
case 2:
switch(VarCol)
{
case 1: VarTemp=0b0100; break;
case 2: VarTemp=0b0101; break;
case 3: VarTemp=0b0110; break;
case 4: VarTemp=0b1011; break;
}
break;
case 1:
switch(VarCol)
{
case 1: VarTemp=0b0111; break;
case 2: VarTemp=0b1000; break;
case 3: VarTemp=0b1001; break;
case 4: VarTemp=0b1010; break;
}
break;
}
return VarTemp;
}
void main() // Rutina principal
{
set_tris_a(0b00000); //El puerto A son todo salidas
set_tris_b(0b11110000); //El puerto B: pin 0-1-2-3 salidas 4-5-6-7 entradas
ext_int_edge(0,H_TO_L); //Establecemos el flanco de las interrupciones
enable_interrupts(INT_RB); //Habilitamos las interrupciones
enable_interrupts(GLOBAL);
PuertoB=0b00000000;
PuertoA=0b00000;
Reseteo();
while(true)
{
if ((Fila!=0) && (Columna!=0))
{
PuertoA=Decodifica(Fila, Columna);
delay_ms(1000);
Fila=0;
Columna=0;
PuertoA=0;
Rebote=0;
}
}
}
#int_rb //Vamos a vigilar la interrupción correspondiente al cambio de estado de RB4-RB7
void manejador_rb()
{
//Empezamos el barrido
if (Rebote==0)
{
//Rebote=1; //Este lo tengo comentado para no tratar los rebotes de momento
output_b(0b0001); //Encendemos el pin 0 (correspondiente a columna 1)
//delay_ms(10);
if (!input(PIN_B4) || !input(PIN_B5) || !input (PIN_B6) || !input (PIN_B7)) //Si hemos activado una fila...
{
Columna=1; //Sabemos que la columna es 1
if (!input(PIN_B4)) Fila=1; //Y la fila... depende del pin activado
if (!input(PIN_B5)) Fila=2;
if (!input(PIN_B6)) Fila=3;
if (!input(PIN_B7)) Fila=4;
}
output_b(0b0010); //Encendemos el pin 1 (correspondiente a columna 2)
//delay_ms(10);
if (!input(PIN_B4) || !input(PIN_B5) || !input (PIN_B6) || !input (PIN_B7)) //Si hemos activado una fila...
{
Columna=2; //Sabemos que la columna es 2
if (!input(PIN_B4)) Fila=1; //Y la fila... depende del pin activado
if (!input(PIN_B5)) Fila=2;
if (!input(PIN_B6)) Fila=3;
if (!input(PIN_B7)) Fila=4;
}
output_b(0b0100); //Encendemos el pin 2 (correspondiente a columna 3)
//delay_ms(10);
if (!input(PIN_B4) || !input(PIN_B5) || !input (PIN_B6) || !input (PIN_B7)) //Si hemos activado una fila...
{
Columna=3; //Sabemos que la columna es 3
if (!input(PIN_B4)) Fila=1; //Y la fila... depende del pin activado
if (!input(PIN_B5)) Fila=2;
if (!input(PIN_B6)) Fila=3;
if (!input(PIN_B7)) Fila=4;
}
output_b(0b1000); //Encendemos el pin 3 (correspondiente a columna 4)
//delay_ms(10);
if (!input(PIN_B4) || !input(PIN_B5) || !input (PIN_B6) || !input (PIN_B7)) //Si hemos activado una fila...
{
Columna=4; //Sabemos que la columna es 4
if (!input(PIN_B4)) Fila=1; //Y la fila... depende del pin activado
if (!input(PIN_B5)) Fila=2;
if (!input(PIN_B6)) Fila=3;
if (!input(PIN_B7)) Fila=4;
}
PuertoB=0b00000000;
}
}
El esquema:
¿Mi problema?
Cuando desactivo la detección de interrupciones en el código fuente, la lógica del circuito funciona perfectamente: cuando acciono un pulsador,el pin correspondiente del rango RB4 a RB7 pasa de nivel alto se pone a nivel bajo (pasa de rojo a azul). Todo perfecto. Pero cuando activo las interrupciones... me encuentro con que, al comenzar el barrido que se realiza en el tratamiento de la interrupción, se pone en estado lógico desconocido (los pines RB0 a RB3 se ponen en gris, y el pin correspondiente en el rango RB4 a RB7 también se pone en gris). Es posible que en el código que acabo de poner esté tratando de forma incorrecta el barrido (que deba tratarlo partiendo de los pines RB0 a RB3 con nivel alto, e ir desactivandolos uno a uno), pero llevo varios días dándole vueltas, ya he probado de mil maneras distintas, y siempre consigo el mismo resultado.
Es posible que el código no esté muy optimizado, pero primero quiero hacerlo con grandes pinceladas, y luego irlo optimizando a medida que lo vaya entendiendo.
Muchas gracias de antemano a quien me ayude, y ¡perdón por la parrafada!