Hola, en mi proyecto estoy utilizando un micro de muy pocos pines 28 para ser precisos, ante el agregado de componentes y funciones decayeron considerablemente la cantidad de pines hasta quedar libres unos 4 o 5, ninguno de ellos ligado a una interrupción externa. Mi proyecto necesitaba la posibilidad de interrumpir en cualquier momento el sistema, por lo tanto, en arquitecturas menos evolucionadas estaba destinado a combatir mi problema por software utilizando recursos y podía llegar al punto de tener que optar por otro micro con más pines. Aquí ingresan al juego los PPS como héroes, dicho a lo bruto los PPS son registros que permiten asignar funciones a pines que no las tenían por defecto, pero cualquier pin? cualquier modulo o función? bueno la respuesta es no a ambas preguntas. Primero no cualquier pin puede ser remapeado en el diagrama de pines se observa los que pueden ser remapeados destacados como Rpx donde x va de 1 a 15.
se observa por ejemplo que el pin 11 correspondiente a RB4 (Rp4) no esta asignado a ninguna interrupción externa y también puede verse que este micro contiene 3 interrupciones externas INT0, INT1 e INT2 solo la primera de estas tiene asignado un pin por defecto e incluso en la siguiente tabla puede verse que la función INT0 no permite PPS ! genial!
Bien, entonces si podemos asignar en cualquier punto del programa esa interrupción INT1 a RP4 sería perfecto. Pero un momento, no tenemos que pisar en la trampa y apresurarnos ya que quedan otros detalles por ver...
Los registros PPS se dividen en 2 grupos: uno para mapear periféricos de entrada y otro para mapear periféricos de salida. Los registro utilizados para configurar el mapeo de las entradas son los denominados RPINRx y Como en este caso el periférico es efectivamente de entrada, entonces, en este conjunto esta el registro que debemos afectar. En la siguiente imagen se ve una representacion de multlipexación que haría un registro de entrada PPS en este caso para UIRX
Pero si la idea era ligar la interrupción externa INT1 a RP4 el registro que debemos modificar sería RPINR0, del registro se observa que solo son necesarios 5 bits para asignar la interrupción a cualquiera de las Rpx. Para este caso Rp4 es decir debemos ubicar el dato 0x40 en dicho registro.
Pero hay que tener en cuenta que el registro de PPS no tiene prioridad sobre otros registros como por ejemplos TRIS... De esta manera nuestro pin tiene que estar correctamente configurado como entrada digital.
Uno podría pensar que el remapeo solo implica el cambio de un registro para que funcione, pero como esto puede hacerse en tiempo de ejecución, este simple hecho puede causar que nuestro micro se estrelle como en caída libre y termine en la hecatombe total. Por esta razón las PPS se encuentran bloqueadas por hardware normalmente y existen codigos de bloqueos y desbloqueos de los PPS. Existen ademas registros transparentes al usuario que monitorean por hardware el estado de estos registros de tal manera que si existen cambios no habilitados se resetea la cosa.
Como desbloqueamos?, tenemos que desbloquear el bits IOLOCK bit (OSCCON<6>) y borrarlo para permitir la escritura, para hacer eso necesitamos escribir una secuencia de codigos tal cual una caja de seguridad sobre OSCCON<7:0>.
la secuencia exacta sería:
1. escribir 0x46 sobre OSCCON<7:0>.
2. escribir 0x57 sobre OSCCON<7:0>.
3. borrar IOLOCK para desbloquear o setear para bloquear.
No hay mucho más por decir, solo que C30 nos facilita el trabajo con funciones integradas para el proceso anterior __builtin_write_OSCCONL(value), de esta manera y sin más chachará vemos el código para ligar INT1 a RP4 como
.h
#define desbloquearPPS __builtin_write_OSCCONL(OSCCON & 0xbf)
#define bloquearPPS __builtin_write_OSCCONL(OSCCON | 0x40)
//------------------------------------------------------------------
.c
.....
.....
AD1PCFGL=0xFFFF; //todas salidas digitales
TRISBbits.TRISB4=1; //RB4 como entrada
desbloquearPPS;
RPINR0=0b0000010000000000; //0000 0100 0000 0000 (0x40) ligamos interrupción externa INT1 a RP4->RB4 pin11
bloquearPPS;
// seteo de la interrupción externa INT1
INTCON2bits.INT1EP=1; //sucede cada flanco descendente
IPC5bits.INT1IP=7; // 111 máxima prioridad
IFS1bits.INT1IF=0; //reset flag de interrupción
IEC1bits.INT1IE=1; //interrupción habilitada
.....
.....
Queda ahora como futuro próximo poner en práctica un periférico de salida. Sinceramente me he quedado encantado con este detalle y creo que todas las familias deberían contener estas cosas que convierten a nuestros micros mucho más versatiles.
Saludos