Hola, bueno les paso a explicar el problema.
Tengo como proyecto realizar una matriz de leds controlada por un teclado PS2, entonces encontre el codigo de PicMania para decodificar los ScanCodes, por suerte lo entendí.
Estoy utilizando un 628a.
Para adaptarlo realize lo siguiente, en vez de que el caracter decodificado se envie a un display por el puerto serie, guardaba el caracter en una cadena seguido del valor null "\0".
Configure los puertos correctamente, utilize el RB0 como clock e interrupcion, y el RA5 como entrada del tren de datos.
La matriz muestra mensajes preestablecidos, osea primero comprobe que muestre los mensajes que yo queria, sin conectar el teclado.Por ejemplo cuando prendo la matriz dice "Matriz de Leds" ...despues de dos segundos "Iniciando"... y despues de un segundo "Ingrese Mensaje", recien ahi inicializo las interrupciones y entro en el bucle infinito.
Para mostrar un mensaje solo basta con poner un strcpy(texto,"Un Texto Cualquiera").
El problema es que apreto una letra del teclado, y titila el mensaje "Ingrese mensaje" ( pareciera que tomo la interrupcion, pero no decodifico nada ), comprobe que no decodifica nada, pero entra en la interrupcion, lo comprobe copiando a la cadena de caracteres el mensaje "letra" (de esa forma muestra en la matriz la palabra "letra"), entonces una vez que toque una tecla y mostro el mensaje letra, me di cuenta que el error estaba mas abajo, entonces realize lo mismo, en la parte que decodifica la tecla ENTER, puse strcpy(texto, "enter") (asi realizo el envio de mensajes a la matriz) ... y al apretar ENTER, NO MUESTRA EL MENSAJE. SOLO TITILA EL MENSAJE "Ingrese Mensaje".
Y NO SOLO ESO, medi las tensiones en los pines de clock y data. Cuando inicio la matriz, estan a nivel alto, cuando aprieto una tecla parpadea el mensaje "Ingrese Mensaje", y los pines siguen a nivel alto ( hasta ahi esta bien, el cambio no se puede notar ya que se realiza muy rapido ).
PERO CUANDO APRIETO 4 VECES ALGUNA TECLA, O TECLAS DISTINTAS, ME TIRA EL CLOCK Y DATA A NIVEL BAJO, Y LOS DEJA AHI, entonces si vuelvo a apretar ni siquiera titila o parpadea el mensaje "Ingrese Mensaje".
El reloj esta configurado a 20MHZ.
El problema principal es porque si aprieto 4 o 5 veces una tecla, me deja el Clock y el Data en Estado Bajo ? En la parte Hardware no creo que haya problemas, ya que tiene su resistencia 10K de pullup. Supongo que debe estar con el tema del tiempo o algo asi, RedPic dice claramente que se debe usar con 20MHZ
Espero que me puedan ayudar ya que es un trabajo de fin de curso y no se que mas probar.
Les dejo el Main, interrupcion y el decode.
#include <16F628A.h>
#include <string.h>
#FUSES NOWDT //Watch Dog Timer
#FUSES HS
#FUSES NOPROTECT //Code not protected from reading
#FUSES NOBROWNOUT //No brownout reset
#FUSES NOLVP //No low voltage prgming, B3(PIC16) or B5(PIC18) used for I/O
#FUSES NOCPD //No EE protection
#FUSES NOMCLR
#ZERO_RAM
#use delay(clock=20000000)
#byte PORTA = 0x05
#byte PORTB = 0x06
#bit INTF_BIT = 0x0B.1 // INTCON BIT 1 = INTF RB0/INT External Interrupt Flag Bit
#define SHIFT_DAT PIN_A0 // PIN DE DATOS DEL REGISTRO DE DESPLAZAMIENTO
#define SHIFT_CLK PIN_A3 // PIN DE CLOCK DEL REG
#define SHIFT_RST PIN_A1 // PIN DE RESET DEL REG
//-------- Tabla de caracteres correspondientes a la pulsación de la tecla
//-------- en modalidad normal (sin pulsar SHIFT)
unsigned char const unshifted[68][2] = {
0x0d,9,
0x0e,'º', 0x15,'q', 0x16,'1', 0x1a,'z', 0x1b,'s', 0x1c,'a', 0x1d,'w',
0x1e,'2', 0x21,'c', 0x22,'x', 0x23,'d', 0x24,'e', 0x25,'4', 0x26,'3',
0x29,' ', 0x2a,'v', 0x2b,'f', 0x2c,'t', 0x2d,'r', 0x2e,'5', 0x31,'n',
0x32,'b', 0x33,'h', 0x34,'g', 0x35,'y', 0x36,'6', 0x39,',', 0x3a,'m',
0x3b,'j', 0x3c,'u', 0x3d,'7', 0x3e,'8', 0x41,',', 0x42,'k', 0x43,'i',
0x44,'o', 0x45,'0', 0x46,'9', 0x49,'.', 0x4a,'-', 0x4b,'l', 0x4c,'ñ',
0x4d,'p', 0x4e,''', 0x52,'´', 0x54,'`', 0x55,'¡', 0x5a,13, 0x5b,'+',
0x5d,'ç', 0x61,'<', 0x66,8, 0x69,'1', 0x6b,'4', 0x6c,'7', 0x70,'0',
0x71,'.', 0x72,'2', 0x73,'5', 0x74,'6', 0x75,'8', 0x79,'+', 0x7a,'3',
0x7b,'-', 0x7c,'*', 0x7d,'9',
0,0
};
//-------- Tabla de caracteres correspondientes a la pulsación de la tecla
//-------- en modalidad desplazamiento (pulsando SHIFT)
unsigned char const shifted[68][2] = {
0x0d,9,
0x0e,'ª', 0x15,'Q', 0x16,'!', 0x1a,'Z', 0x1b,'S', 0x1c,'A', 0x1d,'W',
0x1e,'"', 0x21,'C', 0x22,'X', 0x23,'D', 0x24,'E', 0x25,'$', 0x26,'·',
0x29,' ', 0x2a,'V', 0x2b,'F', 0x2c,'T', 0x2d,'R', 0x2e,'%', 0x31,'N',
0x32,'B', 0x33,'H', 0x34,'G', 0x35,'Y', 0x36,'&', 0x39,'L', 0x3a,'M',
0x3b,'J', 0x3c,'U', 0x3d,'/', 0x3e,'(', 0x41,';', 0x42,'K', 0x43,'I',
0x44,'O', 0x45,'=', 0x46,')', 0x49,':', 0x4a,'_', 0x4b,'L', 0x4c,'Ñ',
0x4d,'P', 0x4e,'?', 0x52,'¨', 0x54,'^', 0x55,'¿', 0x5a,13, 0x5b,'*',
0x5d,'Ç', 0x61,'>', 0x66,8, 0x69,'1', 0x6b,'4', 0x6c,'7', 0x70,'0',
0x71,'.', 0x72,'2', 0x73,'5', 0x74,'6', 0x75,'8', 0x79,'+', 0x7a,'3',
0x7b,'-', 0x7c,'*', 0x7d,'9',
0,0
};
char texto[20]; //TEXTO A REPRESENTAR EN LA MATRIZ, MAX 20 CARACTERES
unsigned char bitcount, cont_texto=0;
unsigned char data;
int1 flag_inter=FALSE;
char got_interrupt;
char interrupt_count;
char status_b3;
unsigned int8 cantdeletras, fila=1, j=0, c=0, pos_let=0, mul=1,cont=0;
unsigned int8 f=0, relleno=0, i_inicio=0;
unsigned int8 i=0;
unsigned int8 const columnas=24;
//-----------------------------------------------------------------------------
// Decodificación de pulsaciones
//-----------------------------------------------------------------------------
void decode(unsigned char sc)
{
static unsigned char is_up=0, shift = 0;
unsigned char cont_dec;
//-------- El último dato recibido fue el identificador de Up-Key
if (!is_up){
switch (sc){
//-------- Identificador de Up-Key
case 0xF0 :
is_up = 1;
break;
//-------- SHIFT Izquierdo
case 0x12 :
shift = 1;
break;
//-------- SHIFT Derecho
case 0x59 :
shift = 1;
break;
//-------- ENTER
case 0x5A :
shift = 0;
strcpy(texto,"Enter");
cont_texto=0; //EN CASO DE ENTER,PONE EL CONTADOR DE CARACTERES A CERO
break;
//-------- Si no es ninguno de los identificadores especiales, procesar
//-------- pulsación, localizando caracter en tabla de caracteres.
default:
//-------- Pulsación normal
if(!shift)
{
for(cont_dec = 0; unshifted[cont_dec][0]!=sc && unshifted[cont_dec][0]; cont_dec++);
if (unshifted[cont_dec][0] == sc)
{
texto[cont_texto] = unshifted[cont_dec][1]; //COPIA EL CARACTER A LA CADENA
texto[cont_texto+1] = '\0'; //INSERTA AL FINAL EL VALOR DE FINAL DE CADENA
cont_texto++;
}
}
else
//-------- Pulsación + SHIFT presionado
{
for(cont_dec = 0; shifted[cont_dec][0]!=sc && shifted[cont_dec][0]; cont_dec++);
if (shifted[cont_dec][0] == sc)
{
texto[cont_texto] = shifted[cont_dec][1];
texto[cont_texto+1] = '\0';
cont_texto++;
}
}
break;
} // --- End Switch
}
else
{
//-------- No se permiten 2 0xF0 en una fila
is_up = 0;
switch (sc)
{
//-------- SHIFT Izquierdo
case 0x12 :
shift = 0;
break;
//-------- SHIFT Derecho
case 0x59 :
shift = 0;
break;
} // --- End Switch
}
}
//-----------------------------------------------------------------------------
// Rutina de gestión de interrupciones
//-----------------------------------------------------------------------------
#int_EXT
void EXT_isr(void){
got_interrupt = TRUE;
flag_inter=TRUE;
disable_interrupts(INT_EXT);
}
void main()
{
setup_timer_0(RTCC_INTERNAL|RTCC_DIV_1);
setup_timer_1(T1_DISABLED);
setup_timer_2(T2_DISABLED,0,1);
setup_comparator(NC_NC_NC_NC);
setup_vref(FALSE);
delay_ms(100);
bitcount=11;
PORTA=0b00100010;
PORTB=0b11111111;
//-------- Los pins indicados (B0 y B3) son configurados como entradas.
set_tris_a(0b11011111);
set_tris_b(0b11111110);
//-------- Espera a que se activen.
delay_us(5);
//-------- Inicializa las variables usadas por la rutina de interrupción
//-------- antes de activar las interrupciones
interrupt_count = 0;
got_interrupt = FALSE;
status_b3 = 0;
output_high(SHIFT_RST);
fila=1;
strcpy(texto,"Matriz de Leds");
for(i_inicio=0; i_inicio<200; i_inicio++)
envio_mensaje();
strcpy(texto,"Iniciando..");
for(i_inicio=0; i_inicio<200; i_inicio++)
envio_mensaje();
strcpy(texto,"Iniciando....");
for(i_inicio=0; i_inicio<200; i_inicio++)
envio_mensaje();
strcpy(texto,"Ingrese Mensaje");
//-------- Desde que se activó el modo PULLUPS del puerto B, el estado
//-------- normal del pin B0 es ALTO. La gestión de la interrupción externa
//-------- se gestiona cuando se produce un cambio de nivel ALTO a BAJO.
ext_int_edge(H_TO_L);
//-------- Asegurarse de que el el bit de flag de la interrupción externa
//-------- es borrado antes de activar la gestión de dicha interrupción
//-------- externa.
INTF_BIT = 0;
enable_interrupts(INT_EXT);
enable_interrupts(GLOBAL);
while(TRUE)
{
if(got_interrupt == TRUE)
{
if(flag_inter==TRUE)
{
//-------- Los bit 3 a 10 se considerran datos. Paridad, start y stop
//-------- son ignorados
if(bitcount < 11 && bitcount > 2){
data = (data >> 1);
status_b3 = input(PIN_A5);
if((status_b3) == 1){
data = data | 0x80;
}
}
//-------- Todos los bits se han recibido
if(--bitcount == 0){
decode(data);
data = 0;
bitcount = 11;
got_interrupt = TRUE;
}
interrupt_count++;
}
//-------- Borrar el flag global que se inicio en la rutina de servicio
//-------- de interrupciones externas.
got_interrupt = FALSE;
flag_inter = FALSE;
//-------- Esperar 50 ms para evitar rebotes en los contactos de las teclas.
delay_ms(50);
//-------- Borrar cualquier interrupción producida durante el periodo de espera.
INTF_BIT = 0;
//-------- Reactivar interrupciones
enable_interrupts(INT_EXT);
} // --- End If ---
envio_mensaje();
}
}