Você está na página 1de 28

5- Interrupciones

Ing. Juan Ramon Terven Salinas 65


5 INTERRUPCIONES

Una interrupcin es un evento interno o externo que requiere atencin inmediata del
CPU. La arquitectura del PIC32 puede manejar hasta 64 vectores de interrupcin
distintos y puede soportar hasta 96 fuentes de interrupcin distintas. Cada fuente de
interrupcin puede tener su propia rutina de interrupcin (ISR) en un vector individual,
o varias fuentes de interrupcin pueden compartir la misma ISR dentro de un solo
vector de interrupcin.

Bits asociados con cada fuente de interrupcin
Cada fuente de interrupcin tiene 7 bits de control agrupados en distintos SFRs.
Estos bits se describen a continuacin:

1. Bit de Habilitacin de Interrupcin (con terminacin IE). Cuando est en 0
la fuente de interrupcin asociada est deshabilitada. Cuando est en 1 la
fuente de interrupcin puede disparar una interrupcin. Al reset, todas las
fuentes de interrupcin estn deshabilitadas.
2. Bit de Bandera de Interrupcin (con terminacin IF). Este bit se activa
automticamente cuando se dispara un evento de interrupcin. Se debe limpiar
(poner en 0) por cdigo.
3. Bits de Nivel de Prioridad Grupal (con terminacin IP). Son 3 bits que
determinan la prioridad de la interrupcin (desde ipl1 hasta ipl7). Cuando
ocurren 2 disparos de interrupcin al mismo tiempo, se ejecutar primero la
fuente de interrupcin con mayor prioridad. Al reset todas las fuentes de
interrupcin tienen un nivel de prioridad ipl0 el cual indica deshabilitado.
4. Bits de Nivel de Subprioridad (cont terminacin IS). Son 2 bits ms usados
para especificar 4 niveles de subprioridad distintos dentro de un mismo grupo.

Adems de estos niveles de prioridad, si aun as 2 fuentes de interrupcin con la misma
prioridad se disparan al mismo tiempo, se ejecutar primero la que tenga la mayor
prioridad natural. La Tabla 5-1 muestra todas las fuentes de interrupcin con sus bits
asociados y el orden mostrado en esta tabla determina la prioridad natural.
5- Interrupciones
Ing. Juan Ramon Terven Salinas 66
Tabla 5-1. Fuentes de Interrupcin con sus bits asociados


5- Interrupciones
Ing. Juan Ramon Terven Salinas 67

5- Interrupciones
Ing. Juan Ramon Terven Salinas 68


Librera de Manejo de Interrupciones
El Lenguaje C32 provee una librera para manejo de interrupciones con funciones
que nos permiten configurar las interrupciones de manera sencilla.
Podemos agregar la librera como int.h o como plib.h (esta incluye int.h
adems de las funciones de manejo de perifricos).
Manejo de Interrupciones de un vector (Single Vector)
El PIC32 permite usar un solo vector para varias fuentes de interrupcin, o permite
usar vectores individuales para cada fuente de interrupcin.
Para activar el modo Single Vector podemos usar la siguiente funcin de la librera:

INTEnableSystemSingleVectoredInt();

Y definimos la rutina de interrupcin de la siguiente manera:
void __ISR( 0, ipl1) InterruptHandler (void)
{
//aqu va el cdigo de la rutina de interrupcin
}

En este cdigo el argumento (0, ipl1) se refiere a que usaremos el vector 0 con
prioridad 1.
5- Interrupciones
Ing. Juan Ramon Terven Salinas 69
Ejemplo 1: Interrupcin CN en Single Vector
La Interrupcin Change Notification (CN) se dispara cuando ocurre un cambio de
estado en alguno de los pins denominados CN (vea el diagrama de pines del PIC32).
Todos los pines CN producen la misma interrupcin.
Cada pin CN tiene una pull up conectada que puede ser habilitada o
deshabilitada por software.
Las pull ups deben ser deshabilitadas si el pin est configurado como salida.
Una vez que se produce una interrupcin CN, se debe leer el puerto donde se
ubica el pin CN que la produjo, de lo contrario, la interrupcin se producir otra
vez al salir de la rutina de interrupcin.
Recuerde limpiar la bandera de interrupcin antes de salir de la rutina de
interrupcin.

La Figura 5-1 muestra un diagrama a bloques del mecanismo de interrupcin Change
Notification.

Figura 5-1. Diagrama a bloques de la interrupcin CN [8]

5- Interrupciones
Ing. Juan Ramon Terven Salinas 70
Configuracin de Change Notification
De acuerdo al manual de referencia de la familia PIC32MX en el apartado de
puertos [8] , el procedimiento para configurar la interrupcin por Change Notification es
el siguiente:
1. Deshabilitar interrupciones del CPU.
2. Configurar los pines CN como entradas digitales (usando registro TRISx).
3. Activar el mdulo CN (bit ON del registro CNCON en 1).
4. Activar cada pin CN que deseamos utilizar (bits CNENx del registro CNEN).
5. Opcionalmente podemos activar las pull ups de cada pin CN (bits CNPUEx del
registro CNPUE).
6. Leer los puertos donde se ubican los pines CN para limpiar la condicin de
cambio.
7. Configurar la prioridad y subprioridad de la interrupcin (registro IPC6 vea la
Tabla 5-1).
8. Limpiar la bandera de interrupcin CN (bit CNIF del registro IFS1).
9. Activar la interrupcin CN (bit CNIE del registro IEC1).
10. Activar las interrupciones del CPU.

El ejemplo que se muestra a continuacin usa 2 pines CN, el RB0 (CN2) y el RB1
(CN3) para producir una interrupcin cuando cualquiera de estos 2 pines cambia de
estado. La rutina de interrupcin simplemente cambia el estado de 2 LEDs en funcin
de cual pin CN produjo un cambio positivo (de 0 a 1).
El circuito usado se muestra en la Figura 5-2 y el cdigo se muestra en el Programa 5-1.
El cdigo del programa muestra el procedimiento de configuracin de la interrupcin
Change Notification descrito anteriormente.
5- Interrupciones
Ing. Juan Ramon Terven Salinas 71

Figura 5-2. Ejemplo Interrupcin CN


Programa 5-1. Uso de interrupcin CN con Single Vector
#include <p32xxxx.h>
#include <plib.h>

//Bits de configuracion
#pragma config POSCMOD = HS, FNOSC = PRIPLL, FPLLMUL = MUL_20
#pragma config FPLLIDIV = DIV_2, FPLLODIV = DIV_1
#pragma config FPBDIV = DIV_1, FWDTEN = OFF, UPLLEN = ON
#pragma config UPLLIDIV = DIV_2, FVBUSONIO = ON, FUSBIDIO = ON
#pragma config FSOSCEN = OFF, CP = OFF, FCKSM = CSECMD

// Funcin Main
int main(void)
{
AD1PCFG = 0xFFFF; // configura AN pins como digitales

TRISE = 0; //Puerto E como salidas
LATE = 0; //Limpia salida de puerto E

/**CONFIGURACION DE INTERRUPCION CHANGE NOTIFICATION EN CN2 Y CN3****/

//Configura RB0(CN2) y RB1(CN3) como entradas
_TRISB0 = 1;
_TRISB1 = 1;

5- Interrupciones
Ing. Juan Ramon Terven Salinas 72
//Activa el mdulo CN
CNCONbits.ON = 1;

//Activa la interrupcin CN en los pines CN2 y CN3
CNENbits.CNEN2 = 1;
CNENbits.CNEN3 = 1;

//Activa las pull-ups en los pines CN2 y CN3
CNPUEbits.CNPUE2 = 1;
CNPUEbits.CNPUE3 = 1;

//Lee el registro PORTB para limpiar el change notification
PORTB;

//Selecciona prioridad 1 y subprioridad de 0
//La prioridad de 1 (ipl1) debe coincidir con la indicada en la
// rutina de interrupcin
IPC6bits.CNIP = 1; //prioridad de 1
IPC6bits.CNIS = 0; //subprioridad de 0

//Limpia la bandera de interrupcion
IFS1bits.CNIF = 0;

// Activa el modo Single Vector
INTEnableSystemSingleVectoredInt();

//Activa la interrupcion CN
IEC1bits.CNIE = 1;
/********************************************************************/

while(1)
{
}

return 0;
}

//RUTINA DE INTERRUPCIN
void __ISR( 0, ipl1) InterruptHandler( void)
{
if(PORTB & 1) //Lee el PORTB y extra el bit RB0 (CN2)
_LATE0 ^= 1;
else if(PORTB & 2) //Lee el PORTB y extra el bit RB1 (CN3)
_LATE1 ^= 1;

//Limpia la bandera de interrupcin
IFS1bits.CNIF = 0;
}

Mltiples Interrupciones en un solo vector (Single Vector)
Para tener varias rutinas de interrupcin en un solo vector, simplemente
configuramos las interrupciones con la misma prioridad y usamos la misma funcin
INTEnableSystemSingleVectoredInt();
5- Interrupciones
Ing. Juan Ramon Terven Salinas 73
La nica diferencia es que dentro de la rutina de interrupcin debemos averiguar
cual interrupcin fue disparada analizando la bandera de interrupcin de cada fuente de
interrupcin que comparte el mismo vector.
Ejemplo 2. Interrupciones INT0 y CN en el mismo vector
El PIC32 ofrece 5 fuentes de interrupcin externa disparadas por flanco llamadas
INT0, INT1, INT2, INT3 e INT4. Cada una de estas fuentes de interrupcin se puede
configurar para generar una interrupcin cuando se produce un flanco ascendente o un
flanco descendente en dicho pin.
El siguiente ejemplo muestra el uso de la interrupcin INT0 (pin RD0) y la
interrupcin CN (CN2 y CN3)
Programa 5-2. Interrupcin INT0 y CN en single vector
#include <p32xxxx.h>
#include <plib.h>

//Bits de configuracin
#pragma config POSCMOD = HS, FNOSC = PRIPLL, FPLLMUL = MUL_20
#pragma config FPLLIDIV = DIV_2, FPLLODIV = DIV_1
#pragma config FPBDIV = DIV_1, FWDTEN = OFF, UPLLEN = ON
#pragma config UPLLIDIV = DIV_2, FVBUSONIO = ON, FUSBIDIO = ON
#pragma config FSOSCEN = OFF, CP = OFF, FCKSM = CSECMD

int main(void)
{
AD1PCFG = 0xFFFF; // configura AN pins como digitales

TRISE = 0; //Puerto E como salidas
LATE = 0; //Limpia salida de puerto E

/** CONFIGURACION DE INTERRUPCIONES CN2 Y CN3 *****/

//Configura RB0(CN2) y RB1(CN3) como entradas
_TRISB0 = 1;
_TRISB1 = 1;

//Activa el mdulo CN
CNCONbits.ON = 1;

//Activa la interrupcin CN en los pines CN2 y CN3
CNENbits.CNEN2 = 1;
CNENbits.CNEN3 = 1;

//Activa las pull-ups en los pines CN2 y CN3
CNPUEbits.CNPUE2 = 1;
CNPUEbits.CNPUE3 = 1;

//Lee el registro PORTB para limpiar el change notification
PORTB;

5- Interrupciones
Ing. Juan Ramon Terven Salinas 74

//Activa prioridad 1 con subprioridad de 0
//La prioridad de 1 (ipl1) debe coincidir con la indicada en la
// rutina de interrupcin
IPC6bits.CNIP = 1; //prioridad de 1
IPC6bits.CNIS = 0; //subprioridad de 0

//Limpia la bandera de interrupcin
IFS1bits.CNIF = 0;

/************* CONFIGURACION DE INTERRUPCION INT0 ***************/
//Configura RD0 (INT0) como entrada
_TRISD0 = 1;

//Activacin por flanco descendente
INTCONbits.INT0EP = 0;

//Prioridad 1(ipl1) con subprioridad de 1
IPC0bits.INT0IP = 1;
IPC0bits.INT0IS = 1;

//Limpia la bandera de interrupcin
IFS0bits.INT0IF = 0;

// Activa el modo Single Vector
INTEnableSystemSingleVectoredInt();
/****************************************************************/

//FINALMENTE ACTIVA AMBAS INTERRUPCIONES
IEC1bits.CNIE = 1; //Activa la interrupcin CN
IEC0bits.INT0IE = 1; //Activa la interrupcin INT0

while(1)
{ }
return 0;
}

//RUTINA DE INTERRUPCIN
void __ISR( 0, ipl1) InterruptHandler( void)
{
// Si se dispar la rutina de interrupcion CN
if(IFS1bits.CNIF)
{
if(PORTB & 1) //Lee el PORTB y extra el bit RB0 (CN2)
_LATE0 ^= 1;
else if(PORTB & 2) //Lee el PORTB y extra el bit RB1 (CN3)
_LATE1 ^= 1;

//Limpia la bandera de interrupcin
IFS1bits.CNIF = 0;
}
// Si se dispar la rutina de interrupcin INT0
else if(IFS0bits.INT0IF)
{
_LATE2 ^= 1;

//Limpia la bandera de interrupcin
IFS0bits.INT0IF = 0;
}
}
5- Interrupciones
Ing. Juan Ramon Terven Salinas 75
Manejo de Interrupciones con mltiples vectores
El PIC32 soporta el manejo de interrupciones con mltiples vectores. La ventaja de
este mtodo es que la latencia en el servicio de interrupcin es menor. La latencia del
servicio de interrupcin es aun menor si se asigna prioridad nivel 7 ya que se hace uso
de un registro conjunto de registros alterno para respaldo.
La Tabla 5-2 muestra los vectores de interrupcin con su nombre simblico que se
usar en la rutina de interrupcin.
Tabla 5-2. Vectores de Interrupcin [14]


5- Interrupciones
Ing. Juan Ramon Terven Salinas 76



5- Interrupciones
Ing. Juan Ramon Terven Salinas 77
Ejemplo 3. Interrupciones INT0 y CN en mltiples vectores
El siguiente ejemplo demuestra el uso de interrupciones en modo Multivector. El
funcionamiento del circuito es equivalente al ejemplo anterior. Se resalta con color azul
el cdigo distinto al ejemplo anterior que usaba un solo vector de interrupcin.
Programa 5-3. Uso de Interrupciones CN e INT2 en vectores separados
#include <p32xxxx.h>
#include <plib.h>

//Bits de configuracin
#pragma config POSCMOD = HS, FNOSC = PRIPLL, FPLLMUL = MUL_20
#pragma config FPLLIDIV = DIV_2, FPLLODIV = DIV_1
#pragma config FPBDIV = DIV_1, FWDTEN = OFF, UPLLEN = ON
#pragma config UPLLIDIV = DIV_2, FVBUSONIO = ON, FUSBIDIO = ON
#pragma config FSOSCEN = OFF, CP = OFF, FCKSM = CSECMD

int main(void)
{
AD1PCFG = 0xFFFF; // configura AN pins como digitales

TRISE = 0; //Puerto E como salidas
LATE = 0; //Limpia salida de puerto E

/******CONFIGURACION DE INTERRUPCIONES CN2 Y CN3 *****/
//Configura RB0(CN2) y RB1(CN3) como entradas
_TRISB0 = 1;
_TRISB1 = 1;

//Activa el mdulo CN
CNCONbits.ON = 1;

//Activa la interrupcion CN en los pines CN2 y CN3
CNENbits.CNEN2 = 1;
CNENbits.CNEN3 = 1;

//Activa las pull-ups en los pines CN2 y CN3
CNPUEbits.CNPUE2 = 1;
CNPUEbits.CNPUE3 = 1;

//Lee el registro PORTB para limpiar el change notification
PORTB;

//Activa la prioridad 1 en la interrupcion CN con subprioridad de 0
//La prioridad de 1 (ipl1) debe coincidir con la indicada
//en la rutina de interrupcin
IPC6bits.CNIP = 1; //prioridad de 1
IPC6bits.CNIS = 0; //subprioridad de 0

//Limpia la bandera de interrupcin
IFS1bits.CNIF = 0;
/*****************************************************************/

/************** CONFIGURACION DE INTERRUPCION INT0 **************/
//Configura RD0 (INT0) como entrada
_TRISD0 = 1;

//Activacin por flanco descendente
5- Interrupciones
Ing. Juan Ramon Terven Salinas 78
INTCONbits.INT0EP = 0;

//Prioridad 2(ipl2) con subprioridad de 1
IPC0bits.INT0IP = 2;
IPC0bits.INT0IS = 1;

//Limpia la bandera de interrupcion
IFS0bits.INT0IF = 0;

// Activa el modo MultiVectored
INTEnableSystemMultiVectoredInt();
/****************************************************************/

//FINALMENTE ACTIVA AMBAS INTERRUPCIONES
IEC1bits.CNIE = 1; //Activa la interrupcion CN
IEC0bits.INT0IE = 1; //Activa la interrupcion INT0

while(1)
{
}

return 0;
}

//RUTINA DE INTERRUPCIN DE CHANGE NOTIFICATION
void __ISR( _CHANGE_NOTICE_VECTOR, ipl1) CNInterruptHandler(void)
{
if(PORTB & 1) //Lee el PORTB y extra el bit RB0 (CN2)
_LATE0 ^= 1;
else if(PORTB & 2) //Lee el PORTB y extra el bit RB1 (CN3)
_LATE1 ^= 1;

//Limpia la bandera de interrupcin
IFS1bits.CNIF = 0;
}

//RUTINA DE INTERRUPCIN DE INT0
void __ISR( _EXTERNAL_0_VECTOR, ipl2) INT0InterruptHandler(void)
{
_LATE2 ^= 1;

//Limpia la bandera de interrupcion
IFS0bits.INT0IF = 0;
}


5- Interrupciones
Ing. Juan Ramon Terven Salinas 79
Uso de un Teclado Matricial
Un teclado matricial est constituido por una matriz de pulsadores dispuestos en
filas y columnas como se muestra en la Figura 5-3. La finalidad es reducir el nmero de
lneas necesarias para la conexin.
Como se observa en la figura, cada tecla se conecta a una fila y a una columna. En
este caso se tiene un teclado de 4x4 en el cual se necesitan slo 8 pines del
microcontrolador en lugar de 16 si fueran botones independientes. Cuando se pulsa una
tecla, queda en contacto una fila con una columna. Si no hay tecla pulsada, las filas
estn desconectadas de las columnas.


Figura 5-3. Teclado matricial con microcontrolador [19]

5.1.1 Conexin de un Teclado matricial con un PIC32


La Figura 5-3 muestra una posible conexin de un teclado matricial a un PIC32 con las
siguientes caractersticas:
Las filas del teclado se conectan a pines configurados como salida.
Las columnas del teclado se conectan a pines con interrupcin CN. Observe que
estas pines deben tener habilitadas las resistencias de pull-up.

5- Interrupciones
Ing. Juan Ramon Terven Salinas 80
Si se presiona una tecla, una de las columnas (entras CN) recibe un nivel bajo
produciendo una interrupcin. Por ejemplo en la Figura 5-3 se pulsa la tecla 3, de tal
forma que se produce una interrupcin Change Notification. En la rutina de
interrupcin, debemos determinar que tecla se puls por medio del siguiente algortmo.

5.1.2 Algoritmo para lectura del teclado

1. A cada tecla se le asigna un cdigo que puede ser el orden de la tecla, como se
muestra en la Figura 5-4.


Figura 5-4- Codigo asignado a cada tecla


2. Luego ejecutamos el algoritmo siguiente:
5- Interrupciones
Ing. Juan Ramon Terven Salinas 81





Figura 5-5. Algoritmo de deteccin de tecla pulsada


5- Interrupciones
Ing. Juan Ramon Terven Salinas 82
A continuacin se muestra una funcin llamada leeTecla la cual implementa el
algoritmo anterior en lenguaje C32:


//VALORES DE LAS TECLAS
char teclas[16] ={ '1','2','3','A',
'4','5','6','B',
'7','8','9','C',
'*','0','#','D'};

// Esta funcion obtiene la tecla pulsada del
// teclado matricial y la decodifica.
// Regresa el caracter ASCII que representa la tecla
int leeTecla(void)
{
char tecla;

//REVISA FILA 1
// Fila1 = 0, dems filas = 1
FIL1 = 0;
FIL2 = 1;
FIL3 = 1;
FIL4 = 1;

tecla = 0;

if(COL1==0) goto decodificaTecla;
tecla++;

if(COL2==0) goto decodificaTecla;
tecla++;

if(COL3==0) goto decodificaTecla;
tecla++;

if(COL4==0) goto decodificaTecla;
tecla++;

//REVISA FILA 2
// Fila2 = 0, dems filas = 1
FIL2 = 0;
FIL1 = 1;
FIL3 = 1;
FIL4 = 1;
if(COL1==0) goto decodificaTecla;
tecla++;

if(COL2==0) goto decodificaTecla;
tecla++;

if(COL3==0) goto decodificaTecla;
tecla++;

if(COL4==0) goto decodificaTecla;
tecla++;




5- Interrupciones
Ing. Juan Ramon Terven Salinas 83
//REVISA FILA 3
// Fila3 = 0, dems filas = 1
FIL3 = 0;
FIL2 = 1;
FIL1 = 1;
FIL4 = 1;
if(COL1==0) goto decodificaTecla;
tecla++;

if(COL2==0) goto decodificaTecla;
tecla++;

if(COL3==0) goto decodificaTecla;
tecla++;

if(COL4==0) goto decodificaTecla;
tecla++;

//REVISA FILA 4
// Fila4 = 0, dems filas = 1
FIL4 = 0;
FIL3 = 1;
FIL2 = 1;
FIL1 = 1;
if(COL1==0) goto decodificaTecla;
tecla++;

if(COL2==0) goto decodificaTecla;
tecla++;

if(COL3==0) goto decodificaTecla;
tecla++;

if(COL4==0) goto decodificaTecla;
tecla++;

decodificaTecla:
//Deja lista las filas para la interrupcion
FIL1 = 0;
FIL2 = 0;
FIL3 = 0;
FIL4 = 0;

// Decodifica la tecla
if(tecla < 16)
return teclas[tecla];
else
return -1;


}//fin de funcin leeTecla
Programa 5-4. Algoritmo de lectura del teclado, funcin leeTecla


La idea es que cuando se pulse cualquier tecla se produzca una interrupcin CN, para
esto debemos habilitar la interrupcin CN en los pines donde se conectan las columnas
C1-C4.
5- Interrupciones
Ing. Juan Ramon Terven Salinas 84
La funcin openTeclado mostrada en el cdigo siguiente deja listo el
microcontrolador para detectar las interrupciones CN.

// Esta funcin Activa la interrupcin CN en los pines
// En el archivo teclado.h se encuentran las definiciones de los pines
void openTeclado(void)
{
//Configura columnas como entradas
TRIS_COL1 = 1;
TRIS_COL2 = 1;
TRIS_COL3 = 1;
TRIS_COL4 = 1;

//Configura filas como salidas
TRIS_FIL1 = 0;
TRIS_FIL2 = 0;
TRIS_FIL3 = 0;
TRIS_FIL4 = 0;

//Escribe 0 en las filas para dejar listo el teclado
FIL1 = 0;
FIL2 = 0;
FIL3 = 0;
FIL4 = 0;

//Activa el mdulo CN
CNCONbits.ON = 1;

//Activa la interrupcion CN en cada columna
CN_COL1 = 1;
CN_COL2 = 1;
CN_COL3 = 1;
CN_COL4 = 1;

//Activa las pull-ups en cada columna
PULL_COL1 = 1;
PULL_COL2 = 1;
PULL_COL3 = 1;
PULL_COL4 = 1;

//Lee los pines de columnas para limpiar el change notification
COL1; COL2; COL3; COL4;

//Prioridad del teclado
IPC6bits.CNIP = PRIORIDAD_TECLADO;
IPC6bits.CNIS = SUBPRIORIDAD_TECLADO;

//Limpia la bandera de interrupcion
IFS1bits.CNIF = 0;

// Activa el modo de interrupcin (vea teclado.h)
MODO_DE_INTERRUPCION

IEC1bits.CNIE = 1; //Activa la interrupcion CN
}
Programa 5-5. Funcin openTeclado


5- Interrupciones
Ing. Juan Ramon Terven Salinas 85

Estas funciones anteriores forman parte de un archivo llamado teclado.c el cual
junto con otro archivo llamado teclado.h forman la librera para el teclado. A
continuacin se muestra el contenido del archivo teclado.h.
#ifndef TECLADO_H
#define TECLADO_H
#include <p32xxxx.h>
#include <plib.h>

//AQUI MODIFIQUE LO REFERENTE A LA INTERRUPCION
#define PRIORIDAD_TECLADO 1 //ipl1
#define SUBPRIORIDAD_TECLADO 0
#define MODO_DE_INTERRUPCION INTEnableSystemMultiVectoredInt();

//AQUI CAMBIE LOS PINES DE ACUERDO A SU CONEXIN
//Registro TRIS de Columnas
#define TRIS_COL1 TRISBbits.TRISB0
#define TRIS_COL2 TRISBbits.TRISB1
#define TRIS_COL3 TRISBbits.TRISB4
#define TRIS_COL4 TRISBbits.TRISB5

//Pines de entrada de Columnas
#define COL1 PORTBbits.RB0
#define COL2 PORTBbits.RB1
#define COL3 PORTBbits.RB4
#define COL4 PORTBbits.RB5

//Interrupciones CN de cada columna
#define CN_COL1 CNENbits.CNEN2
#define CN_COL2 CNENbits.CNEN3
#define CN_COL3 CNENbits.CNEN6
#define CN_COL4 CNENbits.CNEN7

//Pull-ups de cada columna
#define PULL_COL1 CNPUEbits.CNPUE2
#define PULL_COL2 CNPUEbits.CNPUE3
#define PULL_COL3 CNPUEbits.CNPUE6
#define PULL_COL4 CNPUEbits.CNPUE7

//Registro TRIS de Filas
#define TRIS_FIL1 TRISDbits.TRISD4
#define TRIS_FIL2 TRISDbits.TRISD5
#define TRIS_FIL3 TRISBbits.TRISB9
#define TRIS_FIL4 TRISDbits.TRISD11

//Pines de salida de las filas
#define FIL1 LATDbits.LATD4
#define FIL2 LATDbits.LATD5
#define FIL3 LATBbits.LATB9
#define FIL4 LATDbits.LATD11

//Prototipos de funciones
void openTeclado(void);
void setTeclado(void);
int leeTecla(void);

#endif
Programa 5-6. teclado.h
5- Interrupciones
Ing. Juan Ramon Terven Salinas 86
Ejemplo 4. Uso de Teclado Matricial
El siguiente ejemplo hace uso de la librera teclado.h explicada anteriormente
para probar el funcionamiento de un teclado matricial conectado como se muestra en la
Figura 5-6. El programa simplemente muestra en pantalla la tecla pulsada.

Figura 5-6. Circuito para ejemplo de teclado matricial

Cada vez que se pulsa cualquier tecla, se genera una interrupcin CN. Dentro de la
rutina de servicio de interrupcin se identifica la tecla pulsada con la funcin
leeTecla() y luego se muestra en el display el cdigo asociado con dicha tecla.
5- Interrupciones
Ing. Juan Ramon Terven Salinas 87
Programa 5-7. Ejemplo de Teclado Matricial
#include <p32xxxx.h>
#include "../librerias/LCD/alpha_lcd.h"
#include "../librerias/teclado/teclado.h"
#include "../librerias/retardos/retardos.h"

//Bits de configuracion
#pragma config POSCMOD = HS, FNOSC = PRIPLL, FPLLMUL = MUL_20
#pragma config FPLLIDIV = DIV_2, FPLLODIV = DIV_1
#pragma config FPBDIV = DIV_1, FWDTEN = OFF, UPLLEN = ON
#pragma config UPLLIDIV = DIV_2, FVBUSONIO = ON, FUSBIDIO = ON
#pragma config FSOSCEN = OFF, CP = OFF, FCKSM = CSECMD


int main(void)
{

AD1PCFG = 0xFFFF; // configura pines AN como digitales

// configura LCD
openLCD();

//Escribe TECLADO en renglon 1
setDDRamAddr(0x0);
putsLCD("TECLADO");

//Coloca el cursor en renglon 2
setDDRamAddr(0x40);

//Activa el teclado matricial
openTeclado();

//Ciclo principal
while(1)
{
//Solo espera a que se pulse una tecla
}

return 0;
}

//RUTINA DE INTERRUPCIN DE CHANGE NOTIFICATION
//Se produce cuando se pulsa cualquier tecla
void __ISR( _CHANGE_NOTICE_VECTOR, ipl1) CNInterruptHandler( void)
{
char tecla;

retardoms(5);
tecla = leeTecla();

if(tecla != -1) // si hay tecla valida
{
putcLCD(tecla); // escribe la tecla pulsada en LCD
while(leeTecla()!=-1); //espera a que se suelte la tecla
retardoms(5);
}

//Limpia la bandera de interrupcin
IFS1bits.CNIF = 0;
}
5- Interrupciones
Ing. Juan Ramon Terven Salinas 88
Ejemplo 5. Calculadora Bsica
El siguiente ejemplo consiste en una calculadora bsica capaz de realizar las
operaciones suma, resta, multiplicacin y divisin.
La Figura 5-7 muestra el diagrama de la calculadora bsica. Observe que el
diagrama es idntico al anterior, la nica diferencia es el valor de las teclas del teclado
matricial.
El cdigo se encuentra bastante comentado para hacerlo autoexplicativo.

Figura 5-7. Calculadora Bsica


5- Interrupciones
Ing. Juan Ramon Terven Salinas 89
Programa 5-8. Calculadora Bsica
#include <p32xxxx.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include "../librerias/LCD/alpha_lcd.h"
#include "../librerias/teclado/teclado.h"
#include "../librerias/retardos/retardos.h"

//Bits de configuracion
#pragma config POSCMOD = HS, FNOSC = PRIPLL, FPLLMUL = MUL_20
#pragma config FPLLIDIV = DIV_2, FPLLODIV = DIV_1
#pragma config FPBDIV = DIV_1, FWDTEN = OFF, UPLLEN = ON
#pragma config UPLLIDIV = DIV_2, FVBUSONIO = ON, FUSBIDIO = ON
#pragma config FSOSCEN = OFF, CP = OFF, FCKSM = CSECMD

//Prototipo de funcion
double operacion(double,char,double);

//Tamao de los nmeros de la calculadora
#define SIZE_NUMBERS 15

//Variables Globales
char str_operando[SIZE_NUMBERS+1] = {0};
char operador;
short indiceOperando;
double resultado, operando;

//Programa principal
int main(void)
{
AD1PCFG = 0xFFFF; // configura pines AN como digitales

// configura LCD
openLCD();

//Escribe 0 en rengln 1
setDDRamAddr(0x0);
putsLCD("0");
setDDRamAddr(0x0);

//Activa el teclado matricial
openTeclado();

//Inicia variables
indiceOperando = 0;
operador=0;
resultado = 0;
strcpy(str_operando,"0");

//Ciclo principal
while(1)
{
//Solo espera a que se pulse una tecla
}

return 0;
}



5- Interrupciones
Ing. Juan Ramon Terven Salinas 90
//RUTINA DE INTERRUPCIN DE CHANGE NOTIFICATION
//Se produce cuando se pulsa cualquier tecla
//1. Decodifica la tecla pulsada
//2. Si se pulsa una tecla de operacion matemtica
// guarda el valor escrito y el operador
//3. Si se pulsa = realiza la oepracin y
// muestra el resultado en pantalla
//4. Si se pulsa C limpia todo
//5. Si se pulsa una tecla de nmero lo agrega
// a la cadena str_operando
void __ISR( _CHANGE_NOTICE_VECTOR, ipl1) CNInterruptHandler(void)
{
char tecla;
retardoms(5);

1).
tecla = leeTecla();

if(tecla != -1) // si hay tecla valida
{
switch(tecla)
{
//2) Si se puls una tecla de operacion
case '+':
case '-':
case '*':
case '/':
//convierte la cadena a double y guarda en resultado
resultado = atof(str_operando);
//Guarda el operador
operador = tecla;
//Reinicia indice para almacenar cadena numerica
indiceOperando = 0;
//Imprime el operador
putcLCD(tecla);
break;
//3) Si se puls la tecla =
case '=':
//Convierte la cadena de operando a double
operando = atof(str_operando);
//realiza la operacion
resultado = operacion(resultado,operador,operando);
//convierte resultado a cadena
sprintf(str_operando,"%f",resultado);
//lo muestra en renglon2
setDDRamAddr(0x40);
putsLCD(str_operando);
//reinicia la cadena operando
strcpy(str_operando,"0");
indiceOperando = 0;
break;
//4) Si se puls la tecla 'C'
case 'C':
//limpia cadena operando
indiceOperando = 0;
strcpy(str_operando,"0");
//limpia operador y resultado
operador=0;
resultado = 0;
//limpia pantalla
setDDRamAddr(0x0);
5- Interrupciones
Ing. Juan Ramon Terven Salinas 91
putsLCD("0 ");
setDDRamAddr(0x40);
putsLCD(" ");
setDDRamAddr(0x0);
break;
//5) De lo contrario si se puls un numero
default:
//Si indiceOperando es 0, limpia renglon 1
//y se coloca al inicio de LCD
if(indiceOperando == 0)
{
setDDRamAddr(0x0);
putsLCD(" ");
setDDRamAddr(0x0);
}
//Si aun caben digitos...
if(indiceOperando <= SIZE_NUMBERS)
{
//almacena el digito en la cadena operando
str_operando[indiceOperando++] = tecla;
str_operando[indiceOperando] = 0; //fin de cadena
//lo muestra en LCD
putcLCD(tecla);
}
}
while(leeTecla()!=-1); //espera a que se suelte la tecla
retardoms(5);
}

//Limpia la bandera de interrupcion
IFS1bits.CNIF = 0;
}

//Realiza la operacin matemtica indicada
double operacion(double valor1, char operador, double valor2)
{
double r = 0;
switch(operador)
{
case '+':
r = valor1 + valor2;
break;
case '-':
r = valor1 - valor2;
break;
case '*':
r = valor1 * valor2;
break;
case '/':
if(valor2 != 0)
r = valor1 / valor2;
break;
}
return r;
}

5- Interrupciones
Ing. Juan Ramon Terven Salinas 92
PRCTICA 3. Calculadora Cientfica bsica
Usando el mismo circuito de los 2 ejemplos anteriores, disee una calculadora
cientfica que realice las operaciones mostradas en la Figura 5-8.

Nota: Use las funciones de la librera math.h para realizar las operaciones
trigonomtricas y transcendentes.


Figura 5-8. Teclado de Calculadora Cientfica

Você também pode gostar